Pull sound updates from Takashi Iwai: "At this time, it's an interesting mixture of changes for both old and new stuff. Majority of changes are about ASoC (lots of systematic changes for converting remove callbacks to void, and cleanups), while we got the fixes and the enhancements of very old PCI cards, too. Here are some highlights: ALSA/ASoC Core: - Continued effort of more ASoC core cleanups - Minor improvements for XRUN handling in indirect PCM helpers - Code refactoring of PCM core code ASoC: - Continued feature and simplification work on SOF, including addition of a no-DSP mode for bringup, HDA MLink and extensions to the IPC4 protocol - Hibernation support for CS35L45 - More DT binding conversions - Support for Cirrus Logic CS35L56, Freescale QMC, Maxim MAX98363, nVidia systems with MAX9809x and RT5631, Realtek RT712, Renesas R-Car Gen4, Rockchip RK3588 and TI TAS5733 ALSA: - Lots of works for legacy emu10k1 and ymfpci PCI drivers - PCM kselftest fixes and enhancements" * tag 'sound-6.4-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound: (586 commits) ALSA: emu10k1: use high-level I/O in set_filterQ() ALSA: emu10k1: use high-level I/O functions also during init ALSA: emu10k1: fix error handling in snd_audigy_i2c_volume_put() ALSA: emu10k1: don't stop DSP in _snd_emu10k1_{,audigy_}init_efx() ALSA: emu10k1: fix SNDRV_EMU10K1_IOCTL_SINGLE_STEP ALSA: emu10k1: skip Sound Blaster-specific hacks for E-MU cards ALSA: emu10k1: fixup DSP defines ALSA: emu10k1: pull in some register definitions from kX-project ALSA: emu10k1: remove some bogus defines ALSA: emu10k1: eliminate some unused defines ALSA: emu10k1: fix lineup of EMU_HANA_* defines ALSA: emu10k1: comment updates ALSA: emu10k1: fix snd_emu1010_fpga_read() input masking for rev2 cards ALSA: emu10k1: remove unused emu->pcm_playback_efx_substream field ALSA: emu10k1: remove unused `resume` parameter from snd_emu10k1_init() ALSA: emu10k1: minor optimizations ALSA: emu10k1: remove remaining cruft from snd_emu10k1_emu1010_init() ALSA: emu10k1: remove apparently pointless EMU_HANA_OPTION_CARDS reads ALSA: emu10k1: remove apparently pointless FPGA reads ALSA: emu10k1: stop doing weird things with HCFG in snd_emu10k1_emu1010_init() ...
Unified · Split
| @@ -0,0 +1,162 @@ | |||
| 1 | # SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) | ||
| 2 | %YAML 1.2 | ||
| 3 | --- | ||
| 4 | $id: http://devicetree.org/schemas/soc/fsl/cpm_qe/fsl,cpm1-scc-qmc.yaml# | ||
| 5 | $schema: http://devicetree.org/meta-schemas/core.yaml# | ||
| 6 | |||
| 7 | title: PowerQUICC CPM QUICC Multichannel Controller (QMC) | ||
| 8 | |||
| 9 | maintainers: | ||
| 10 | - Herve Codina <herve.codina@bootlin.com> | ||
| 11 | |||
| 12 | description: | ||
| 13 | The QMC (QUICC Multichannel Controller) emulates up to 64 channels within one | ||
| 14 | serial controller using the same TDM physical interface routed from TSA. | ||
| 15 | |||
| 16 | properties: | ||
| 17 | compatible: | ||
| 18 | items: | ||
| 19 | - enum: | ||
| 20 | - fsl,mpc885-scc-qmc | ||
| 21 | - fsl,mpc866-scc-qmc | ||
| 22 | - const: fsl,cpm1-scc-qmc | ||
| 23 | |||
| 24 | reg: | ||
| 25 | items: | ||
| 26 | - description: SCC (Serial communication controller) register base | ||
| 27 | - description: SCC parameter ram base | ||
| 28 | - description: Dual port ram base | ||
| 29 | |||
| 30 | reg-names: | ||
| 31 | items: | ||
| 32 | - const: scc_regs | ||
| 33 | - const: scc_pram | ||
| 34 | - const: dpram | ||
| 35 | |||
| 36 | interrupts: | ||
| 37 | maxItems: 1 | ||
| 38 | description: SCC interrupt line in the CPM interrupt controller | ||
| 39 | |||
| 40 | fsl,tsa-serial: | ||
| 41 | $ref: /schemas/types.yaml#/definitions/phandle-array | ||
| 42 | items: | ||
| 43 | - items: | ||
| 44 | - description: phandle to TSA node | ||
| 45 | - enum: [1, 2, 3] | ||
| 46 | description: | | ||
| 47 | TSA serial interface (dt-bindings/soc/cpm1-fsl,tsa.h defines these | ||
| 48 | values) | ||
| 49 | - 1: SCC2 | ||
| 50 | - 2: SCC3 | ||
| 51 | - 3: SCC4 | ||
| 52 | description: | ||
| 53 | Should be a phandle/number pair. The phandle to TSA node and the TSA | ||
| 54 | serial interface to use. | ||
| 55 | |||
| 56 | '#address-cells': | ||
| 57 | const: 1 | ||
| 58 | |||
| 59 | '#size-cells': | ||
| 60 | const: 0 | ||
| 61 | |||
| 62 | patternProperties: | ||
| 63 | '^channel@([0-9]|[1-5][0-9]|6[0-3])$': | ||
| 64 | description: | ||
| 65 | A channel managed by this controller | ||
| 66 | type: object | ||
| 67 | |||
| 68 | properties: | ||
| 69 | reg: | ||
| 70 | minimum: 0 | ||
| 71 | maximum: 63 | ||
| 72 | description: | ||
| 73 | The channel number | ||
| 74 | |||
| 75 | fsl,operational-mode: | ||
| 76 | $ref: /schemas/types.yaml#/definitions/string | ||
| 77 | enum: [transparent, hdlc] | ||
| 78 | default: transparent | ||
| 79 | description: | | ||
| 80 | The channel operational mode | ||
| 81 | - hdlc: The channel handles HDLC frames | ||
| 82 | - transparent: The channel handles raw data without any processing | ||
| 83 | |||
| 84 | fsl,reverse-data: | ||
| 85 | $ref: /schemas/types.yaml#/definitions/flag | ||
| 86 | description: | ||
| 87 | The bit order as seen on the channels is reversed, | ||
| 88 | transmitting/receiving the MSB of each octet first. | ||
| 89 | This flag is used only in 'transparent' mode. | ||
| 90 | |||
| 91 | fsl,tx-ts-mask: | ||
| 92 | $ref: /schemas/types.yaml#/definitions/uint64 | ||
| 93 | description: | ||
| 94 | Channel assigned Tx time-slots within the Tx time-slots routed by the | ||
| 95 | TSA to this cell. | ||
| 96 | |||
| 97 | fsl,rx-ts-mask: | ||
| 98 | $ref: /schemas/types.yaml#/definitions/uint64 | ||
| 99 | description: | ||
| 100 | Channel assigned Rx time-slots within the Rx time-slots routed by the | ||
| 101 | TSA to this cell. | ||
| 102 | |||
| 103 | required: | ||
| 104 | - reg | ||
| 105 | - fsl,tx-ts-mask | ||
| 106 | - fsl,rx-ts-mask | ||
| 107 | |||
| 108 | required: | ||
| 109 | - compatible | ||
| 110 | - reg | ||
| 111 | - reg-names | ||
| 112 | - interrupts | ||
| 113 | - fsl,tsa-serial | ||
| 114 | - '#address-cells' | ||
| 115 | - '#size-cells' | ||
| 116 | |||
| 117 | additionalProperties: false | ||
| 118 | |||
| 119 | examples: | ||
| 120 | - | | ||
| 121 | #include <dt-bindings/soc/cpm1-fsl,tsa.h> | ||
| 122 | |||
| 123 | qmc@a60 { | ||
| 124 | compatible = "fsl,mpc885-scc-qmc", "fsl,cpm1-scc-qmc"; | ||
| 125 | reg = <0xa60 0x20>, | ||
| 126 | <0x3f00 0xc0>, | ||
| 127 | <0x2000 0x1000>; | ||
| 128 | reg-names = "scc_regs", "scc_pram", "dpram"; | ||
| 129 | interrupts = <27>; | ||
| 130 | interrupt-parent = <&CPM_PIC>; | ||
| 131 | |||
| 132 | #address-cells = <1>; | ||
| 133 | #size-cells = <0>; | ||
| 134 | |||
| 135 | fsl,tsa-serial = <&tsa FSL_CPM_TSA_SCC4>; | ||
| 136 | |||
| 137 | channel@16 { | ||
| 138 | /* Ch16 : First 4 even TS from all routed from TSA */ | ||
| 139 | reg = <16>; | ||
| 140 | fsl,mode = "transparent"; | ||
| 141 | fsl,reverse-data; | ||
| 142 | fsl,tx-ts-mask = <0x00000000 0x000000aa>; | ||
| 143 | fsl,rx-ts-mask = <0x00000000 0x000000aa>; | ||
| 144 | }; | ||
| 145 | |||
| 146 | channel@17 { | ||
| 147 | /* Ch17 : First 4 odd TS from all routed from TSA */ | ||
| 148 | reg = <17>; | ||
| 149 | fsl,mode = "transparent"; | ||
| 150 | fsl,reverse-data; | ||
| 151 | fsl,tx-ts-mask = <0x00000000 0x00000055>; | ||
| 152 | fsl,rx-ts-mask = <0x00000000 0x00000055>; | ||
| 153 | }; | ||
| 154 | |||
| 155 | channel@19 { | ||
| 156 | /* Ch19 : 8 TS (TS 8..15) from all routed from TSA */ | ||
| 157 | reg = <19>; | ||
| 158 | fsl,mode = "hdlc"; | ||
| 159 | fsl,tx-ts-mask = <0x00000000 0x0000ff00>; | ||
| 160 | fsl,rx-ts-mask = <0x00000000 0x0000ff00>; | ||
| 161 | }; | ||
| 162 | }; | ||
| @@ -0,0 +1,205 @@ | |||
| 1 | # SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) | ||
| 2 | %YAML 1.2 | ||
| 3 | --- | ||
| 4 | $id: http://devicetree.org/schemas/soc/fsl/cpm_qe/fsl,cpm1-tsa.yaml# | ||
| 5 | $schema: http://devicetree.org/meta-schemas/core.yaml# | ||
| 6 | |||
| 7 | title: PowerQUICC CPM Time-slot assigner (TSA) controller | ||
| 8 | |||
| 9 | maintainers: | ||
| 10 | - Herve Codina <herve.codina@bootlin.com> | ||
| 11 | |||
| 12 | description: | ||
| 13 | The TSA is the time-slot assigner that can be found on some PowerQUICC SoC. | ||
| 14 | Its purpose is to route some TDM time-slots to other internal serial | ||
| 15 | controllers. | ||
| 16 | |||
| 17 | properties: | ||
| 18 | compatible: | ||
| 19 | items: | ||
| 20 | - enum: | ||
| 21 | - fsl,mpc885-tsa | ||
| 22 | - fsl,mpc866-tsa | ||
| 23 | - const: fsl,cpm1-tsa | ||
| 24 | |||
| 25 | reg: | ||
| 26 | items: | ||
| 27 | - description: SI (Serial Interface) register base | ||
| 28 | - description: SI RAM base | ||
| 29 | |||
| 30 | reg-names: | ||
| 31 | items: | ||
| 32 | - const: si_regs | ||
| 33 | - const: si_ram | ||
| 34 | |||
| 35 | '#address-cells': | ||
| 36 | const: 1 | ||
| 37 | |||
| 38 | '#size-cells': | ||
| 39 | const: 0 | ||
| 40 | |||
| 41 | patternProperties: | ||
| 42 | '^tdm@[0-1]$': | ||
| 43 | description: | ||
| 44 | The TDM managed by this controller | ||
| 45 | type: object | ||
| 46 | |||
| 47 | additionalProperties: false | ||
| 48 | |||
| 49 | properties: | ||
| 50 | reg: | ||
| 51 | minimum: 0 | ||
| 52 | maximum: 1 | ||
| 53 | description: | ||
| 54 | The TDM number for this TDM, 0 for TDMa and 1 for TDMb | ||
| 55 | |||
| 56 | fsl,common-rxtx-pins: | ||
| 57 | $ref: /schemas/types.yaml#/definitions/flag | ||
| 58 | description: | ||
| 59 | The hardware can use four dedicated pins for Tx clock, Tx sync, Rx | ||
| 60 | clock and Rx sync or use only two pins, Tx/Rx clock and Tx/Rx sync. | ||
| 61 | Without the 'fsl,common-rxtx-pins' property, the four pins are used. | ||
| 62 | With the 'fsl,common-rxtx-pins' property, two pins are used. | ||
| 63 | |||
| 64 | clocks: | ||
| 65 | minItems: 2 | ||
| 66 | items: | ||
| 67 | - description: External clock connected to L1RSYNC pin | ||
| 68 | - description: External clock connected to L1RCLK pin | ||
| 69 | - description: External clock connected to L1TSYNC pin | ||
| 70 | - description: External clock connected to L1TCLK pin | ||
| 71 | |||
| 72 | clock-names: | ||
| 73 | minItems: 2 | ||
| 74 | items: | ||
| 75 | - const: l1rsync | ||
| 76 | - const: l1rclk | ||
| 77 | - const: l1tsync | ||
| 78 | - const: l1tclk | ||
| 79 | |||
| 80 | fsl,rx-frame-sync-delay-bits: | ||
| 81 | enum: [0, 1, 2, 3] | ||
| 82 | default: 0 | ||
| 83 | description: | | ||
| 84 | Receive frame sync delay in number of bits. | ||
| 85 | Indicates the delay between the Rx sync and the first bit of the Rx | ||
| 86 | frame. 0 for no bit delay. 1, 2 or 3 for 1, 2 or 3 bits delay. | ||
| 87 | |||
| 88 | fsl,tx-frame-sync-delay-bits: | ||
| 89 | enum: [0, 1, 2, 3] | ||
| 90 | default: 0 | ||
| 91 | description: | | ||
| 92 | Transmit frame sync delay in number of bits. | ||
| 93 | Indicates the delay between the Tx sync and the first bit of the Tx | ||
| 94 | frame. 0 for no bit delay. 1, 2 or 3 for 1, 2 or 3 bits delay. | ||
| 95 | |||
| 96 | fsl,clock-falling-edge: | ||
| 97 | $ref: /schemas/types.yaml#/definitions/flag | ||
| 98 | description: | ||
| 99 | Data is sent on falling edge of the clock (and received on the rising | ||
| 100 | edge). If 'clock-falling-edge' is not present, data is sent on the | ||
| 101 | rising edge (and received on the falling edge). | ||
| 102 | |||
| 103 | fsl,fsync-rising-edge: | ||
| 104 | $ref: /schemas/types.yaml#/definitions/flag | ||
| 105 | description: | ||
| 106 | Frame sync pulses are sampled with the rising edge of the channel | ||
| 107 | clock. If 'fsync-rising-edge' is not present, pulses are sampled with | ||
| 108 | the falling edge. | ||
| 109 | |||
| 110 | fsl,double-speed-clock: | ||
| 111 | $ref: /schemas/types.yaml#/definitions/flag | ||
| 112 | description: | ||
| 113 | The channel clock is twice the data rate. | ||
| 114 | |||
| 115 | patternProperties: | ||
| 116 | '^fsl,[rt]x-ts-routes$': | ||
| 117 | $ref: /schemas/types.yaml#/definitions/uint32-matrix | ||
| 118 | description: | | ||
| 119 | A list of tuple that indicates the Tx or Rx time-slots routes. | ||
| 120 | items: | ||
| 121 | items: | ||
| 122 | - description: | ||
| 123 | The number of time-slots | ||
| 124 | minimum: 1 | ||
| 125 | maximum: 64 | ||
| 126 | - description: | | ||
| 127 | The source (Tx) or destination (Rx) serial interface | ||
| 128 | (dt-bindings/soc/cpm1-fsl,tsa.h defines these values) | ||
| 129 | - 0: No destination | ||
| 130 | - 1: SCC2 | ||
| 131 | - 2: SCC3 | ||
| 132 | - 3: SCC4 | ||
| 133 | - 4: SMC1 | ||
| 134 | - 5: SMC2 | ||
| 135 | enum: [0, 1, 2, 3, 4, 5] | ||
| 136 | minItems: 1 | ||
| 137 | maxItems: 64 | ||
| 138 | |||
| 139 | allOf: | ||
| 140 | # If fsl,common-rxtx-pins is present, only 2 clocks are needed. | ||
| 141 | # Else, the 4 clocks must be present. | ||
| 142 | - if: | ||
| 143 | required: | ||
| 144 | - fsl,common-rxtx-pins | ||
| 145 | then: | ||
| 146 | properties: | ||
| 147 | clocks: | ||
| 148 | maxItems: 2 | ||
| 149 | clock-names: | ||
| 150 | maxItems: 2 | ||
| 151 | else: | ||
| 152 | properties: | ||
| 153 | clocks: | ||
| 154 | minItems: 4 | ||
| 155 | clock-names: | ||
| 156 | minItems: 4 | ||
| 157 | |||
| 158 | required: | ||
| 159 | - reg | ||
| 160 | - clocks | ||
| 161 | - clock-names | ||
| 162 | |||
| 163 | required: | ||
| 164 | - compatible | ||
| 165 | - reg | ||
| 166 | - reg-names | ||
| 167 | - '#address-cells' | ||
| 168 | - '#size-cells' | ||
| 169 | |||
| 170 | additionalProperties: false | ||
| 171 | |||
| 172 | examples: | ||
| 173 | - | | ||
| 174 | #include <dt-bindings/soc/cpm1-fsl,tsa.h> | ||
| 175 | |||
| 176 | tsa@ae0 { | ||
| 177 | compatible = "fsl,mpc885-tsa", "fsl,cpm1-tsa"; | ||
| 178 | reg = <0xae0 0x10>, | ||
| 179 | <0xc00 0x200>; | ||
| 180 | reg-names = "si_regs", "si_ram"; | ||
| 181 | |||
| 182 | #address-cells = <1>; | ||
| 183 | #size-cells = <0>; | ||
| 184 | |||
| 185 | tdm@0 { | ||
| 186 | /* TDMa */ | ||
| 187 | reg = <0>; | ||
| 188 | |||
| 189 | clocks = <&clk_l1rsynca>, <&clk_l1rclka>; | ||
| 190 | clock-names = "l1rsync", "l1rclk"; | ||
| 191 | |||
| 192 | fsl,common-rxtx-pins; | ||
| 193 | fsl,fsync-rising-edge; | ||
| 194 | |||
| 195 | fsl,tx-ts-routes = <2 0>, /* TS 0..1 */ | ||
| 196 | <24 FSL_CPM_TSA_SCC4>, /* TS 2..25 */ | ||
| 197 | <1 0>, /* TS 26 */ | ||
| 198 | <5 FSL_CPM_TSA_SCC3>; /* TS 27..31 */ | ||
| 199 | |||
| 200 | fsl,rx-ts-routes = <2 0>, /* TS 0..1 */ | ||
| 201 | <24 FSL_CPM_TSA_SCC4>, /* 2..25 */ | ||
| 202 | <1 0>, /* TS 26 */ | ||
| 203 | <5 FSL_CPM_TSA_SCC3>; /* TS 27..31 */ | ||
| 204 | }; | ||
| 205 | }; | ||
| @@ -32,7 +32,7 @@ properties: · 31 unmodified lines | |||
| 32 | maxItems: 1 | 32 | maxItems: 1 |
| 33 | 33 | ||
| 34 | clock-names: | 34 | clock-names: |
| 35 | const: "mclk" | 35 | const: mclk |
| 36 | 36 | ||
| 37 | powerdown-gpios: | 37 | powerdown-gpios: |
| 38 | description: GPIO used for hardware power-down. | 38 | description: GPIO used for hardware power-down. |
| @@ -1,32 +0,0 @@ | |||
| 1 | Analog Devices ADAU1361/ADAU1461/ADAU1761/ADAU1961/ADAU1381/ADAU1781 | ||
| 2 | |||
| 3 | Required properties: | ||
| 4 | |||
| 5 | - compatible: Should contain one of the following: | ||
| 6 | "adi,adau1361" | ||
| 7 | "adi,adau1461" | ||
| 8 | "adi,adau1761" | ||
| 9 | "adi,adau1961" | ||
| 10 | "adi,adau1381" | ||
| 11 | "adi,adau1781" | ||
| 12 | |||
| 13 | - reg: The i2c address. Value depends on the state of ADDR0 | ||
| 14 | and ADDR1, as wired in hardware. | ||
| 15 | |||
| 16 | Optional properties: | ||
| 17 | - clock-names: If provided must be "mclk". | ||
| 18 | - clocks: phandle + clock-specifiers for the clock that provides | ||
| 19 | the audio master clock for the device. | ||
| 20 | |||
| 21 | Examples: | ||
| 22 | #include <dt-bindings/sound/adau17x1.h> | ||
| 23 | |||
| 24 | i2c_bus { | ||
| 25 | adau1361@38 { | ||
| 26 | compatible = "adi,adau1761"; | ||
| 27 | reg = <0x38>; | ||
| 28 | |||
| 29 | clock-names = "mclk"; | ||
| 30 | clocks = <&audio_clock>; | ||
| 31 | }; | ||
| 32 | }; | ||
| @@ -0,0 +1,52 @@ | |||
| 1 | # SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) | ||
| 2 | %YAML 1.2 | ||
| 3 | --- | ||
| 4 | $id: http://devicetree.org/schemas/sound/adi,adau17x1.yaml# | ||
| 5 | $schema: http://devicetree.org/meta-schemas/core.yaml# | ||
| 6 | |||
| 7 | title: Analog Devices ADAU1361/ADAU1461/ADAU1761/ADAU1961/ADAU1381/ADAU1781 Codec | ||
| 8 | |||
| 9 | maintainers: | ||
| 10 | - Lars-Peter Clausen <lars@metafoo.de> | ||
| 11 | |||
| 12 | properties: | ||
| 13 | compatible: | ||
| 14 | enum: | ||
| 15 | - adi,adau1361 | ||
| 16 | - adi,adau1381 | ||
| 17 | - adi,adau1461 | ||
| 18 | - adi,adau1761 | ||
| 19 | - adi,adau1781 | ||
| 20 | - adi,adau1961 | ||
| 21 | |||
| 22 | reg: | ||
| 23 | maxItems: 1 | ||
| 24 | description: | ||
| 25 | The i2c address. Value depends on the state of ADDR0 and ADDR1, | ||
| 26 | as wired in hardware. | ||
| 27 | |||
| 28 | clock-names: | ||
| 29 | const: mclk | ||
| 30 | |||
| 31 | clocks: | ||
| 32 | items: | ||
| 33 | - description: provides the audio master clock for the device. | ||
| 34 | |||
| 35 | required: | ||
| 36 | - compatible | ||
| 37 | - reg | ||
| 38 | |||
| 39 | additionalProperties: false | ||
| 40 | |||
| 41 | examples: | ||
| 42 | - | | ||
| 43 | i2c { | ||
| 44 | #address-cells = <1>; | ||
| 45 | #size-cells = <0>; | ||
| 46 | audio-codec@38 { | ||
| 47 | compatible = "adi,adau1761"; | ||
| 48 | reg = <0x38>; | ||
| 49 | clock-names = "mclk"; | ||
| 50 | clocks = <&audio_clock>; | ||
| 51 | }; | ||
| 52 | }; | ||
| @@ -0,0 +1,60 @@ | |||
| 1 | # SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) | ||
| 2 | %YAML 1.2 | ||
| 3 | --- | ||
| 4 | $id: http://devicetree.org/schemas/sound/adi,max98363.yaml# | ||
| 5 | $schema: http://devicetree.org/meta-schemas/core.yaml# | ||
| 6 | |||
| 7 | title: Analog Devices MAX98363 SoundWire Amplifier | ||
| 8 | |||
| 9 | maintainers: | ||
| 10 | - Ryan Lee <ryans.lee@analog.com> | ||
| 11 | |||
| 12 | description: | ||
| 13 | The MAX98363 is a SoundWire input Class D mono amplifier that | ||
| 14 | supports MIPI SoundWire v1.2-compatible digital interface for | ||
| 15 | audio and control data. | ||
| 16 | SoundWire peripheral device ID of MAX98363 is 0x3*019f836300 | ||
| 17 | where * is the peripheral device unique ID decoded from pin. | ||
| 18 | It supports up to 10 peripheral devices(0x0 to 0x9). | ||
| 19 | |||
| 20 | allOf: | ||
| 21 | - $ref: dai-common.yaml# | ||
| 22 | |||
| 23 | properties: | ||
| 24 | compatible: | ||
| 25 | const: sdw3019f836300 | ||
| 26 | |||
| 27 | reg: | ||
| 28 | maxItems: 1 | ||
| 29 | |||
| 30 | '#sound-dai-cells': | ||
| 31 | const: 0 | ||
| 32 | |||
| 33 | required: | ||
| 34 | - compatible | ||
| 35 | - reg | ||
| 36 | - "#sound-dai-cells" | ||
| 37 | |||
| 38 | unevaluatedProperties: false | ||
| 39 | |||
| 40 | examples: | ||
| 41 | - | | ||
| 42 | soundwire-controller@3250000 { | ||
| 43 | #address-cells = <2>; | ||
| 44 | #size-cells = <0>; | ||
| 45 | reg = <0x3250000 0x2000>; | ||
| 46 | |||
| 47 | speaker@0,0 { | ||
| 48 | compatible = "sdw3019f836300"; | ||
| 49 | reg = <0 0>; | ||
| 50 | #sound-dai-cells = <0>; | ||
| 51 | sound-name-prefix = "Speaker Left"; | ||
| 52 | }; | ||
| 53 | |||
| 54 | speaker@0,1 { | ||
| 55 | compatible = "sdw3019f836300"; | ||
| 56 | reg = <0 1>; | ||
| 57 | #sound-dai-cells = <0>; | ||
| 58 | sound-name-prefix = "Speaker Right"; | ||
| 59 | }; | ||
| 60 | }; | ||
| @@ -41,21 +41,21 @@ properties: · 40 unmodified lines | |||
| 41 | 41 | ||
| 42 | adi,vmon-slot-no: | 42 | adi,vmon-slot-no: |
| 43 | description: slot number of the voltage sense monitor | 43 | description: slot number of the voltage sense monitor |
| 44 | $ref: "/schemas/types.yaml#/definitions/uint32" | 44 | $ref: /schemas/types.yaml#/definitions/uint32 |
| 45 | minimum: 0 | 45 | minimum: 0 |
| 46 | maximum: 15 | 46 | maximum: 15 |
| 47 | default: 0 | 47 | default: 0 |
| 48 | 48 | ||
| 49 | adi,imon-slot-no: | 49 | adi,imon-slot-no: |
| 50 | description: slot number of the current sense monitor | 50 | description: slot number of the current sense monitor |
| 51 | $ref: "/schemas/types.yaml#/definitions/uint32" | 51 | $ref: /schemas/types.yaml#/definitions/uint32 |
| 52 | minimum: 0 | 52 | minimum: 0 |
| 53 | maximum: 15 | 53 | maximum: 15 |
| 54 | default: 1 | 54 | default: 1 |
| 55 | 55 | ||
| 56 | adi,spkfb-slot-no: | 56 | adi,spkfb-slot-no: |
| 57 | description: slot number of speaker DSP monitor | 57 | description: slot number of speaker DSP monitor |
| 58 | $ref: "/schemas/types.yaml#/definitions/uint32" | 58 | $ref: /schemas/types.yaml#/definitions/uint32 |
| 59 | minimum: 0 | 59 | minimum: 0 |
| 60 | maximum: 15 | 60 | maximum: 15 |
| 61 | default: 2 | 61 | default: 2 |
| @@ -64,7 +64,7 @@ properties: · 2 unmodified lines | |||
| 64 | description: | 64 | description: |
| 65 | Selects the PCM data input channel that is routed to the speaker | 65 | Selects the PCM data input channel that is routed to the speaker |
| 66 | audio processing bypass path. | 66 | audio processing bypass path. |
| 67 | $ref: "/schemas/types.yaml#/definitions/uint32" | 67 | $ref: /schemas/types.yaml#/definitions/uint32 |
| 68 | minimum: 0 | 68 | minimum: 0 |
| 69 | maximum: 15 | 69 | maximum: 15 |
| 70 | default: 0 | 70 | default: 0 |
| @@ -1,28 +0,0 @@ | |||
| 1 | AK4458 audio DAC | ||
| 2 | |||
| 3 | This device supports I2C mode. | ||
| 4 | |||
| 5 | Required properties: | ||
| 6 | |||
| 7 | - compatible : "asahi-kasei,ak4458" or "asahi-kasei,ak4497" | ||
| 8 | - reg : The I2C address of the device for I2C | ||
| 9 | |||
| 10 | Optional properties: | ||
| 11 | - reset-gpios: A GPIO specifier for the power down & reset pin | ||
| 12 | - mute-gpios: A GPIO specifier for the soft mute pin | ||
| 13 | - AVDD-supply: Analog power supply | ||
| 14 | - DVDD-supply: Digital power supply | ||
| 15 | - dsd-path: Select DSD input pins for ak4497 | ||
| 16 | 0: select #16, #17, #19 pins | ||
| 17 | 1: select #3, #4, #5 pins | ||
| 18 | |||
| 19 | Example: | ||
| 20 | |||
| 21 | &i2c { | ||
| 22 | ak4458: dac@10 { | ||
| 23 | compatible = "asahi-kasei,ak4458"; | ||
| 24 | reg = <0x10>; | ||
| 25 | reset-gpios = <&gpio1 10 GPIO_ACTIVE_LOW> | ||
| 26 | mute-gpios = <&gpio1 11 GPIO_ACTIVE_HIGH> | ||
| 27 | }; | ||
| 28 | }; | ||
| @@ -1,24 +0,0 @@ | |||
| 1 | AK5558 8 channel differential 32-bit delta-sigma ADC | ||
| 2 | |||
| 3 | This device supports I2C mode only. | ||
| 4 | |||
| 5 | Required properties: | ||
| 6 | |||
| 7 | - compatible : "asahi-kasei,ak5558" or "asahi-kasei,ak5552". | ||
| 8 | - reg : The I2C address of the device. | ||
| 9 | |||
| 10 | Optional properties: | ||
| 11 | |||
| 12 | - reset-gpios: A GPIO specifier for the power down & reset pin. | ||
| 13 | - AVDD-supply: Analog power supply | ||
| 14 | - DVDD-supply: Digital power supply | ||
| 15 | |||
| 16 | Example: | ||
| 17 | |||
| 18 | &i2c { | ||
| 19 | ak5558: adc@10 { | ||
| 20 | compatible = "asahi-kasei,ak5558"; | ||
| 21 | reg = <0x10>; | ||
| 22 | reset-gpios = <&gpio1 10 GPIO_ACTIVE_LOW>; | ||
| 23 | }; | ||
| 24 | }; | ||
| @@ -1,43 +0,0 @@ | |||
| 1 | ALC5632 audio CODEC | ||
| 2 | |||
| 3 | This device supports I2C only. | ||
| 4 | |||
| 5 | Required properties: | ||
| 6 | |||
| 7 | - compatible : "realtek,alc5632" | ||
| 8 | |||
| 9 | - reg : the I2C address of the device. | ||
| 10 | |||
| 11 | - gpio-controller : Indicates this device is a GPIO controller. | ||
| 12 | |||
| 13 | - #gpio-cells : Should be two. The first cell is the pin number and the | ||
| 14 | second cell is used to specify optional parameters (currently unused). | ||
| 15 | |||
| 16 | Pins on the device (for linking into audio routes): | ||
| 17 | |||
| 18 | * SPK_OUTP | ||
| 19 | * SPK_OUTN | ||
| 20 | * HP_OUT_L | ||
| 21 | * HP_OUT_R | ||
| 22 | * AUX_OUT_P | ||
| 23 | * AUX_OUT_N | ||
| 24 | * LINE_IN_L | ||
| 25 | * LINE_IN_R | ||
| 26 | * PHONE_P | ||
| 27 | * PHONE_N | ||
| 28 | * MIC1_P | ||
| 29 | * MIC1_N | ||
| 30 | * MIC2_P | ||
| 31 | * MIC2_N | ||
| 32 | * MICBIAS1 | ||
| 33 | * DMICDAT | ||
| 34 | |||
| 35 | Example: | ||
| 36 | |||
| 37 | alc5632: alc5632@1e { | ||
| 38 | compatible = "realtek,alc5632"; | ||
| 39 | reg = <0x1a>; | ||
| 40 | |||
| 41 | gpio-controller; | ||
| 42 | #gpio-cells = <2>; | ||
| 43 | }; | ||
| @@ -0,0 +1,73 @@ | |||
| 1 | # SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause | ||
| 2 | %YAML 1.2 | ||
| 3 | --- | ||
| 4 | $id: http://devicetree.org/schemas/sound/asahi-kasei,ak4458.yaml# | ||
| 5 | $schema: http://devicetree.org/meta-schemas/core.yaml# | ||
| 6 | |||
| 7 | title: AK4458 audio DAC | ||
| 8 | |||
| 9 | maintainers: | ||
| 10 | - Shengjiu Wang <shengjiu.wang@nxp.com> | ||
| 11 | |||
| 12 | properties: | ||
| 13 | compatible: | ||
| 14 | enum: | ||
| 15 | - asahi-kasei,ak4458 | ||
| 16 | - asahi-kasei,ak4497 | ||
| 17 | |||
| 18 | reg: | ||
| 19 | maxItems: 1 | ||
| 20 | |||
| 21 | avdd-supply: | ||
| 22 | description: Analog power supply | ||
| 23 | |||
| 24 | dvdd-supply: | ||
| 25 | description: Digital power supply | ||
| 26 | |||
| 27 | reset-gpios: | ||
| 28 | maxItems: 1 | ||
| 29 | |||
| 30 | mute-gpios: | ||
| 31 | maxItems: 1 | ||
| 32 | description: | ||
| 33 | GPIO used to mute all the outputs | ||
| 34 | |||
| 35 | dsd-path: | ||
| 36 | description: Select DSD input pins for ak4497 | ||
| 37 | $ref: /schemas/types.yaml#/definitions/uint32 | ||
| 38 | oneOf: | ||
| 39 | - const: 0 | ||
| 40 | description: "select #16, #17, #19 pins" | ||
| 41 | - const: 1 | ||
| 42 | description: "select #3, #4, #5 pins" | ||
| 43 | |||
| 44 | required: | ||
| 45 | - compatible | ||
| 46 | - reg | ||
| 47 | |||
| 48 | allOf: | ||
| 49 | - if: | ||
| 50 | properties: | ||
| 51 | compatible: | ||
| 52 | contains: | ||
| 53 | const: asahi-kasei,ak4458 | ||
| 54 | |||
| 55 | then: | ||
| 56 | properties: | ||
| 57 | dsd-path: false | ||
| 58 | |||
| 59 | additionalProperties: false | ||
| 60 | |||
| 61 | examples: | ||
| 62 | - | | ||
| 63 | #include <dt-bindings/gpio/gpio.h> | ||
| 64 | i2c { | ||
| 65 | #address-cells = <1>; | ||
| 66 | #size-cells = <0>; | ||
| 67 | codec@10 { | ||
| 68 | compatible = "asahi-kasei,ak4458"; | ||
| 69 | reg = <0x10>; | ||
| 70 | reset-gpios = <&gpio1 10 GPIO_ACTIVE_LOW>; | ||
| 71 | mute-gpios = <&gpio1 11 GPIO_ACTIVE_HIGH>; | ||
| 72 | }; | ||
| 73 | }; | ||
| @@ -0,0 +1,48 @@ | |||
| 1 | # SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause | ||
| 2 | %YAML 1.2 | ||
| 3 | --- | ||
| 4 | $id: http://devicetree.org/schemas/sound/asahi-kasei,ak5558.yaml# | ||
| 5 | $schema: http://devicetree.org/meta-schemas/core.yaml# | ||
| 6 | |||
| 7 | title: AK5558 8 channel differential 32-bit delta-sigma ADC | ||
| 8 | |||
| 9 | maintainers: | ||
| 10 | - Junichi Wakasugi <wakasugi.jb@om.asahi-kasei.co.jp> | ||
| 11 | - Mihai Serban <mihai.serban@nxp.com> | ||
| 12 | |||
| 13 | properties: | ||
| 14 | compatible: | ||
| 15 | enum: | ||
| 16 | - asahi-kasei,ak5552 | ||
| 17 | - asahi-kasei,ak5558 | ||
| 18 | |||
| 19 | reg: | ||
| 20 | maxItems: 1 | ||
| 21 | |||
| 22 | avdd-supply: | ||
| 23 | description: A 1.8V supply that powers up the AVDD pin. | ||
| 24 | |||
| 25 | dvdd-supply: | ||
| 26 | description: A 1.2V supply that powers up the DVDD pin. | ||
| 27 | |||
| 28 | reset-gpios: | ||
| 29 | maxItems: 1 | ||
| 30 | |||
| 31 | required: | ||
| 32 | - compatible | ||
| 33 | - reg | ||
| 34 | |||
| 35 | additionalProperties: false | ||
| 36 | |||
| 37 | examples: | ||
| 38 | - | | ||
| 39 | #include <dt-bindings/gpio/gpio.h> | ||
| 40 | i2c { | ||
| 41 | #address-cells = <1>; | ||
| 42 | #size-cells = <0>; | ||
| 43 | ak5558: codec@10 { | ||
| 44 | compatible = "asahi-kasei,ak5558"; | ||
| 45 | reg = <0x10>; | ||
| 46 | reset-gpios = <&gpio1 10 GPIO_ACTIVE_LOW>; | ||
| 47 | }; | ||
| 48 | }; | ||
| @@ -16,19 +16,19 @@ definitions: · 15 unmodified lines | |||
| 16 | $ref: /schemas/graph.yaml#/$defs/port-base | 16 | $ref: /schemas/graph.yaml#/$defs/port-base |
| 17 | properties: | 17 | properties: |
| 18 | convert-rate: | 18 | convert-rate: |
| 19 | $ref: "/schemas/sound/dai-params.yaml#/$defs/dai-sample-rate" | 19 | $ref: /schemas/sound/dai-params.yaml#/$defs/dai-sample-rate |
| 20 | convert-channels: | 20 | convert-channels: |
| 21 | $ref: "/schemas/sound/dai-params.yaml#/$defs/dai-channels" | 21 | $ref: /schemas/sound/dai-params.yaml#/$defs/dai-channels |
| 22 | convert-sample-format: | 22 | convert-sample-format: |
| 23 | $ref: "/schemas/sound/dai-params.yaml#/$defs/dai-sample-format" | 23 | $ref: /schemas/sound/dai-params.yaml#/$defs/dai-sample-format |
| 24 | mclk-fs: | 24 | mclk-fs: |
| 25 | $ref: "simple-card.yaml#/definitions/mclk-fs" | 25 | $ref: simple-card.yaml#/definitions/mclk-fs |
| 26 | 26 | ||
| 27 | endpoint-base: | 27 | endpoint-base: |
| 28 | $ref: /schemas/graph.yaml#/$defs/endpoint-base | 28 | $ref: /schemas/graph.yaml#/$defs/endpoint-base |
| 29 | properties: | 29 | properties: |
| 30 | mclk-fs: | 30 | mclk-fs: |
| 31 | $ref: "simple-card.yaml#/definitions/mclk-fs" | 31 | $ref: simple-card.yaml#/definitions/mclk-fs |
| 32 | frame-inversion: | 32 | frame-inversion: |
| 33 | description: dai-link uses frame clock inversion | 33 | description: dai-link uses frame clock inversion |
| 34 | $ref: /schemas/types.yaml#/definitions/flag | 34 | $ref: /schemas/types.yaml#/definitions/flag |
| @@ -49,11 +49,11 @@ definitions: · 14 unmodified lines | |||
| 49 | description: Indicates system clock | 49 | description: Indicates system clock |
| 50 | $ref: /schemas/types.yaml#/definitions/phandle | 50 | $ref: /schemas/types.yaml#/definitions/phandle |
| 51 | system-clock-frequency: | 51 | system-clock-frequency: |
| 52 | $ref: "simple-card.yaml#/definitions/system-clock-frequency" | 52 | $ref: simple-card.yaml#/definitions/system-clock-frequency |
| 53 | system-clock-direction-out: | 53 | system-clock-direction-out: |
| 54 | $ref: "simple-card.yaml#/definitions/system-clock-direction-out" | 54 | $ref: simple-card.yaml#/definitions/system-clock-direction-out |
| 55 | system-clock-fixed: | 55 | system-clock-fixed: |
| 56 | $ref: "simple-card.yaml#/definitions/system-clock-fixed" | 56 | $ref: simple-card.yaml#/definitions/system-clock-fixed |
| 57 | 57 | ||
| 58 | dai-format: | 58 | dai-format: |
| 59 | description: audio format. | 59 | description: audio format. |
| @@ -69,11 +69,11 @@ definitions: · 9 unmodified lines | |||
| 69 | - msb | 69 | - msb |
| 70 | - lsb | 70 | - lsb |
| 71 | convert-rate: | 71 | convert-rate: |
| 72 | $ref: "/schemas/sound/dai-params.yaml#/$defs/dai-sample-rate" | 72 | $ref: /schemas/sound/dai-params.yaml#/$defs/dai-sample-rate |
| 73 | convert-channels: | 73 | convert-channels: |
| 74 | $ref: "/schemas/sound/dai-params.yaml#/$defs/dai-channels" | 74 | $ref: /schemas/sound/dai-params.yaml#/$defs/dai-channels |
| 75 | convert-sample-format: | 75 | convert-sample-format: |
| 76 | $ref: "/schemas/sound/dai-params.yaml#/$defs/dai-sample-format" | 76 | $ref: /schemas/sound/dai-params.yaml#/$defs/dai-sample-format |
| 77 | 77 | ||
| 78 | dai-tdm-slot-num: | 78 | dai-tdm-slot-num: |
| 79 | description: Number of slots in use. | 79 | description: Number of slots in use. |
| @@ -15,7 +15,7 @@ properties: · 14 unmodified lines | |||
| 15 | label: | 15 | label: |
| 16 | maxItems: 1 | 16 | maxItems: 1 |
| 17 | prefix: | 17 | prefix: |
| 18 | description: "device name prefix" | 18 | description: device name prefix |
| 19 | $ref: /schemas/types.yaml#/definitions/string | 19 | $ref: /schemas/types.yaml#/definitions/string |
| 20 | routing: | 20 | routing: |
| 21 | description: | | 21 | description: | |
| @@ -27,11 +27,11 @@ properties: · 5 unmodified lines | |||
| 27 | description: User specified audio sound widgets. | 27 | description: User specified audio sound widgets. |
| 28 | $ref: /schemas/types.yaml#/definitions/non-unique-string-array | 28 | $ref: /schemas/types.yaml#/definitions/non-unique-string-array |
| 29 | convert-rate: | 29 | convert-rate: |
| 30 | $ref: "/schemas/sound/dai-params.yaml#/$defs/dai-sample-rate" | 30 | $ref: /schemas/sound/dai-params.yaml#/$defs/dai-sample-rate |
| 31 | convert-channels: | 31 | convert-channels: |
| 32 | $ref: "/schemas/sound/dai-params.yaml#/$defs/dai-channels" | 32 | $ref: /schemas/sound/dai-params.yaml#/$defs/dai-channels |
| 33 | convert-sample-format: | 33 | convert-sample-format: |
| 34 | $ref: "/schemas/sound/dai-params.yaml#/$defs/dai-sample-format" | 34 | $ref: /schemas/sound/dai-params.yaml#/$defs/dai-sample-format |
| 35 | 35 | ||
| 36 | pa-gpios: | 36 | pa-gpios: |
| 37 | maxItems: 1 | 37 | maxItems: 1 |
| @@ -85,11 +85,19 @@ properties: · 84 unmodified lines | |||
| 85 | boost-cap-microfarad. | 85 | boost-cap-microfarad. |
| 86 | External Boost must have GPIO1 as GPIO output. GPIO1 will be set high to | 86 | External Boost must have GPIO1 as GPIO output. GPIO1 will be set high to |
| 87 | enable boost voltage. | 87 | enable boost voltage. |
| 88 | Shared boost allows two amplifiers to share a single boost circuit by | ||
| 89 | communicating on the MDSYNC bus. The active amplifier controls the boost | ||
| 90 | circuit using combined data from both amplifiers. GPIO1 should be | ||
| 91 | configured for Sync when shared boost is used. Shared boost is not | ||
| 92 | compatible with External boost. Active amplifier requires | ||
| 93 | boost-peak-milliamp, boost-ind-nanohenry and boost-cap-microfarad. | ||
| 88 | 0 = Internal Boost | 94 | 0 = Internal Boost |
| 89 | 1 = External Boost | 95 | 1 = External Boost |
| 96 | 2 = Shared Boost Active | ||
| 97 | 3 = Shared Boost Passive | ||
| 90 | $ref: /schemas/types.yaml#/definitions/uint32 | 98 | $ref: /schemas/types.yaml#/definitions/uint32 |
| 91 | minimum: 0 | 99 | minimum: 0 |
| 92 | maximum: 1 | 100 | maximum: 3 |
| 93 | 101 | ||
| 94 | cirrus,gpio1-polarity-invert: | 102 | cirrus,gpio1-polarity-invert: |
| 95 | description: | 103 | description: |
| @@ -45,11 +45,79 @@ properties: · 44 unmodified lines | |||
| 45 | Audio serial port SDOUT Hi-Z control. Sets the Hi-Z | 45 | Audio serial port SDOUT Hi-Z control. Sets the Hi-Z |
| 46 | configuration for SDOUT pin of amplifier. Logical OR of | 46 | configuration for SDOUT pin of amplifier. Logical OR of |
| 47 | CS35L45_ASP_TX_HIZ_xxx values. | 47 | CS35L45_ASP_TX_HIZ_xxx values. |
| 48 | $ref: "/schemas/types.yaml#/definitions/uint32" | 48 | $ref: /schemas/types.yaml#/definitions/uint32 |
| 49 | minimum: 0 | 49 | minimum: 0 |
| 50 | maximum: 3 | 50 | maximum: 3 |
| 51 | default: 2 | 51 | default: 2 |
| 52 | 52 | ||
| 53 | patternProperties: | ||
| 54 | "^cirrus,gpio-ctrl[1-3]$": | ||
| 55 | description: | ||
| 56 | GPIO pins configuration. | ||
| 57 | type: object | ||
| 58 | additionalProperties: false | ||
| 59 | properties: | ||
| 60 | gpio-dir: | ||
| 61 | description: | ||
| 62 | GPIO pin direction. Valid only when 'gpio-ctrl' is 1 | ||
| 63 | 0 = Output | ||
| 64 | 1 = Input | ||
| 65 | $ref: "/schemas/types.yaml#/definitions/uint32" | ||
| 66 | minimum: 0 | ||
| 67 | maximum: 1 | ||
| 68 | default: 1 | ||
| 69 | gpio-lvl: | ||
| 70 | description: | ||
| 71 | GPIO level. Valid only when 'gpio-ctrl' is 1 and 'gpio-dir' is 0 | ||
| 72 | 0 = Low | ||
| 73 | 1 = High | ||
| 74 | $ref: "/schemas/types.yaml#/definitions/uint32" | ||
| 75 | minimum: 0 | ||
| 76 | maximum: 1 | ||
| 77 | default: 0 | ||
| 78 | gpio-op-cfg: | ||
| 79 | description: | ||
| 80 | GPIO level. Valid only when 'gpio-ctrl' is 1 and 'gpio-dir' is 0 | ||
| 81 | 0 = CMOS | ||
| 82 | 1 = Open Drain | ||
| 83 | $ref: "/schemas/types.yaml#/definitions/uint32" | ||
| 84 | minimum: 0 | ||
| 85 | maximum: 1 | ||
| 86 | default: 0 | ||
| 87 | gpio-pol: | ||
| 88 | description: | ||
| 89 | GPIO output polarity select. Valid only when 'gpio-ctrl' is 1 | ||
| 90 | and 'gpio-dir' is 0 | ||
| 91 | 0 = Non-inverted, Active High | ||
| 92 | 1 = Inverted, Active Low | ||
| 93 | $ref: "/schemas/types.yaml#/definitions/uint32" | ||
| 94 | minimum: 0 | ||
| 95 | maximum: 1 | ||
| 96 | default: 0 | ||
| 97 | gpio-ctrl: | ||
| 98 | description: | ||
| 99 | Defines the function of the GPIO pin. | ||
| 100 | GPIO1 | ||
| 101 | 0 = High impedance input | ||
| 102 | 1 = Pin acts as a GPIO, direction controlled by 'gpio-dir' | ||
| 103 | 2 = Pin acts as MDSYNC, direction controlled by MDSYNC | ||
| 104 | 3-7 = Reserved | ||
| 105 | GPIO2 | ||
| 106 | 0 = High impedance input | ||
| 107 | 1 = Pin acts as a GPIO, direction controlled by 'gpio-dir' | ||
| 108 | 2 = Pin acts as open drain INT | ||
| 109 | 3 = Reserved | ||
| 110 | 4 = Pin acts as push-pull output INT. Active low. | ||
| 111 | 5 = Pin acts as push-pull output INT. Active high. | ||
| 112 | 6,7 = Reserved | ||
| 113 | GPIO3 | ||
| 114 | 0 = High impedance input | ||
| 115 | 1 = Pin acts as a GPIO, direction controlled by 'gpio-dir' | ||
| 116 | 2-7 = Reserved | ||
| 117 | $ref: "/schemas/types.yaml#/definitions/uint32" | ||
| 118 | minimum: 0 | ||
| 119 | maximum: 7 | ||
| 120 | default: 0 | ||
| 53 | required: | 121 | required: |
| 54 | - compatible | 122 | - compatible |
| 55 | - reg | 123 | - reg |
| @@ -74,5 +142,15 @@ examples: · 18 unmodified lines | |||
| 74 | reset-gpios = <&gpio 110 0>; | 142 | reset-gpios = <&gpio 110 0>; |
| 75 | cirrus,asp-sdout-hiz-ctrl = <(CS35L45_ASP_TX_HIZ_UNUSED | | 143 | cirrus,asp-sdout-hiz-ctrl = <(CS35L45_ASP_TX_HIZ_UNUSED | |
| 76 | CS35L45_ASP_TX_HIZ_DISABLED)>; | 144 | CS35L45_ASP_TX_HIZ_DISABLED)>; |
| 145 | cirrus,gpio-ctrl1 { | ||
| 146 | gpio-ctrl = <0x2>; | ||
| 147 | }; | ||
| 148 | cirrus,gpio-ctrl2 { | ||
| 149 | gpio-ctrl = <0x2>; | ||
| 150 | }; | ||
| 151 | cirrus,gpio-ctrl3 { | ||
| 152 | gpio-ctrl = <0x1>; | ||
| 153 | gpio-dir = <0x1>; | ||
| 154 | }; | ||
| 77 | }; | 155 | }; |
| 78 | }; | 156 | }; |
| @@ -68,7 +68,7 @@ properties: · 67 unmodified lines | |||
| 68 | This is "normal tip sense (TS)" in the datasheet. | 68 | This is "normal tip sense (TS)" in the datasheet. |
| 69 | 69 | ||
| 70 | The CS42L42_TS_INV_* defines are available for this. | 70 | The CS42L42_TS_INV_* defines are available for this. |
| 71 | $ref: "/schemas/types.yaml#/definitions/uint32" | 71 | $ref: /schemas/types.yaml#/definitions/uint32 |
| 72 | minimum: 0 | 72 | minimum: 0 |
| 73 | maximum: 1 | 73 | maximum: 1 |
| 74 | 74 | ||
| @@ -87,7 +87,7 @@ properties: · 12 unmodified lines | |||
| 87 | 7 - 1.5s | 87 | 7 - 1.5s |
| 88 | 88 | ||
| 89 | The CS42L42_TS_DBNCE_* defines are available for this. | 89 | The CS42L42_TS_DBNCE_* defines are available for this. |
| 90 | $ref: "/schemas/types.yaml#/definitions/uint32" | 90 | $ref: /schemas/types.yaml#/definitions/uint32 |
| 91 | minimum: 0 | 91 | minimum: 0 |
| 92 | maximum: 7 | 92 | maximum: 7 |
| 93 | 93 | ||
| @@ -106,7 +106,7 @@ properties: · 12 unmodified lines | |||
| 106 | 7 - 1.5s | 106 | 7 - 1.5s |
| 107 | 107 | ||
| 108 | The CS42L42_TS_DBNCE_* defines are available for this. | 108 | The CS42L42_TS_DBNCE_* defines are available for this. |
| 109 | $ref: "/schemas/types.yaml#/definitions/uint32" | 109 | $ref: /schemas/types.yaml#/definitions/uint32 |
| 110 | minimum: 0 | 110 | minimum: 0 |
| 111 | maximum: 7 | 111 | maximum: 7 |
| 112 | 112 | ||
| @@ -120,7 +120,7 @@ properties: · 7 unmodified lines | |||
| 120 | 120 | ||
| 121 | 0ms - 200ms, | 121 | 0ms - 200ms, |
| 122 | Default = 100ms | 122 | Default = 100ms |
| 123 | $ref: "/schemas/types.yaml#/definitions/uint32" | 123 | $ref: /schemas/types.yaml#/definitions/uint32 |
| 124 | minimum: 0 | 124 | minimum: 0 |
| 125 | maximum: 200 | 125 | maximum: 200 |
| 126 | 126 | ||
| @@ -133,7 +133,7 @@ properties: · 6 unmodified lines | |||
| 133 | 133 | ||
| 134 | 0ms - 20ms, | 134 | 0ms - 20ms, |
| 135 | Default = 10ms | 135 | Default = 10ms |
| 136 | $ref: "/schemas/types.yaml#/definitions/uint32" | 136 | $ref: /schemas/types.yaml#/definitions/uint32 |
| 137 | minimum: 0 | 137 | minimum: 0 |
| 138 | maximum: 20 | 138 | maximum: 20 |
| 139 | 139 | ||
| @@ -169,7 +169,7 @@ properties: · 29 unmodified lines | |||
| 169 | 3 - Slowest | 169 | 3 - Slowest |
| 170 | 170 | ||
| 171 | The CS42L42_HSBIAS_RAMP_* defines are available for this. | 171 | The CS42L42_HSBIAS_RAMP_* defines are available for this. |
| 172 | $ref: "/schemas/types.yaml#/definitions/uint32" | 172 | $ref: /schemas/types.yaml#/definitions/uint32 |
| 173 | minimum: 0 | 173 | minimum: 0 |
| 174 | maximum: 3 | 174 | maximum: 3 |
| 175 | 175 | ||
| @@ -0,0 +1,66 @@ | |||
| 1 | # SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) | ||
| 2 | %YAML 1.2 | ||
| 3 | --- | ||
| 4 | $id: http://devicetree.org/schemas/sound/cirrus,ep9301-i2s.yaml# | ||
| 5 | $schema: http://devicetree.org/meta-schemas/core.yaml# | ||
| 6 | |||
| 7 | title: Cirrus EP93xx I2S Controller | ||
| 8 | |||
| 9 | description: | | ||
| 10 | The I2S controller is used to stream serial audio data between the external | ||
| 11 | I2S CODECs’, ADCs/DACs, and the ARM Core. The controller supports I2S, Left- | ||
| 12 | and Right-Justified DSP formats. | ||
| 13 | |||
| 14 | maintainers: | ||
| 15 | - Alexander Sverdlin <alexander.sverdlin@gmail.com> | ||
| 16 | |||
| 17 | allOf: | ||
| 18 | - $ref: dai-common.yaml# | ||
| 19 | |||
| 20 | properties: | ||
| 21 | compatible: | ||
| 22 | const: cirrus,ep9301-i2s | ||
| 23 | |||
| 24 | '#sound-dai-cells': | ||
| 25 | const: 0 | ||
| 26 | |||
| 27 | reg: | ||
| 28 | maxItems: 1 | ||
| 29 | |||
| 30 | interrupts: | ||
| 31 | maxItems: 1 | ||
| 32 | |||
| 33 | clocks: | ||
| 34 | minItems: 3 | ||
| 35 | maxItems: 3 | ||
| 36 | |||
| 37 | clock-names: | ||
| 38 | items: | ||
| 39 | - const: mclk | ||
| 40 | - const: sclk | ||
| 41 | - const: lrclk | ||
| 42 | |||
| 43 | required: | ||
| 44 | - compatible | ||
| 45 | - '#sound-dai-cells' | ||
| 46 | - reg | ||
| 47 | - clocks | ||
| 48 | - clock-names | ||
| 49 | |||
| 50 | additionalProperties: false | ||
| 51 | |||
| 52 | examples: | ||
| 53 | - | | ||
| 54 | i2s: i2s@80820000 { | ||
| 55 | compatible = "cirrus,ep9301-i2s"; | ||
| 56 | #sound-dai-cells = <0>; | ||
| 57 | reg = <0x80820000 0x100>; | ||
| 58 | interrupt-parent = <&vic1>; | ||
| 59 | interrupts = <28>; | ||
| 60 | clocks = <&syscon 29>, | ||
| 61 | <&syscon 30>, | ||
| 62 | <&syscon 31>; | ||
| 63 | clock-names = "mclk", "sclk", "lrclk"; | ||
| 64 | }; | ||
| 65 | |||
| 66 | ... | ||
| @@ -28,6 +28,10 @@ properties: · 27 unmodified lines | |||
| 28 | items: | 28 | items: |
| 29 | - const: mclk | 29 | - const: mclk |
| 30 | 30 | ||
| 31 | port: | ||
| 32 | $ref: audio-graph-port.yaml# | ||
| 33 | unevaluatedProperties: false | ||
| 34 | |||
| 31 | "#sound-dai-cells": | 35 | "#sound-dai-cells": |
| 32 | const: 0 | 36 | const: 0 |
| 33 | 37 | ||
| @@ -0,0 +1,117 @@ | |||
| 1 | # SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) | ||
| 2 | %YAML 1.2 | ||
| 3 | --- | ||
| 4 | $id: http://devicetree.org/schemas/sound/fsl,qmc-audio.yaml# | ||
| 5 | $schema: http://devicetree.org/meta-schemas/core.yaml# | ||
| 6 | |||
| 7 | title: QMC audio | ||
| 8 | |||
| 9 | maintainers: | ||
| 10 | - Herve Codina <herve.codina@bootlin.com> | ||
| 11 | |||
| 12 | description: | | ||
| 13 | The QMC audio is an ASoC component which uses QMC (QUICC Multichannel | ||
| 14 | Controller) channels to transfer the audio data. | ||
| 15 | It provides as many DAI as the number of QMC channel used. | ||
| 16 | |||
| 17 | allOf: | ||
| 18 | - $ref: dai-common.yaml# | ||
| 19 | |||
| 20 | properties: | ||
| 21 | compatible: | ||
| 22 | const: fsl,qmc-audio | ||
| 23 | |||
| 24 | '#address-cells': | ||
| 25 | const: 1 | ||
| 26 | '#size-cells': | ||
| 27 | const: 0 | ||
| 28 | '#sound-dai-cells': | ||
| 29 | const: 1 | ||
| 30 | |||
| 31 | patternProperties: | ||
| 32 | '^dai@([0-9]|[1-5][0-9]|6[0-3])$': | ||
| 33 | description: | ||
| 34 | A DAI managed by this controller | ||
| 35 | type: object | ||
| 36 | |||
| 37 | properties: | ||
| 38 | reg: | ||
| 39 | minimum: 0 | ||
| 40 | maximum: 63 | ||
| 41 | description: | ||
| 42 | The DAI number | ||
| 43 | |||
| 44 | fsl,qmc-chan: | ||
| 45 | $ref: /schemas/types.yaml#/definitions/phandle-array | ||
| 46 | items: | ||
| 47 | - items: | ||
| 48 | - description: phandle to QMC node | ||
| 49 | - description: Channel number | ||
| 50 | description: | ||
| 51 | Should be a phandle/number pair. The phandle to QMC node and the QMC | ||
| 52 | channel to use for this DAI. | ||
| 53 | |||
| 54 | required: | ||
| 55 | - reg | ||
| 56 | - fsl,qmc-chan | ||
| 57 | |||
| 58 | required: | ||
| 59 | - compatible | ||
| 60 | - '#address-cells' | ||
| 61 | - '#size-cells' | ||
| 62 | - '#sound-dai-cells' | ||
| 63 | |||
| 64 | additionalProperties: false | ||
| 65 | |||
| 66 | examples: | ||
| 67 | - | | ||
| 68 | audio_controller: audio-controller { | ||
| 69 | compatible = "fsl,qmc-audio"; | ||
| 70 | #address-cells = <1>; | ||
| 71 | #size-cells = <0>; | ||
| 72 | #sound-dai-cells = <1>; | ||
| 73 | dai@16 { | ||
| 74 | reg = <16>; | ||
| 75 | fsl,qmc-chan = <&qmc 16>; | ||
| 76 | }; | ||
| 77 | dai@17 { | ||
| 78 | reg = <17>; | ||
| 79 | fsl,qmc-chan = <&qmc 17>; | ||
| 80 | }; | ||
| 81 | }; | ||
| 82 | |||
| 83 | sound { | ||
| 84 | compatible = "simple-audio-card"; | ||
| 85 | #address-cells = <1>; | ||
| 86 | #size-cells = <0>; | ||
| 87 | simple-audio-card,dai-link@0 { | ||
| 88 | reg = <0>; | ||
| 89 | format = "dsp_b"; | ||
| 90 | cpu { | ||
| 91 | sound-dai = <&audio_controller 16>; | ||
| 92 | }; | ||
| 93 | codec { | ||
| 94 | sound-dai = <&codec1>; | ||
| 95 | dai-tdm-slot-num = <4>; | ||
| 96 | dai-tdm-slot-width = <8>; | ||
| 97 | /* TS 3, 5, 7, 9 */ | ||
| 98 | dai-tdm-slot-tx-mask = <0 0 0 1 0 1 0 1 0 1>; | ||
| 99 | dai-tdm-slot-rx-mask = <0 0 0 1 0 1 0 1 0 1>; | ||
| 100 | }; | ||
| 101 | }; | ||
| 102 | simple-audio-card,dai-link@1 { | ||
| 103 | reg = <1>; | ||
| 104 | format = "dsp_b"; | ||
| 105 | cpu { | ||
| 106 | sound-dai = <&audio_controller 17>; | ||
| 107 | }; | ||
| 108 | codec { | ||
| 109 | sound-dai = <&codec2>; | ||
| 110 | dai-tdm-slot-num = <4>; | ||
| 111 | dai-tdm-slot-width = <8>; | ||
| 112 | /* TS 2, 4, 6, 8 */ | ||
| 113 | dai-tdm-slot-tx-mask = <0 0 1 0 1 0 1 0 1>; | ||
| 114 | dai-tdm-slot-rx-mask = <0 0 1 0 1 0 1 0 1>; | ||
| 115 | }; | ||
| 116 | }; | ||
| 117 | }; | ||
| @@ -1,17 +0,0 @@ | |||
| 1 | max98371 codec | ||
| 2 | |||
| 3 | This device supports I2C mode only. | ||
| 4 | |||
| 5 | Required properties: | ||
| 6 | |||
| 7 | - compatible : "maxim,max98371" | ||
| 8 | - reg : The chip select number on the I2C bus | ||
| 9 | |||
| 10 | Example: | ||
| 11 | |||
| 12 | &i2c { | ||
| 13 | max98371: max98371@31 { | ||
| 14 | compatible = "maxim,max98371"; | ||
| 15 | reg = <0x31>; | ||
| 16 | }; | ||
| 17 | }; | ||
| @@ -1,17 +0,0 @@ | |||
| 1 | max9867 codec | ||
| 2 | |||
| 3 | This device supports I2C mode only. | ||
| 4 | |||
| 5 | Required properties: | ||
| 6 | |||
| 7 | - compatible : "maxim,max9867" | ||
| 8 | - reg : The chip select number on the I2C bus | ||
| 9 | |||
| 10 | Example: | ||
| 11 | |||
| 12 | &i2c { | ||
| 13 | max9867: max9867@18 { | ||
| 14 | compatible = "maxim,max9867"; | ||
| 15 | reg = <0x18>; | ||
| 16 | }; | ||
| 17 | }; | ||
| @@ -1,18 +0,0 @@ | |||
| 1 | Maxim MAX9759 Speaker Amplifier | ||
| 2 | =============================== | ||
| 3 | |||
| 4 | Required properties: | ||
| 5 | - compatible : "maxim,max9759" | ||
| 6 | - shutdown-gpios : the gpio connected to the shutdown pin | ||
| 7 | - mute-gpios : the gpio connected to the mute pin | ||
| 8 | - gain-gpios : the 2 gpios connected to the g1 and g2 pins | ||
| 9 | |||
| 10 | Example: | ||
| 11 | |||
| 12 | max9759: analog-amplifier { | ||
| 13 | compatible = "maxim,max9759"; | ||
| 14 | shutdown-gpios = <&gpio3 20 GPIO_ACTIVE_LOW>; | ||
| 15 | mute-gpios = <&gpio3 19 GPIO_ACTIVE_LOW>; | ||
| 16 | gain-gpios = <&gpio3 23 GPIO_ACTIVE_LOW>, | ||
| 17 | <&gpio3 25 GPIO_ACTIVE_LOW>; | ||
| 18 | }; | ||
| @@ -0,0 +1,45 @@ | |||
| 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,max9759.yaml# | ||
| 5 | $schema: http://devicetree.org/meta-schemas/core.yaml# | ||
| 6 | |||
| 7 | title: Maxim MAX9759 Speaker Amplifier | ||
| 8 | |||
| 9 | maintainers: | ||
| 10 | - Otabek Nazrullaev <otabeknazrullaev1998@gmail.com> | ||
| 11 | |||
| 12 | properties: | ||
| 13 | compatible: | ||
| 14 | const: maxim,max9759 | ||
| 15 | |||
| 16 | shutdown-gpios: | ||
| 17 | maxItems: 1 | ||
| 18 | description: the gpio connected to the shutdown pin | ||
| 19 | |||
| 20 | mute-gpios: | ||
| 21 | maxItems: 1 | ||
| 22 | description: the gpio connected to the mute pin | ||
| 23 | |||
| 24 | gain-gpios: | ||
| 25 | maxItems: 2 | ||
| 26 | description: the 2 gpios connected to the g1 and g2 pins | ||
| 27 | |||
| 28 | required: | ||
| 29 | - compatible | ||
| 30 | - shutdown-gpios | ||
| 31 | - mute-gpios | ||
| 32 | - gain-gpios | ||
| 33 | |||
| 34 | additionalProperties: false | ||
| 35 | |||
| 36 | examples: | ||
| 37 | - | | ||
| 38 | #include <dt-bindings/gpio/gpio.h> | ||
| 39 | amplifier { | ||
| 40 | compatible = "maxim,max9759"; | ||
| 41 | shutdown-gpios = <&gpio3 20 GPIO_ACTIVE_LOW>; | ||
| 42 | mute-gpios = <&gpio3 19 GPIO_ACTIVE_LOW>; | ||
| 43 | gain-gpios = <&gpio3 23 GPIO_ACTIVE_LOW>, | ||
| 44 | <&gpio3 25 GPIO_ACTIVE_LOW>; | ||
| 45 | }; | ||
| @@ -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/maxim,max98371.yaml# | ||
| 5 | $schema: http://devicetree.org/meta-schemas/core.yaml# | ||
| 6 | |||
| 7 | title: Maxim MAX98371 audio codec | ||
| 8 | |||
| 9 | maintainers: | ||
| 10 | - anish kumar <yesanishhere@gmail.com> | ||
| 11 | |||
| 12 | allOf: | ||
| 13 | - $ref: dai-common.yaml# | ||
| 14 | |||
| 15 | properties: | ||
| 16 | compatible: | ||
| 17 | const: maxim,max98371 | ||
| 18 | |||
| 19 | '#sound-dai-cells': | ||
| 20 | const: 0 | ||
| 21 | |||
| 22 | reg: | ||
| 23 | maxItems: 1 | ||
| 24 | |||
| 25 | required: | ||
| 26 | - compatible | ||
| 27 | - reg | ||
| 28 | |||
| 29 | unevaluatedProperties: false | ||
| 30 | |||
| 31 | examples: | ||
| 32 | - | | ||
| 33 | i2c { | ||
| 34 | #address-cells = <1>; | ||
| 35 | #size-cells = <0>; | ||
| 36 | |||
| 37 | codec@31 { | ||
| 38 | compatible = "maxim,max98371"; | ||
| 39 | reg = <0x31>; | ||
| 40 | #sound-dai-cells = <0>; | ||
| 41 | }; | ||
| 42 | }; | ||
| @@ -0,0 +1,60 @@ | |||
| 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,max9867.yaml# | ||
| 5 | $schema: http://devicetree.org/meta-schemas/core.yaml# | ||
| 6 | |||
| 7 | title: Maxim Integrated MAX9867 CODEC | ||
| 8 | |||
| 9 | description: | | ||
| 10 | This device supports I2C only. | ||
| 11 | Pins on the device (for linking into audio routes): | ||
| 12 | * LOUT | ||
| 13 | * ROUT | ||
| 14 | * LINL | ||
| 15 | * LINR | ||
| 16 | * MICL | ||
| 17 | * MICR | ||
| 18 | * DMICL | ||
| 19 | * DMICR | ||
| 20 | |||
| 21 | maintainers: | ||
| 22 | - Ladislav Michl <ladis@linux-mips.org> | ||
| 23 | |||
| 24 | allOf: | ||
| 25 | - $ref: dai-common.yaml# | ||
| 26 | |||
| 27 | properties: | ||
| 28 | compatible: | ||
| 29 | enum: | ||
| 30 | - maxim,max9867 | ||
| 31 | |||
| 32 | '#sound-dai-cells': | ||
| 33 | const: 0 | ||
| 34 | |||
| 35 | reg: | ||
| 36 | maxItems: 1 | ||
| 37 | |||
| 38 | clocks: | ||
| 39 | maxItems: 1 | ||
| 40 | |||
| 41 | required: | ||
| 42 | - compatible | ||
| 43 | - reg | ||
| 44 | - clocks | ||
| 45 | |||
| 46 | additionalProperties: false | ||
| 47 | |||
| 48 | examples: | ||
| 49 | - | | ||
| 50 | i2c { | ||
| 51 | #address-cells = <1>; | ||
| 52 | #size-cells = <0>; | ||
| 53 | codec@18 { | ||
| 54 | compatible = "maxim,max9867"; | ||
| 55 | #sound-dai-cells = <0>; | ||
| 56 | reg = <0x18>; | ||
| 57 | clocks = <&codec_clk>; | ||
| 58 | }; | ||
| 59 | }; | ||
| 60 | ... | ||
| @@ -26,15 +26,15 @@ properties: · 25 unmodified lines | |||
| 26 | const: audiosys | 26 | const: audiosys |
| 27 | 27 | ||
| 28 | mediatek,apmixedsys: | 28 | mediatek,apmixedsys: |
| 29 | $ref: "/schemas/types.yaml#/definitions/phandle" | 29 | $ref: /schemas/types.yaml#/definitions/phandle |
| 30 | description: The phandle of the mediatek apmixedsys controller | 30 | description: The phandle of the mediatek apmixedsys controller |
| 31 | 31 | ||
| 32 | mediatek,infracfg: | 32 | mediatek,infracfg: |
| 33 | $ref: "/schemas/types.yaml#/definitions/phandle" | 33 | $ref: /schemas/types.yaml#/definitions/phandle |
| 34 | description: The phandle of the mediatek infracfg controller | 34 | description: The phandle of the mediatek infracfg controller |
| 35 | 35 | ||
| 36 | mediatek,topckgen: | 36 | mediatek,topckgen: |
| 37 | $ref: "/schemas/types.yaml#/definitions/phandle" | 37 | $ref: /schemas/types.yaml#/definitions/phandle |
| 38 | description: The phandle of the mediatek topckgen controller | 38 | description: The phandle of the mediatek topckgen controller |
| 39 | 39 | ||
| 40 | clocks: | 40 | clocks: |
| @@ -18,7 +18,7 @@ properties: · 17 unmodified lines | |||
| 18 | - mediatek,mt8186-mt6366-da7219-max98357-sound | 18 | - mediatek,mt8186-mt6366-da7219-max98357-sound |
| 19 | 19 | ||
| 20 | mediatek,platform: | 20 | mediatek,platform: |
| 21 | $ref: "/schemas/types.yaml#/definitions/phandle" | 21 | $ref: /schemas/types.yaml#/definitions/phandle |
| 22 | description: The phandle of MT8186 ASoC platform. | 22 | description: The phandle of MT8186 ASoC platform. |
| 23 | 23 | ||
| 24 | headset-codec: | 24 | headset-codec: |
| @@ -19,7 +19,7 @@ properties: · 18 unmodified lines | |||
| 19 | - mediatek,mt8186-mt6366-rt5682s-max98360-sound | 19 | - mediatek,mt8186-mt6366-rt5682s-max98360-sound |
| 20 | 20 | ||
| 21 | mediatek,platform: | 21 | mediatek,platform: |
| 22 | $ref: "/schemas/types.yaml#/definitions/phandle" | 22 | $ref: /schemas/types.yaml#/definitions/phandle |
| 23 | description: The phandle of MT8186 ASoC platform. | 23 | description: The phandle of MT8186 ASoC platform. |
| 24 | 24 | ||
| 25 | dmic-gpios: | 25 | dmic-gpios: |
| @@ -24,15 +24,15 @@ properties: · 23 unmodified lines | |||
| 24 | const: audiosys | 24 | const: audiosys |
| 25 | 25 | ||
| 26 | mediatek,apmixedsys: | 26 | mediatek,apmixedsys: |
| 27 | $ref: "/schemas/types.yaml#/definitions/phandle" | 27 | $ref: /schemas/types.yaml#/definitions/phandle |
| 28 | description: The phandle of the mediatek apmixedsys controller | 28 | description: The phandle of the mediatek apmixedsys controller |
| 29 | 29 | ||
| 30 | mediatek,infracfg: | 30 | mediatek,infracfg: |
| 31 | $ref: "/schemas/types.yaml#/definitions/phandle" | 31 | $ref: /schemas/types.yaml#/definitions/phandle |
| 32 | description: The phandle of the mediatek infracfg controller | 32 | description: The phandle of the mediatek infracfg controller |
| 33 | 33 | ||
| 34 | mediatek,topckgen: | 34 | mediatek,topckgen: |
| 35 | $ref: "/schemas/types.yaml#/definitions/phandle" | 35 | $ref: /schemas/types.yaml#/definitions/phandle |
| 36 | description: The phandle of the mediatek topckgen controller | 36 | description: The phandle of the mediatek topckgen controller |
| 37 | 37 | ||
| 38 | power-domains: | 38 | power-domains: |
| @@ -21,11 +21,11 @@ properties: · 20 unmodified lines | |||
| 21 | - mediatek,mt8192_mt6359_rt1015p_rt5682s | 21 | - mediatek,mt8192_mt6359_rt1015p_rt5682s |
| 22 | 22 | ||
| 23 | mediatek,platform: | 23 | mediatek,platform: |
| 24 | $ref: "/schemas/types.yaml#/definitions/phandle" | 24 | $ref: /schemas/types.yaml#/definitions/phandle |
| 25 | description: The phandle of MT8192 ASoC platform. | 25 | description: The phandle of MT8192 ASoC platform. |
| 26 | 26 | ||
| 27 | mediatek,hdmi-codec: | 27 | mediatek,hdmi-codec: |
| 28 | $ref: "/schemas/types.yaml#/definitions/phandle" | 28 | $ref: /schemas/types.yaml#/definitions/phandle |
| 29 | description: The phandle of HDMI codec. | 29 | description: The phandle of HDMI codec. |
| 30 | 30 | ||
| 31 | headset-codec: | 31 | headset-codec: |
| @@ -32,7 +32,7 @@ properties: · 31 unmodified lines | |||
| 32 | See ../reserved-memory/reserved-memory.txt for details. | 32 | See ../reserved-memory/reserved-memory.txt for details. |
| 33 | 33 | ||
| 34 | mediatek,topckgen: | 34 | mediatek,topckgen: |
| 35 | $ref: "/schemas/types.yaml#/definitions/phandle" | 35 | $ref: /schemas/types.yaml#/definitions/phandle |
| 36 | description: The phandle of the mediatek topckgen controller | 36 | description: The phandle of the mediatek topckgen controller |
| 37 | 37 | ||
| 38 | power-domains: | 38 | power-domains: |
| @@ -24,19 +24,19 @@ properties: · 23 unmodified lines | |||
| 24 | description: User specified audio sound card name | 24 | description: User specified audio sound card name |
| 25 | 25 | ||
| 26 | mediatek,platform: | 26 | mediatek,platform: |
| 27 | $ref: "/schemas/types.yaml#/definitions/phandle" | 27 | $ref: /schemas/types.yaml#/definitions/phandle |
| 28 | description: The phandle of MT8195 ASoC platform. | 28 | description: The phandle of MT8195 ASoC platform. |
| 29 | 29 | ||
| 30 | mediatek,dptx-codec: | 30 | mediatek,dptx-codec: |
| 31 | $ref: "/schemas/types.yaml#/definitions/phandle" | 31 | $ref: /schemas/types.yaml#/definitions/phandle |
| 32 | description: The phandle of MT8195 Display Port Tx codec node. | 32 | description: The phandle of MT8195 Display Port Tx codec node. |
| 33 | 33 | ||
| 34 | mediatek,hdmi-codec: | 34 | mediatek,hdmi-codec: |
| 35 | $ref: "/schemas/types.yaml#/definitions/phandle" | 35 | $ref: /schemas/types.yaml#/definitions/phandle |
| 36 | description: The phandle of MT8195 HDMI codec node. | 36 | description: The phandle of MT8195 HDMI codec node. |
| 37 | 37 | ||
| 38 | mediatek,adsp: | 38 | mediatek,adsp: |
| 39 | $ref: "/schemas/types.yaml#/definitions/phandle" | 39 | $ref: /schemas/types.yaml#/definitions/phandle |
| 40 | description: The phandle of MT8195 ADSP platform. | 40 | description: The phandle of MT8195 ADSP platform. |
| 41 | 41 | ||
| 42 | mediatek,dai-link: | 42 | mediatek,dai-link: |
| @@ -74,6 +74,9 @@ Optional properties: · 73 unmodified lines | |||
| 74 | - nuvoton,adcout-drive-strong: make the drive strength of ADCOUT IO PIN strong if set. | 74 | - nuvoton,adcout-drive-strong: make the drive strength of ADCOUT IO PIN strong if set. |
| 75 | Otherwise, the drive keeps normal strength. | 75 | Otherwise, the drive keeps normal strength. |
| 76 | 76 | ||
| 77 | - nuvoton,adc-delay-ms: Delay (in ms) to make input path stable and avoid pop noise. The | ||
| 78 | default value is 125 and range between 125 to 500 ms. | ||
| 79 | |||
| 77 | - clocks: list of phandle and clock specifier pairs according to common clock bindings for the | 80 | - clocks: list of phandle and clock specifier pairs according to common clock bindings for the |
| 78 | clocks described in clock-names | 81 | clocks described in clock-names |
| 79 | - clock-names: should include "mclk" for the MCLK master clock | 82 | - clock-names: should include "mclk" for the MCLK master clock |
| @@ -31,10 +31,10 @@ properties: · 30 unmodified lines | |||
| 31 | items: | 31 | items: |
| 32 | enum: | 32 | enum: |
| 33 | # Board Connectors | 33 | # Board Connectors |
| 34 | - "Headset Stereophone" | 34 | - Headset Stereophone |
| 35 | - "Int Spk" | 35 | - Int Spk |
| 36 | - "Headset Mic" | 36 | - Headset Mic |
| 37 | - "Digital Mic" | 37 | - Digital Mic |
| 38 | 38 | ||
| 39 | # CODEC Pins | 39 | # CODEC Pins |
| 40 | - SPKOUT | 40 | - SPKOUT |
| @@ -80,4 +80,8 @@ properties: · 79 unmodified lines | |||
| 80 | type: boolean | 80 | type: boolean |
| 81 | description: The Mic Jack represents state of the headset microphone pin | 81 | description: The Mic Jack represents state of the headset microphone pin |
| 82 | 82 | ||
| 83 | nvidia,coupled-mic-hp-det: | ||
| 84 | type: boolean | ||
| 85 | description: The Mic detect GPIO is viable only if HP detect GPIO is active | ||
| 86 | |||
| 83 | additionalProperties: true | 87 | additionalProperties: true |
| @@ -0,0 +1,90 @@ | |||
| 1 | # SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) | ||
| 2 | %YAML 1.2 | ||
| 3 | --- | ||
| 4 | $id: http://devicetree.org/schemas/sound/nvidia,tegra-audio-max9808x.yaml# | ||
| 5 | $schema: http://devicetree.org/meta-schemas/core.yaml# | ||
| 6 | |||
| 7 | title: NVIDIA Tegra audio complex with MAX9808x CODEC | ||
| 8 | |||
| 9 | maintainers: | ||
| 10 | - Jon Hunter <jonathanh@nvidia.com> | ||
| 11 | - Thierry Reding <thierry.reding@gmail.com> | ||
| 12 | |||
| 13 | allOf: | ||
| 14 | - $ref: nvidia,tegra-audio-common.yaml# | ||
| 15 | |||
| 16 | properties: | ||
| 17 | compatible: | ||
| 18 | oneOf: | ||
| 19 | - items: | ||
| 20 | - pattern: '^[a-z0-9]+,tegra-audio-max98088(-[a-z0-9]+)+$' | ||
| 21 | - const: nvidia,tegra-audio-max98088 | ||
| 22 | - items: | ||
| 23 | - pattern: '^[a-z0-9]+,tegra-audio-max98089(-[a-z0-9]+)+$' | ||
| 24 | - const: nvidia,tegra-audio-max98089 | ||
| 25 | |||
| 26 | nvidia,audio-routing: | ||
| 27 | $ref: /schemas/types.yaml#/definitions/non-unique-string-array | ||
| 28 | description: | | ||
| 29 | A list of the connections between audio components. | ||
| 30 | Each entry is a pair of strings, the first being the connection's sink, | ||
| 31 | the second being the connection's source. Valid names for sources and | ||
| 32 | sinks are the pins (documented in the binding document), | ||
| 33 | and the jacks on the board. | ||
| 34 | minItems: 2 | ||
| 35 | items: | ||
| 36 | enum: | ||
| 37 | # Board Connectors | ||
| 38 | - "Int Spk" | ||
| 39 | - "Headphone Jack" | ||
| 40 | - "Earpiece" | ||
| 41 | - "Headset Mic" | ||
| 42 | - "Internal Mic 1" | ||
| 43 | - "Internal Mic 2" | ||
| 44 | |||
| 45 | # CODEC Pins | ||
| 46 | - HPL | ||
| 47 | - HPR | ||
| 48 | - SPKL | ||
| 49 | - SPKR | ||
| 50 | - RECL | ||
| 51 | - RECR | ||
| 52 | - INA1 | ||
| 53 | - INA2 | ||
| 54 | - INB1 | ||
| 55 | - INB2 | ||
| 56 | - MIC1 | ||
| 57 | - MIC2 | ||
| 58 | - MICBIAS | ||
| 59 | |||
| 60 | unevaluatedProperties: false | ||
| 61 | |||
| 62 | examples: | ||
| 63 | - | | ||
| 64 | #include <dt-bindings/clock/tegra30-car.h> | ||
| 65 | #include <dt-bindings/soc/tegra-pmc.h> | ||
| 66 | sound { | ||
| 67 | compatible = "lge,tegra-audio-max98089-p895", | ||
| 68 | "nvidia,tegra-audio-max98089"; | ||
| 69 | nvidia,model = "LG Optimus Vu MAX98089"; | ||
| 70 | |||
| 71 | nvidia,audio-routing = | ||
| 72 | "Headphone Jack", "HPL", | ||
| 73 | "Headphone Jack", "HPR", | ||
| 74 | "Int Spk", "SPKL", | ||
| 75 | "Int Spk", "SPKR", | ||
| 76 | "Earpiece", "RECL", | ||
| 77 | "Earpiece", "RECR", | ||
| 78 | "INA1", "Headset Mic", | ||
| 79 | "MIC1", "MICBIAS", | ||
| 80 | "MICBIAS", "Internal Mic 1", | ||
| 81 | "MIC2", "Internal Mic 2"; | ||
| 82 | |||
| 83 | nvidia,i2s-controller = <&tegra_i2s0>; | ||
| 84 | nvidia,audio-codec = <&codec>; | ||
| 85 | |||
| 86 | clocks = <&tegra_car TEGRA30_CLK_PLL_A>, | ||
| 87 | <&tegra_car TEGRA30_CLK_PLL_A_OUT0>, | ||
| 88 | <&tegra_pmc TEGRA_PMC_CLK_OUT_1>; | ||
| 89 | clock-names = "pll_a", "pll_a_out0", "mclk"; | ||
| 90 | }; | ||
| @@ -38,10 +38,10 @@ properties: · 37 unmodified lines | |||
| 38 | items: | 38 | items: |
| 39 | enum: | 39 | enum: |
| 40 | # Board Connectors | 40 | # Board Connectors |
| 41 | - "Headphones" | 41 | - Headphones |
| 42 | - "Speakers" | 42 | - Speakers |
| 43 | - "Mic Jack" | 43 | - Mic Jack |
| 44 | - "Int Mic" | 44 | - Int Mic |
| 45 | 45 | ||
| 46 | # CODEC Pins | 46 | # CODEC Pins |
| 47 | - MIC1 | 47 | - MIC1 |
| @@ -0,0 +1,85 @@ | |||
| 1 | # SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) | ||
| 2 | %YAML 1.2 | ||
| 3 | --- | ||
| 4 | $id: http://devicetree.org/schemas/sound/nvidia,tegra-audio-rt5631.yaml# | ||
| 5 | $schema: http://devicetree.org/meta-schemas/core.yaml# | ||
| 6 | |||
| 7 | title: NVIDIA Tegra audio complex with RT5631 CODEC | ||
| 8 | |||
| 9 | maintainers: | ||
| 10 | - Jon Hunter <jonathanh@nvidia.com> | ||
| 11 | - Thierry Reding <thierry.reding@gmail.com> | ||
| 12 | |||
| 13 | allOf: | ||
| 14 | - $ref: nvidia,tegra-audio-common.yaml# | ||
| 15 | |||
| 16 | properties: | ||
| 17 | compatible: | ||
| 18 | items: | ||
| 19 | - pattern: '^[a-z0-9]+,tegra-audio-rt5631(-[a-z0-9]+)+$' | ||
| 20 | - const: nvidia,tegra-audio-rt5631 | ||
| 21 | |||
| 22 | nvidia,audio-routing: | ||
| 23 | $ref: /schemas/types.yaml#/definitions/non-unique-string-array | ||
| 24 | description: | | ||
| 25 | A list of the connections between audio components. | ||
| 26 | Each entry is a pair of strings, the first being the connection's sink, | ||
| 27 | the second being the connection's source. Valid names for sources and | ||
| 28 | sinks are the pins (documented in the binding document), | ||
| 29 | and the jacks on the board. | ||
| 30 | minItems: 2 | ||
| 31 | items: | ||
| 32 | enum: | ||
| 33 | # Board Connectors | ||
| 34 | - "Int Spk" | ||
| 35 | - "Headphone Jack" | ||
| 36 | - "Mic Jack" | ||
| 37 | - "Int Mic" | ||
| 38 | |||
| 39 | # CODEC Pins | ||
| 40 | - MIC1 | ||
| 41 | - MIC2 | ||
| 42 | - AXIL | ||
| 43 | - AXIR | ||
| 44 | - MONOIN_RXN | ||
| 45 | - MONOIN_RXP | ||
| 46 | - DMIC | ||
| 47 | - MIC Bias1 | ||
| 48 | - MIC Bias2 | ||
| 49 | - MONO_IN | ||
| 50 | - AUXO1 | ||
| 51 | - AUXO2 | ||
| 52 | - SPOL | ||
| 53 | - SPOR | ||
| 54 | - HPOL | ||
| 55 | - HPOR | ||
| 56 | - MONO | ||
| 57 | |||
| 58 | unevaluatedProperties: false | ||
| 59 | |||
| 60 | examples: | ||
| 61 | - | | ||
| 62 | #include <dt-bindings/clock/tegra30-car.h> | ||
| 63 | #include <dt-bindings/soc/tegra-pmc.h> | ||
| 64 | sound { | ||
| 65 | compatible = "asus,tegra-audio-rt5631-tf700t", | ||
| 66 | "nvidia,tegra-audio-rt5631"; | ||
| 67 | nvidia,model = "Asus Transformer Infinity TF700T RT5631"; | ||
| 68 | |||
| 69 | nvidia,audio-routing = | ||
| 70 | "Headphone Jack", "HPOL", | ||
| 71 | "Headphone Jack", "HPOR", | ||
| 72 | "Int Spk", "SPOL", | ||
| 73 | "Int Spk", "SPOR", | ||
| 74 | "MIC1", "MIC Bias1", | ||
| 75 | "MIC Bias1", "Mic Jack", | ||
| 76 | "DMIC", "Int Mic"; | ||
| 77 | |||
| 78 | nvidia,i2s-controller = <&tegra_i2s1>; | ||
| 79 | nvidia,audio-codec = <&rt5631>; | ||
| 80 | |||
| 81 | clocks = <&tegra_car TEGRA30_CLK_PLL_A>, | ||
| 82 | <&tegra_car TEGRA30_CLK_PLL_A_OUT0>, | ||
| 83 | <&tegra_pmc TEGRA_PMC_CLK_OUT_1>; | ||
| 84 | clock-names = "pll_a", "pll_a_out0", "mclk"; | ||
| 85 | }; | ||
| @@ -31,9 +31,9 @@ properties: · 30 unmodified lines | |||
| 31 | items: | 31 | items: |
| 32 | enum: | 32 | enum: |
| 33 | # Board Connectors | 33 | # Board Connectors |
| 34 | - "Headphones" | 34 | - Headphones |
| 35 | - "Speakers" | 35 | - Speakers |
| 36 | - "Mic Jack" | 36 | - Mic Jack |
| 37 | 37 | ||
| 38 | # CODEC Pins | 38 | # CODEC Pins |
| 39 | - DMIC1 | 39 | - DMIC1 |
| @@ -31,11 +31,11 @@ properties: · 30 unmodified lines | |||
| 31 | items: | 31 | items: |
| 32 | enum: | 32 | enum: |
| 33 | # Board Connectors | 33 | # Board Connectors |
| 34 | - "Headphone" | 34 | - Headphone |
| 35 | - "Speaker" | 35 | - Speaker |
| 36 | - "Headset Mic" | 36 | - Headset Mic |
| 37 | - "Internal Mic 1" | 37 | - Internal Mic 1 |
| 38 | - "Internal Mic 2" | 38 | - Internal Mic 2 |
| 39 | 39 | ||
| 40 | # CODEC Pins | 40 | # CODEC Pins |
| 41 | - IN1P | 41 | - IN1P |
| @@ -47,14 +47,14 @@ properties: · 5 unmodified lines | |||
| 47 | - DMIC2 | 47 | - DMIC2 |
| 48 | - DMIC3 | 48 | - DMIC3 |
| 49 | - DMIC4 | 49 | - DMIC4 |
| 50 | - "DMIC L1" | 50 | - DMIC L1 |
| 51 | - "DMIC L2" | 51 | - DMIC L2 |
| 52 | - "DMIC L3" | 52 | - DMIC L3 |
| 53 | - "DMIC L4" | 53 | - DMIC L4 |
| 54 | - "DMIC R1" | 54 | - DMIC R1 |
| 55 | - "DMIC R2" | 55 | - DMIC R2 |
| 56 | - "DMIC R3" | 56 | - DMIC R3 |
| 57 | - "DMIC R4" | 57 | - DMIC R4 |
| 58 | - LOUT1 | 58 | - LOUT1 |
| 59 | - LOUT2 | 59 | - LOUT2 |
| 60 | - LOUT3 | 60 | - LOUT3 |
| @@ -31,9 +31,9 @@ properties: · 30 unmodified lines | |||
| 31 | items: | 31 | items: |
| 32 | enum: | 32 | enum: |
| 33 | # Board Connectors | 33 | # Board Connectors |
| 34 | - "Headphone Jack" | 34 | - Headphone Jack |
| 35 | - "Line In Jack" | 35 | - Line In Jack |
| 36 | - "Mic Jack" | 36 | - Mic Jack |
| 37 | 37 | ||
| 38 | # CODEC Pins | 38 | # CODEC Pins |
| 39 | - HP_OUT | 39 | - HP_OUT |
| @@ -31,8 +31,8 @@ properties: · 30 unmodified lines | |||
| 31 | items: | 31 | items: |
| 32 | enum: | 32 | enum: |
| 33 | # Board Connectors | 33 | # Board Connectors |
| 34 | - "Headphone Jack" | 34 | - Headphone Jack |
| 35 | - "Mic Jack" | 35 | - Mic Jack |
| 36 | 36 | ||
| 37 | # CODEC Pins | 37 | # CODEC Pins |
| 38 | - LOUT1 | 38 | - LOUT1 |
| @@ -53,7 +53,7 @@ properties: · 14 unmodified lines | |||
| 53 | - MIC1 | 53 | - MIC1 |
| 54 | - MIC2N | 54 | - MIC2N |
| 55 | - MIC2 | 55 | - MIC2 |
| 56 | - "Mic Bias" | 56 | - Mic Bias |
| 57 | 57 | ||
| 58 | required: | 58 | required: |
| 59 | - nvidia,i2s-controller | 59 | - nvidia,i2s-controller |
| @@ -35,10 +35,10 @@ properties: · 34 unmodified lines | |||
| 35 | items: | 35 | items: |
| 36 | enum: | 36 | enum: |
| 37 | # Board Connectors | 37 | # Board Connectors |
| 38 | - "Headphone Jack" | 38 | - Headphone Jack |
| 39 | - "Int Spk" | 39 | - Int Spk |
| 40 | - "Mic Jack" | 40 | - Mic Jack |
| 41 | - "Int Mic" | 41 | - Int Mic |
| 42 | 42 | ||
| 43 | # CODEC Pins | 43 | # CODEC Pins |
| 44 | - IN1L | 44 | - IN1L |
| @@ -31,9 +31,9 @@ properties: · 30 unmodified lines | |||
| 31 | items: | 31 | items: |
| 32 | enum: | 32 | enum: |
| 33 | # Board Connectors | 33 | # Board Connectors |
| 34 | - "Headphone" | 34 | - Headphone |
| 35 | - "LineIn" | 35 | - LineIn |
| 36 | - "Mic" | 36 | - Mic |
| 37 | 37 | ||
| 38 | # CODEC Pins | 38 | # CODEC Pins |
| 39 | - MONOOUT | 39 | - MONOOUT |
| @@ -48,7 +48,7 @@ properties: · 8 unmodified lines | |||
| 48 | - PCBEEP | 48 | - PCBEEP |
| 49 | - MIC1 | 49 | - MIC1 |
| 50 | - MIC2 | 50 | - MIC2 |
| 51 | - "Mic Bias" | 51 | - Mic Bias |
| 52 | 52 | ||
| 53 | required: | 53 | required: |
| 54 | - nvidia,ac97-controller | 54 | - nvidia,ac97-controller |
| @@ -9,15 +9,13 @@ title: LPASS(Low Power Audio Subsystem) RX Macro audio codec · 8 unmodified lines | |||
| 9 | maintainers: | 9 | maintainers: |
| 10 | - Srinivas Kandagatla <srinivas.kandagatla@linaro.org> | 10 | - Srinivas Kandagatla <srinivas.kandagatla@linaro.org> |
| 11 | 11 | ||
| 12 | allOf: | ||
| 13 | - $ref: dai-common.yaml# | ||
| 14 | |||
| 15 | properties: | 12 | properties: |
| 16 | compatible: | 13 | compatible: |
| 17 | enum: | 14 | enum: |
| 18 | - qcom,sc7280-lpass-rx-macro | 15 | - qcom,sc7280-lpass-rx-macro |
| 19 | - qcom,sm8250-lpass-rx-macro | 16 | - qcom,sm8250-lpass-rx-macro |
| 20 | - qcom,sm8450-lpass-rx-macro | 17 | - qcom,sm8450-lpass-rx-macro |
| 18 | - qcom,sm8550-lpass-rx-macro | ||
| 21 | - qcom,sc8280xp-lpass-rx-macro | 19 | - qcom,sc8280xp-lpass-rx-macro |
| 22 | 20 | ||
| 23 | reg: | 21 | reg: |
| @@ -30,20 +28,12 @@ properties: · 6 unmodified lines | |||
| 30 | const: 0 | 28 | const: 0 |
| 31 | 29 | ||
| 32 | clocks: | 30 | clocks: |
| 31 | minItems: 3 | ||
| 33 | maxItems: 5 | 32 | maxItems: 5 |
| 34 | 33 | ||
| 35 | clock-names: | 34 | clock-names: |
| 36 | oneOf: | 35 | minItems: 3 |
| 37 | - items: # for ADSP based platforms | 36 | maxItems: 5 |
| 38 | - const: mclk | ||
| 39 | - const: npl | ||
| 40 | - const: macro | ||
| 41 | - const: dcodec | ||
| 42 | - const: fsgen | ||
| 43 | - items: # for ADSP bypass based platforms | ||
| 44 | - const: mclk | ||
| 45 | - const: npl | ||
| 46 | - const: fsgen | ||
| 47 | 37 | ||
| 48 | clock-output-names: | 38 | clock-output-names: |
| 49 | maxItems: 1 | 39 | maxItems: 1 |
| @@ -61,6 +51,65 @@ required: · 11 unmodified lines | |||
| 61 | - reg | 51 | - reg |
| 62 | - "#sound-dai-cells" | 52 | - "#sound-dai-cells" |
| 63 | 53 | ||
| 54 | allOf: | ||
| 55 | - $ref: dai-common.yaml# | ||
| 56 | - if: | ||
| 57 | properties: | ||
| 58 | compatible: | ||
| 59 | enum: | ||
| 60 | - qcom,sc7280-lpass-rx-macro | ||
| 61 | then: | ||
| 62 | properties: | ||
| 63 | clock-names: | ||
| 64 | oneOf: | ||
| 65 | - items: # for ADSP based platforms | ||
| 66 | - const: mclk | ||
| 67 | - const: npl | ||
| 68 | - const: macro | ||
| 69 | - const: dcodec | ||
| 70 | - const: fsgen | ||
| 71 | - items: # for ADSP bypass based platforms | ||
| 72 | - const: mclk | ||
| 73 | - const: npl | ||
| 74 | - const: fsgen | ||
| 75 | |||
| 76 | - if: | ||
| 77 | properties: | ||
| 78 | compatible: | ||
| 79 | enum: | ||
| 80 | - qcom,sc8280xp-lpass-rx-macro | ||
| 81 | - qcom,sm8250-lpass-rx-macro | ||
| 82 | - qcom,sm8450-lpass-rx-macro | ||
| 83 | then: | ||
| 84 | properties: | ||
| 85 | clocks: | ||
| 86 | minItems: 5 | ||
| 87 | maxItems: 5 | ||
| 88 | clock-names: | ||
| 89 | items: | ||
| 90 | - const: mclk | ||
| 91 | - const: npl | ||
| 92 | - const: macro | ||
| 93 | - const: dcodec | ||
| 94 | - const: fsgen | ||
| 95 | |||
| 96 | - if: | ||
| 97 | properties: | ||
| 98 | compatible: | ||
| 99 | enum: | ||
| 100 | - qcom,sm8550-lpass-rx-macro | ||
| 101 | then: | ||
| 102 | properties: | ||
| 103 | clocks: | ||
| 104 | minItems: 4 | ||
| 105 | maxItems: 4 | ||
| 106 | clock-names: | ||
| 107 | items: | ||
| 108 | - const: mclk | ||
| 109 | - const: macro | ||
| 110 | - const: dcodec | ||
| 111 | - const: fsgen | ||
| 112 | |||
| 64 | unevaluatedProperties: false | 113 | unevaluatedProperties: false |
| 65 | 114 | ||
| 66 | examples: | 115 | examples: |
| @@ -9,15 +9,13 @@ title: LPASS(Low Power Audio Subsystem) TX Macro audio codec · 8 unmodified lines | |||
| 9 | maintainers: | 9 | maintainers: |
| 10 | - Srinivas Kandagatla <srinivas.kandagatla@linaro.org> | 10 | - Srinivas Kandagatla <srinivas.kandagatla@linaro.org> |
| 11 | 11 | ||
| 12 | allOf: | ||
| 13 | - $ref: dai-common.yaml# | ||
| 14 | |||
| 15 | properties: | 12 | properties: |
| 16 | compatible: | 13 | compatible: |
| 17 | enum: | 14 | enum: |
| 18 | - qcom,sc7280-lpass-tx-macro | 15 | - qcom,sc7280-lpass-tx-macro |
| 19 | - qcom,sm8250-lpass-tx-macro | 16 | - qcom,sm8250-lpass-tx-macro |
| 20 | - qcom,sm8450-lpass-tx-macro | 17 | - qcom,sm8450-lpass-tx-macro |
| 18 | - qcom,sm8550-lpass-tx-macro | ||
| 21 | - qcom,sc8280xp-lpass-tx-macro | 19 | - qcom,sc8280xp-lpass-tx-macro |
| 22 | 20 | ||
| 23 | reg: | 21 | reg: |
| @@ -30,22 +28,12 @@ properties: · 6 unmodified lines | |||
| 30 | const: 0 | 28 | const: 0 |
| 31 | 29 | ||
| 32 | clocks: | 30 | clocks: |
| 33 | oneOf: | 31 | minItems: 3 |
| 34 | - maxItems: 3 | 32 | maxItems: 5 |
| 35 | - maxItems: 5 | ||
| 36 | 33 | ||
| 37 | clock-names: | 34 | clock-names: |
| 38 | oneOf: | 35 | minItems: 3 |
| 39 | - items: # for ADSP based platforms | 36 | maxItems: 5 |
| 40 | - const: mclk | ||
| 41 | - const: npl | ||
| 42 | - const: macro | ||
| 43 | - const: dcodec | ||
| 44 | - const: fsgen | ||
| 45 | - items: # for ADSP bypass based platforms | ||
| 46 | - const: mclk | ||
| 47 | - const: npl | ||
| 48 | - const: fsgen | ||
| 49 | 37 | ||
| 50 | clock-output-names: | 38 | clock-output-names: |
| 51 | maxItems: 1 | 39 | maxItems: 1 |
| @@ -67,6 +55,65 @@ required: · 15 unmodified lines | |||
| 67 | - reg | 55 | - reg |
| 68 | - "#sound-dai-cells" | 56 | - "#sound-dai-cells" |
| 69 | 57 | ||
| 58 | allOf: | ||
| 59 | - $ref: dai-common.yaml# | ||
| 60 | - if: | ||
| 61 | properties: | ||
| 62 | compatible: | ||
| 63 | enum: | ||
| 64 | - qcom,sc7280-lpass-tx-macro | ||
| 65 | then: | ||
| 66 | properties: | ||
| 67 | clock-names: | ||
| 68 | oneOf: | ||
| 69 | - items: # for ADSP based platforms | ||
| 70 | - const: mclk | ||
| 71 | - const: npl | ||
| 72 | - const: macro | ||
| 73 | - const: dcodec | ||
| 74 | - const: fsgen | ||
| 75 | - items: # for ADSP bypass based platforms | ||
| 76 | - const: mclk | ||
| 77 | - const: npl | ||
| 78 | - const: fsgen | ||
| 79 | |||
| 80 | - if: | ||
| 81 | properties: | ||
| 82 | compatible: | ||
| 83 | enum: | ||
| 84 | - qcom,sc8280xp-lpass-tx-macro | ||
| 85 | - qcom,sm8250-lpass-tx-macro | ||
| 86 | - qcom,sm8450-lpass-tx-macro | ||
| 87 | then: | ||
| 88 | properties: | ||
| 89 | clocks: | ||
| 90 | minItems: 5 | ||
| 91 | maxItems: 5 | ||
| 92 | clock-names: | ||
| 93 | items: | ||
| 94 | - const: mclk | ||
| 95 | - const: npl | ||
| 96 | - const: macro | ||
| 97 | - const: dcodec | ||
| 98 | - const: fsgen | ||
| 99 | |||
| 100 | - if: | ||
| 101 | properties: | ||
| 102 | compatible: | ||
| 103 | enum: | ||
| 104 | - qcom,sm8550-lpass-tx-macro | ||
| 105 | then: | ||
| 106 | properties: | ||
| 107 | clocks: | ||
| 108 | minItems: 4 | ||
| 109 | maxItems: 4 | ||
| 110 | clock-names: | ||
| 111 | items: | ||
| 112 | - const: mclk | ||
| 113 | - const: macro | ||
| 114 | - const: dcodec | ||
| 115 | - const: fsgen | ||
| 116 | |||
| 70 | unevaluatedProperties: false | 117 | unevaluatedProperties: false |
| 71 | 118 | ||
| 72 | examples: | 119 | examples: |
| @@ -9,15 +9,13 @@ title: LPASS(Low Power Audio Subsystem) VA Macro audio codec · 8 unmodified lines | |||
| 9 | maintainers: | 9 | maintainers: |
| 10 | - Srinivas Kandagatla <srinivas.kandagatla@linaro.org> | 10 | - Srinivas Kandagatla <srinivas.kandagatla@linaro.org> |
| 11 | 11 | ||
| 12 | allOf: | ||
| 13 | - $ref: dai-common.yaml# | ||
| 14 | |||
| 15 | properties: | 12 | properties: |
| 16 | compatible: | 13 | compatible: |
| 17 | enum: | 14 | enum: |
| 18 | - qcom,sc7280-lpass-va-macro | 15 | - qcom,sc7280-lpass-va-macro |
| 19 | - qcom,sm8250-lpass-va-macro | 16 | - qcom,sm8250-lpass-va-macro |
| 20 | - qcom,sm8450-lpass-va-macro | 17 | - qcom,sm8450-lpass-va-macro |
| 18 | - qcom,sm8550-lpass-va-macro | ||
| 21 | - qcom,sc8280xp-lpass-va-macro | 19 | - qcom,sc8280xp-lpass-va-macro |
| 22 | 20 | ||
| 23 | reg: | 21 | reg: |
| @@ -30,16 +28,12 @@ properties: · 6 unmodified lines | |||
| 30 | const: 0 | 28 | const: 0 |
| 31 | 29 | ||
| 32 | clocks: | 30 | clocks: |
| 33 | maxItems: 3 | 31 | minItems: 1 |
| 32 | maxItems: 4 | ||
| 34 | 33 | ||
| 35 | clock-names: | 34 | clock-names: |
| 36 | oneOf: | 35 | minItems: 1 |
| 37 | - items: # for ADSP based platforms | 36 | maxItems: 4 |
| 38 | - const: mclk | ||
| 39 | - const: macro | ||
| 40 | - const: dcodec | ||
| 41 | - items: # for ADSP bypass based platforms | ||
| 42 | - const: mclk | ||
| 43 | 37 | ||
| 44 | clock-output-names: | 38 | clock-output-names: |
| 45 | maxItems: 1 | 39 | maxItems: 1 |
| @@ -63,6 +57,76 @@ required: · 17 unmodified lines | |||
| 63 | - compatible | 57 | - compatible |
| 64 | - reg | 58 | - reg |
| 65 | - "#sound-dai-cells" | 59 | - "#sound-dai-cells" |
| 60 | - clock-names | ||
| 61 | - clocks | ||
| 62 | |||
| 63 | allOf: | ||
| 64 | - $ref: dai-common.yaml# | ||
| 65 | |||
| 66 | - if: | ||
| 67 | properties: | ||
| 68 | compatible: | ||
| 69 | contains: | ||
| 70 | const: qcom,sc7280-lpass-va-macro | ||
| 71 | then: | ||
| 72 | properties: | ||
| 73 | clocks: | ||
| 74 | maxItems: 1 | ||
| 75 | clock-names: | ||
| 76 | items: | ||
| 77 | - const: mclk | ||
| 78 | |||
| 79 | - if: | ||
| 80 | properties: | ||
| 81 | compatible: | ||
| 82 | contains: | ||
| 83 | const: qcom,sm8250-lpass-va-macro | ||
| 84 | then: | ||
| 85 | properties: | ||
| 86 | clocks: | ||
| 87 | minItems: 3 | ||
| 88 | maxItems: 3 | ||
| 89 | clock-names: | ||
| 90 | items: | ||
| 91 | - const: mclk | ||
| 92 | - const: macro | ||
| 93 | - const: dcodec | ||
| 94 | |||
| 95 | - if: | ||
| 96 | properties: | ||
| 97 | compatible: | ||
| 98 | contains: | ||
| 99 | enum: | ||
| 100 | - qcom,sc8280xp-lpass-va-macro | ||
| 101 | - qcom,sm8450-lpass-va-macro | ||
| 102 | then: | ||
| 103 | properties: | ||
| 104 | clocks: | ||
| 105 | minItems: 4 | ||
| 106 | maxItems: 4 | ||
| 107 | clock-names: | ||
| 108 | items: | ||
| 109 | - const: mclk | ||
| 110 | - const: macro | ||
| 111 | - const: dcodec | ||
| 112 | - const: npl | ||
| 113 | |||
| 114 | - if: | ||
| 115 | properties: | ||
| 116 | compatible: | ||
| 117 | contains: | ||
| 118 | enum: | ||
| 119 | - qcom,sm8550-lpass-va-macro | ||
| 120 | then: | ||
| 121 | properties: | ||
| 122 | clocks: | ||
| 123 | minItems: 3 | ||
| 124 | maxItems: 3 | ||
| 125 | clock-names: | ||
| 126 | items: | ||
| 127 | - const: mclk | ||
| 128 | - const: macro | ||
| 129 | - const: dcodec | ||
| 66 | 130 | ||
| 67 | unevaluatedProperties: false | 131 | unevaluatedProperties: false |
| 68 | 132 | ||
| @@ -15,6 +15,7 @@ properties: · 14 unmodified lines | |||
| 15 | - qcom,sc7280-lpass-wsa-macro | 15 | - qcom,sc7280-lpass-wsa-macro |
| 16 | - qcom,sm8250-lpass-wsa-macro | 16 | - qcom,sm8250-lpass-wsa-macro |
| 17 | - qcom,sm8450-lpass-wsa-macro | 17 | - qcom,sm8450-lpass-wsa-macro |
| 18 | - qcom,sm8550-lpass-wsa-macro | ||
| 18 | - qcom,sc8280xp-lpass-wsa-macro | 19 | - qcom,sc8280xp-lpass-wsa-macro |
| 19 | 20 | ||
| 20 | reg: | 21 | reg: |
| @@ -27,11 +28,11 @@ properties: · 6 unmodified lines | |||
| 27 | const: 0 | 28 | const: 0 |
| 28 | 29 | ||
| 29 | clocks: | 30 | clocks: |
| 30 | minItems: 5 | 31 | minItems: 4 |
| 31 | maxItems: 6 | 32 | maxItems: 6 |
| 32 | 33 | ||
| 33 | clock-names: | 34 | clock-names: |
| 34 | minItems: 5 | 35 | minItems: 4 |
| 35 | maxItems: 6 | 36 | maxItems: 6 |
| 36 | 37 | ||
| 37 | clock-output-names: | 38 | clock-output-names: |
| @@ -62,6 +63,7 @@ allOf: · 24 unmodified lines | |||
| 62 | then: | 63 | then: |
| 63 | properties: | 64 | properties: |
| 64 | clocks: | 65 | clocks: |
| 66 | minItems: 5 | ||
| 65 | maxItems: 5 | 67 | maxItems: 5 |
| 66 | clock-names: | 68 | clock-names: |
| 67 | items: | 69 | items: |
| @@ -89,6 +91,23 @@ allOf: · 21 unmodified lines | |||
| 89 | - const: va | 91 | - const: va |
| 90 | - const: fsgen | 92 | - const: fsgen |
| 91 | 93 | ||
| 94 | - if: | ||
| 95 | properties: | ||
| 96 | compatible: | ||
| 97 | enum: | ||
| 98 | - qcom,sm8550-lpass-wsa-macro | ||
| 99 | then: | ||
| 100 | properties: | ||
| 101 | clocks: | ||
| 102 | minItems: 4 | ||
| 103 | maxItems: 4 | ||
| 104 | clock-names: | ||
| 105 | items: | ||
| 106 | - const: mclk | ||
| 107 | - const: macro | ||
| 108 | - const: dcodec | ||
| 109 | - const: fsgen | ||
| 110 | |||
| 92 | unevaluatedProperties: false | 111 | unevaluatedProperties: false |
| 93 | 112 | ||
| 94 | examples: | 113 | examples: |
| @@ -56,7 +56,7 @@ patternProperties: · 55 unmodified lines | |||
| 56 | Compress offload dai. | 56 | Compress offload dai. |
| 57 | 57 | ||
| 58 | dependencies: | 58 | dependencies: |
| 59 | is-compress-dai: ["direction"] | 59 | is-compress-dai: [ direction ] |
| 60 | 60 | ||
| 61 | required: | 61 | required: |
| 62 | - reg | 62 | - reg |
| @@ -1,123 +0,0 @@ | |||
| 1 | QCOM WCD9335 Codec | ||
| 2 | |||
| 3 | Qualcomm WCD9335 Codec is a standalone Hi-Fi audio codec IC, supports | ||
| 4 | Qualcomm Technologies, Inc. (QTI) multimedia solutions, including | ||
| 5 | the MSM8996, MSM8976, and MSM8956 chipsets. It has in-built | ||
| 6 | Soundwire controller, interrupt mux. It supports both I2S/I2C and | ||
| 7 | SLIMbus audio interfaces. | ||
| 8 | |||
| 9 | Required properties with SLIMbus Interface: | ||
| 10 | |||
| 11 | - compatible: | ||
| 12 | Usage: required | ||
| 13 | Value type: <stringlist> | ||
| 14 | Definition: For SLIMbus interface it should be "slimMID,PID", | ||
| 15 | textual representation of Manufacturer ID, Product Code, | ||
| 16 | shall be in lower case hexadecimal with leading zeroes | ||
| 17 | suppressed. Refer to slimbus/bus.txt for details. | ||
| 18 | Should be: | ||
| 19 | "slim217,1a0" for MSM8996 and APQ8096 SoCs with SLIMbus. | ||
| 20 | |||
| 21 | - reg | ||
| 22 | Usage: required | ||
| 23 | Value type: <u32 u32> | ||
| 24 | Definition: Should be ('Device index', 'Instance ID') | ||
| 25 | |||
| 26 | - interrupts | ||
| 27 | Usage: required | ||
| 28 | Value type: <prop-encoded-array> | ||
| 29 | Definition: Interrupts via WCD INTR1 and INTR2 pins | ||
| 30 | |||
| 31 | - interrupt-names: | ||
| 32 | Usage: required | ||
| 33 | Value type: <String array> | ||
| 34 | Definition: Interrupt names of WCD INTR1 and INTR2 | ||
| 35 | Should be: "intr1", "intr2" | ||
| 36 | |||
| 37 | - reset-gpios: | ||
| 38 | Usage: required | ||
| 39 | Value type: <String Array> | ||
| 40 | Definition: Reset gpio line | ||
| 41 | |||
| 42 | - slim-ifc-dev: | ||
| 43 | Usage: required | ||
| 44 | Value type: <phandle> | ||
| 45 | Definition: SLIM interface device | ||
| 46 | |||
| 47 | - clocks: | ||
| 48 | Usage: required | ||
| 49 | Value type: <prop-encoded-array> | ||
| 50 | Definition: See clock-bindings.txt section "consumers". List of | ||
| 51 | three clock specifiers for mclk, mclk2 and slimbus clock. | ||
| 52 | |||
| 53 | - clock-names: | ||
| 54 | Usage: required | ||
| 55 | Value type: <string> | ||
| 56 | Definition: Must contain "mclk", "mclk2" and "slimbus" strings. | ||
| 57 | |||
| 58 | - vdd-buck-supply: | ||
| 59 | Usage: required | ||
| 60 | Value type: <phandle> | ||
| 61 | Definition: Should contain a reference to the 1.8V buck supply | ||
| 62 | |||
| 63 | - vdd-buck-sido-supply: | ||
| 64 | Usage: required | ||
| 65 | Value type: <phandle> | ||
| 66 | Definition: Should contain a reference to the 1.8V SIDO buck supply | ||
| 67 | |||
| 68 | - vdd-rx-supply: | ||
| 69 | Usage: required | ||
| 70 | Value type: <phandle> | ||
| 71 | Definition: Should contain a reference to the 1.8V rx supply | ||
| 72 | |||
| 73 | - vdd-tx-supply: | ||
| 74 | Usage: required | ||
| 75 | Value type: <phandle> | ||
| 76 | Definition: Should contain a reference to the 1.8V tx supply | ||
| 77 | |||
| 78 | - vdd-vbat-supply: | ||
| 79 | Usage: Optional | ||
| 80 | Value type: <phandle> | ||
| 81 | Definition: Should contain a reference to the vbat supply | ||
| 82 | |||
| 83 | - vdd-micbias-supply: | ||
| 84 | Usage: required | ||
| 85 | Value type: <phandle> | ||
| 86 | Definition: Should contain a reference to the micbias supply | ||
| 87 | |||
| 88 | - vdd-io-supply: | ||
| 89 | Usage: required | ||
| 90 | Value type: <phandle> | ||
| 91 | Definition: Should contain a reference to the 1.8V io supply | ||
| 92 | |||
| 93 | - interrupt-controller: | ||
| 94 | Usage: required | ||
| 95 | Definition: Indicating that this is a interrupt controller | ||
| 96 | |||
| 97 | - #interrupt-cells: | ||
| 98 | Usage: required | ||
| 99 | Value type: <int> | ||
| 100 | Definition: should be 1 | ||
| 101 | |||
| 102 | #sound-dai-cells | ||
| 103 | Usage: required | ||
| 104 | Value type: <u32> | ||
| 105 | Definition: Must be 1 | ||
| 106 | |||
| 107 | audio-codec@1{ | ||
| 108 | compatible = "slim217,1a0"; | ||
| 109 | reg = <1 0>; | ||
| 110 | interrupts = <&msmgpio 54 IRQ_TYPE_LEVEL_HIGH>; | ||
| 111 | interrupt-names = "intr2" | ||
| 112 | reset-gpios = <&msmgpio 64 GPIO_ACTIVE_LOW>; | ||
| 113 | slim-ifc-dev = <&wc9335_ifd>; | ||
| 114 | clock-names = "mclk", "native"; | ||
| 115 | clocks = <&rpmcc RPM_SMD_DIV_CLK1>, | ||
| 116 | <&rpmcc RPM_SMD_BB_CLK1>; | ||
| 117 | vdd-buck-supply = <&pm8994_s4>; | ||
| 118 | vdd-rx-supply = <&pm8994_s4>; | ||
| 119 | vdd-buck-sido-supply = <&pm8994_s4>; | ||
| 120 | vdd-tx-supply = <&pm8994_s4>; | ||
| 121 | vdd-io-supply = <&pm8994_s4>; | ||
| 122 | #sound-dai-cells = <1>; | ||
| 123 | } | ||
| @@ -0,0 +1,156 @@ | |||
| 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,wcd9335.yaml# | ||
| 5 | $schema: http://devicetree.org/meta-schemas/core.yaml# | ||
| 6 | |||
| 7 | title: Qualcomm WCD9335 Audio Codec | ||
| 8 | |||
| 9 | maintainers: | ||
| 10 | - Srinivas Kandagatla <srinivas.kandagatla@linaro.org> | ||
| 11 | |||
| 12 | description: | ||
| 13 | Qualcomm WCD9335 Codec is a standalone Hi-Fi audio codec IC with in-built | ||
| 14 | Soundwire controller and interrupt mux. It supports both I2S/I2C and SLIMbus | ||
| 15 | audio interfaces. | ||
| 16 | |||
| 17 | properties: | ||
| 18 | compatible: | ||
| 19 | const: slim217,1a0 | ||
| 20 | |||
| 21 | reg: | ||
| 22 | maxItems: 1 | ||
| 23 | |||
| 24 | clocks: | ||
| 25 | maxItems: 2 | ||
| 26 | |||
| 27 | clock-names: | ||
| 28 | items: | ||
| 29 | - const: mclk | ||
| 30 | - const: slimbus | ||
| 31 | |||
| 32 | interrupts: | ||
| 33 | maxItems: 2 | ||
| 34 | |||
| 35 | interrupt-names: | ||
| 36 | items: | ||
| 37 | - const: intr1 | ||
| 38 | - const: intr2 | ||
| 39 | |||
| 40 | interrupt-controller: true | ||
| 41 | |||
| 42 | '#interrupt-cells': | ||
| 43 | const: 1 | ||
| 44 | |||
| 45 | reset-gpios: | ||
| 46 | maxItems: 1 | ||
| 47 | |||
| 48 | slim-ifc-dev: | ||
| 49 | description: SLIM IFC device interface | ||
| 50 | $ref: /schemas/types.yaml#/definitions/phandle | ||
| 51 | |||
| 52 | '#sound-dai-cells': | ||
| 53 | const: 1 | ||
| 54 | |||
| 55 | vdd-buck-supply: | ||
| 56 | description: 1.8V buck supply | ||
| 57 | |||
| 58 | vdd-buck-sido-supply: | ||
| 59 | description: 1.8V SIDO buck supply | ||
| 60 | |||
| 61 | vdd-io-supply: | ||
| 62 | description: 1.8V I/O supply | ||
| 63 | |||
| 64 | vdd-micbias-supply: | ||
| 65 | description: micbias supply | ||
| 66 | |||
| 67 | vdd-rx-supply: | ||
| 68 | description: 1.8V rx supply | ||
| 69 | |||
| 70 | vdd-tx-supply: | ||
| 71 | description: 1.8V tx supply | ||
| 72 | |||
| 73 | vdd-vbat-supply: | ||
| 74 | description: vbat supply | ||
| 75 | |||
| 76 | required: | ||
| 77 | - compatible | ||
| 78 | - reg | ||
| 79 | |||
| 80 | allOf: | ||
| 81 | - $ref: dai-common.yaml# | ||
| 82 | - if: | ||
| 83 | required: | ||
| 84 | - slim-ifc-dev | ||
| 85 | then: | ||
| 86 | required: | ||
| 87 | - clocks | ||
| 88 | - clock-names | ||
| 89 | - interrupts | ||
| 90 | - interrupt-names | ||
| 91 | - interrupt-controller | ||
| 92 | - '#interrupt-cells' | ||
| 93 | - reset-gpios | ||
| 94 | - slim-ifc-dev | ||
| 95 | - '#sound-dai-cells' | ||
| 96 | - vdd-buck-supply | ||
| 97 | - vdd-buck-sido-supply | ||
| 98 | - vdd-io-supply | ||
| 99 | - vdd-rx-supply | ||
| 100 | - vdd-tx-supply | ||
| 101 | else: | ||
| 102 | properties: | ||
| 103 | clocks: false | ||
| 104 | clock-names: false | ||
| 105 | interrupts: false | ||
| 106 | interrupt-names: false | ||
| 107 | interrupt-controller: false | ||
| 108 | '#interrupt-cells': false | ||
| 109 | reset-gpios: false | ||
| 110 | slim-ifc-dev: false | ||
| 111 | '#sound-dai-cells': false | ||
| 112 | vdd-buck-supply: false | ||
| 113 | vdd-buck-sido-supply: false | ||
| 114 | vdd-io-supply: false | ||
| 115 | vdd-micbias-supply: false | ||
| 116 | vdd-rx-supply: false | ||
| 117 | vdd-tx-supply: false | ||
| 118 | vdd-vbat-supply: false | ||
| 119 | |||
| 120 | additionalProperties: false | ||
| 121 | |||
| 122 | examples: | ||
| 123 | - | | ||
| 124 | #include <dt-bindings/clock/qcom,rpmcc.h> | ||
| 125 | #include <dt-bindings/gpio/gpio.h> | ||
| 126 | #include <dt-bindings/interrupt-controller/irq.h> | ||
| 127 | |||
| 128 | tasha_ifd: codec@0,0 { | ||
| 129 | compatible = "slim217,1a0"; | ||
| 130 | reg = <0 0>; | ||
| 131 | }; | ||
| 132 | |||
| 133 | codec@1,0 { | ||
| 134 | compatible = "slim217,1a0"; | ||
| 135 | reg = <1 0>; | ||
| 136 | |||
| 137 | clock-names = "mclk", "slimbus"; | ||
| 138 | clocks = <&div1_mclk>, <&rpmcc RPM_SMD_BB_CLK1>; | ||
| 139 | |||
| 140 | interrupt-parent = <&tlmm>; | ||
| 141 | interrupts = <54 IRQ_TYPE_LEVEL_HIGH>, | ||
| 142 | <53 IRQ_TYPE_LEVEL_HIGH>; | ||
| 143 | interrupt-names = "intr1", "intr2"; | ||
| 144 | interrupt-controller; | ||
| 145 | #interrupt-cells = <1>; | ||
| 146 | |||
| 147 | reset-gpios = <&tlmm 64 GPIO_ACTIVE_LOW>; | ||
| 148 | slim-ifc-dev = <&tasha_ifd>; | ||
| 149 | #sound-dai-cells = <1>; | ||
| 150 | |||
| 151 | vdd-buck-supply = <&vreg_s4a_1p8>; | ||
| 152 | vdd-buck-sido-supply = <&vreg_s4a_1p8>; | ||
| 153 | vdd-tx-supply = <&vreg_s4a_1p8>; | ||
| 154 | vdd-rx-supply = <&vreg_s4a_1p8>; | ||
| 155 | vdd-io-supply = <&vreg_s4a_1p8>; | ||
| 156 | }; | ||
| @@ -152,6 +152,7 @@ required: · 151 unmodified lines | |||
| 152 | - reg | 152 | - reg |
| 153 | 153 | ||
| 154 | allOf: | 154 | allOf: |
| 155 | - $ref: dai-common.yaml# | ||
| 155 | - if: | 156 | - if: |
| 156 | required: | 157 | required: |
| 157 | - slim-ifc-dev | 158 | - slim-ifc-dev |
| @@ -0,0 +1,63 @@ | |||
| 1 | # SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause | ||
| 2 | %YAML 1.2 | ||
| 3 | --- | ||
| 4 | $id: http://devicetree.org/schemas/sound/realtek,alc5632.yaml# | ||
| 5 | $schema: http://devicetree.org/meta-schemas/core.yaml# | ||
| 6 | |||
| 7 | title: ALC5632 audio CODEC | ||
| 8 | |||
| 9 | description: | | ||
| 10 | Pins on the device (for linking into audio routes): | ||
| 11 | * SPK_OUTP | ||
| 12 | * SPK_OUTN | ||
| 13 | * HP_OUT_L | ||
| 14 | * HP_OUT_R | ||
| 15 | * AUX_OUT_P | ||
| 16 | * AUX_OUT_N | ||
| 17 | * LINE_IN_L | ||
| 18 | * LINE_IN_R | ||
| 19 | * PHONE_P | ||
| 20 | * PHONE_N | ||
| 21 | * MIC1_P | ||
| 22 | * MIC1_N | ||
| 23 | * MIC2_P | ||
| 24 | * MIC2_N | ||
| 25 | * MICBIAS1 | ||
| 26 | * DMICDAT | ||
| 27 | |||
| 28 | maintainers: | ||
| 29 | - Leon Romanovsky <leon@leon.nu> | ||
| 30 | |||
| 31 | properties: | ||
| 32 | compatible: | ||
| 33 | const: realtek,alc5632 | ||
| 34 | |||
| 35 | reg: | ||
| 36 | maxItems: 1 | ||
| 37 | |||
| 38 | '#gpio-cells': | ||
| 39 | const: 2 | ||
| 40 | |||
| 41 | gpio-controller: true | ||
| 42 | |||
| 43 | required: | ||
| 44 | - compatible | ||
| 45 | - reg | ||
| 46 | - '#gpio-cells' | ||
| 47 | - gpio-controller | ||
| 48 | |||
| 49 | additionalProperties: false | ||
| 50 | |||
| 51 | examples: | ||
| 52 | - | | ||
| 53 | #include <dt-bindings/gpio/gpio.h> | ||
| 54 | i2c { | ||
| 55 | #address-cells = <1>; | ||
| 56 | #size-cells = <0>; | ||
| 57 | codec@1a { | ||
| 58 | compatible = "realtek,alc5632"; | ||
| 59 | reg = <0x1a>; | ||
| 60 | gpio-controller; | ||
| 61 | #gpio-cells = <2>; | ||
| 62 | }; | ||
| 63 | }; | ||
| @@ -101,17 +101,7 @@ properties: · 100 unmodified lines | |||
| 101 | 101 | ||
| 102 | clock-names: | 102 | clock-names: |
| 103 | description: List of necessary clock names. | 103 | description: List of necessary clock names. |
| 104 | minItems: 1 | 104 | # details are defined below |
| 105 | maxItems: 31 | ||
| 106 | items: | ||
| 107 | oneOf: | ||
| 108 | - const: ssi-all | ||
| 109 | - pattern: '^ssi\.[0-9]$' | ||
| 110 | - pattern: '^src\.[0-9]$' | ||
| 111 | - pattern: '^mix\.[0-1]$' | ||
| 112 | - pattern: '^ctu\.[0-1]$' | ||
| 113 | - pattern: '^dvc\.[0-1]$' | ||
| 114 | - pattern: '^clk_(a|b|c|i)$' | ||
| 115 | 105 | ||
| 116 | ports: | 106 | ports: |
| 117 | $ref: audio-graph-port.yaml#/definitions/port-base | 107 | $ref: audio-graph-port.yaml#/definitions/port-base |
| @@ -155,7 +145,7 @@ properties: · 37 unmodified lines | |||
| 155 | dmas: | 145 | dmas: |
| 156 | maxItems: 1 | 146 | maxItems: 1 |
| 157 | dma-names: | 147 | dma-names: |
| 158 | const: "tx" | 148 | const: tx |
| 159 | required: | 149 | required: |
| 160 | - dmas | 150 | - dmas |
| 161 | - dma-names | 151 | - dma-names |
| @@ -288,6 +278,11 @@ required: · 126 unmodified lines | |||
| 288 | 278 | ||
| 289 | allOf: | 279 | allOf: |
| 290 | - $ref: dai-common.yaml# | 280 | - $ref: dai-common.yaml# |
| 281 | |||
| 282 | # -------------------- | ||
| 283 | # reg/reg-names | ||
| 284 | # -------------------- | ||
| 285 | # for Gen1 | ||
| 291 | - if: | 286 | - if: |
| 292 | properties: | 287 | properties: |
| 293 | compatible: | 288 | compatible: |
| @@ -303,7 +298,15 @@ allOf: · 9 unmodified lines | |||
| 303 | - scu | 298 | - scu |
| 304 | - ssi | 299 | - ssi |
| 305 | - adg | 300 | - adg |
| 306 | else: | 301 | # for Gen2/Gen3 |
| 302 | - if: | ||
| 303 | properties: | ||
| 304 | compatible: | ||
| 305 | contains: | ||
| 306 | enum: | ||
| 307 | - renesas,rcar_sound-gen2 | ||
| 308 | - renesas,rcar_sound-gen3 | ||
| 309 | then: | ||
| 307 | properties: | 310 | properties: |
| 308 | reg: | 311 | reg: |
| 309 | minItems: 5 | 312 | minItems: 5 |
| @@ -315,35 +318,87 @@ allOf: · 5 unmodified lines | |||
| 315 | - ssiu | 318 | - ssiu |
| 316 | - ssi | 319 | - ssi |
| 317 | - audmapp | 320 | - audmapp |
| 321 | # for Gen4 | ||
| 322 | - if: | ||
| 323 | properties: | ||
| 324 | compatible: | ||
| 325 | contains: | ||
| 326 | const: renesas,rcar_sound-gen4 | ||
| 327 | then: | ||
| 328 | properties: | ||
| 329 | reg: | ||
| 330 | maxItems: 4 | ||
| 331 | reg-names: | ||
| 332 | items: | ||
| 333 | enum: | ||
| 334 | - adg | ||
| 335 | - ssiu | ||
| 336 | - ssi | ||
| 337 | - sdmc | ||
| 338 | |||
| 339 | # -------------------- | ||
| 340 | # clock-names | ||
| 341 | # -------------------- | ||
| 342 | - if: | ||
| 343 | properties: | ||
| 344 | compatible: | ||
| 345 | contains: | ||
| 346 | const: renesas,rcar_sound-gen4 | ||
| 347 | then: | ||
| 348 | properties: | ||
| 349 | clock-names: | ||
| 350 | maxItems: 3 | ||
| 351 | items: | ||
| 352 | enum: | ||
| 353 | - ssi.0 | ||
| 354 | - ssiu.0 | ||
| 355 | - clkin | ||
| 356 | else: | ||
| 357 | properties: | ||
| 358 | clock-names: | ||
| 359 | minItems: 1 | ||
| 360 | maxItems: 31 | ||
| 361 | items: | ||
| 362 | oneOf: | ||
| 363 | - const: ssi-all | ||
| 364 | - pattern: '^ssi\.[0-9]$' | ||
| 365 | - pattern: '^src\.[0-9]$' | ||
| 366 | - pattern: '^mix\.[0-1]$' | ||
| 367 | - pattern: '^ctu\.[0-1]$' | ||
| 368 | - pattern: '^dvc\.[0-1]$' | ||
| 369 | - pattern: '^clk_(a|b|c|i)$' | ||
| 318 | 370 | ||
| 319 | unevaluatedProperties: false | 371 | unevaluatedProperties: false |
| 320 | 372 | ||
| 321 | examples: | 373 | examples: |
| 322 | - | | 374 | - | |
| 375 | #include <dt-bindings/clock/r8a7790-cpg-mssr.h> | ||
| 376 | #include <dt-bindings/interrupt-controller/arm-gic.h> | ||
| 377 | #include <dt-bindings/power/r8a7790-sysc.h> | ||
| 323 | rcar_sound: sound@ec500000 { | 378 | rcar_sound: sound@ec500000 { |
| 324 | #sound-dai-cells = <1>; | 379 | #sound-dai-cells = <1>; |
| 325 | compatible = "renesas,rcar_sound-r8a7790", "renesas,rcar_sound-gen2"; | 380 | compatible = "renesas,rcar_sound-r8a7790", "renesas,rcar_sound-gen2"; |
| 326 | reg = <0xec500000 0x1000>, /* SCU */ | 381 | reg = <0xec500000 0x1000>, /* SCU */ |
| 327 | <0xec5a0000 0x100>, /* ADG */ | 382 | <0xec5a0000 0x100>, /* ADG */ |
| 328 | <0xec540000 0x1000>, /* SSIU */ | 383 | <0xec540000 0x1000>, /* SSIU */ |
| 329 | <0xec541000 0x1280>, /* SSI */ | 384 | <0xec541000 0x280>, /* SSI */ |
| 330 | <0xec740000 0x200>; /* Audio DMAC peri peri*/ | 385 | <0xec740000 0x200>; /* Audio DMAC peri peri*/ |
| 331 | reg-names = "scu", "adg", "ssiu", "ssi", "audmapp"; | 386 | reg-names = "scu", "adg", "ssiu", "ssi", "audmapp"; |
| 332 | 387 | ||
| 333 | clocks = <&mstp10_clks 1005>, /* SSI-ALL */ | 388 | clocks = <&cpg CPG_MOD 1005>, /* SSI-ALL */ |
| 334 | <&mstp10_clks 1006>, <&mstp10_clks 1007>, /* SSI9, SSI8 */ | 389 | <&cpg CPG_MOD 1006>, <&cpg CPG_MOD 1007>, /* SSI9, SSI8 */ |
| 335 | <&mstp10_clks 1008>, <&mstp10_clks 1009>, /* SSI7, SSI6 */ | 390 | <&cpg CPG_MOD 1008>, <&cpg CPG_MOD 1009>, /* SSI7, SSI6 */ |
| 336 | <&mstp10_clks 1010>, <&mstp10_clks 1011>, /* SSI5, SSI4 */ | 391 | <&cpg CPG_MOD 1010>, <&cpg CPG_MOD 1011>, /* SSI5, SSI4 */ |
| 337 | <&mstp10_clks 1012>, <&mstp10_clks 1013>, /* SSI3, SSI2 */ | 392 | <&cpg CPG_MOD 1012>, <&cpg CPG_MOD 1013>, /* SSI3, SSI2 */ |
| 338 | <&mstp10_clks 1014>, <&mstp10_clks 1015>, /* SSI1, SSI0 */ | 393 | <&cpg CPG_MOD 1014>, <&cpg CPG_MOD 1015>, /* SSI1, SSI0 */ |
| 339 | <&mstp10_clks 1022>, <&mstp10_clks 1023>, /* SRC9, SRC8 */ | 394 | <&cpg CPG_MOD 1022>, <&cpg CPG_MOD 1023>, /* SRC9, SRC8 */ |
| 340 | <&mstp10_clks 1024>, <&mstp10_clks 1025>, /* SRC7, SRC6 */ | 395 | <&cpg CPG_MOD 1024>, <&cpg CPG_MOD 1025>, /* SRC7, SRC6 */ |
| 341 | <&mstp10_clks 1026>, <&mstp10_clks 1027>, /* SRC5, SRC4 */ | 396 | <&cpg CPG_MOD 1026>, <&cpg CPG_MOD 1027>, /* SRC5, SRC4 */ |
| 342 | <&mstp10_clks 1028>, <&mstp10_clks 1029>, /* SRC3, SRC2 */ | 397 | <&cpg CPG_MOD 1028>, <&cpg CPG_MOD 1029>, /* SRC3, SRC2 */ |
| 343 | <&mstp10_clks 1030>, <&mstp10_clks 1031>, /* SRC1, SRC0 */ | 398 | <&cpg CPG_MOD 1030>, <&cpg CPG_MOD 1031>, /* SRC1, SRC0 */ |
| 344 | <&mstp10_clks 1020>, <&mstp10_clks 1021>, /* MIX1, MIX0 */ | 399 | <&cpg CPG_MOD 1020>, <&cpg CPG_MOD 1021>, /* MIX1, MIX0 */ |
| 345 | <&mstp10_clks 1020>, <&mstp10_clks 1021>, /* CTU1, CTU0 */ | 400 | <&cpg CPG_MOD 1020>, <&cpg CPG_MOD 1021>, /* CTU1, CTU0 */ |
| 346 | <&mstp10_clks 1019>, <&mstp10_clks 1018>, /* DVC0, DVC1 */ | 401 | <&cpg CPG_MOD 1019>, <&cpg CPG_MOD 1018>, /* DVC0, DVC1 */ |
| 347 | <&audio_clk_a>, <&audio_clk_b>, /* CLKA, CLKB */ | 402 | <&audio_clk_a>, <&audio_clk_b>, /* CLKA, CLKB */ |
| 348 | <&audio_clk_c>, <&audio_clk_i>; /* CLKC, CLKI */ | 403 | <&audio_clk_c>, <&audio_clk_i>; /* CLKC, CLKI */ |
| 349 | 404 | ||
| @@ -364,6 +419,17 @@ examples: · 14 unmodified lines | |||
| 364 | "clk_a", "clk_b", | 419 | "clk_a", "clk_b", |
| 365 | "clk_c", "clk_i"; | 420 | "clk_c", "clk_i"; |
| 366 | 421 | ||
| 422 | power-domains = <&sysc R8A7790_PD_ALWAYS_ON>; | ||
| 423 | |||
| 424 | resets = <&cpg 1005>, | ||
| 425 | <&cpg 1006>, <&cpg 1007>, <&cpg 1008>, <&cpg 1009>, | ||
| 426 | <&cpg 1010>, <&cpg 1011>, <&cpg 1012>, <&cpg 1013>, | ||
| 427 | <&cpg 1014>, <&cpg 1015>; | ||
| 428 | reset-names = "ssi-all", | ||
| 429 | "ssi.9", "ssi.8", "ssi.7", "ssi.6", | ||
| 430 | "ssi.5", "ssi.4", "ssi.3", "ssi.2", | ||
| 431 | "ssi.1", "ssi.0"; | ||
| 432 | |||
| 367 | rcar_sound,dvc { | 433 | rcar_sound,dvc { |
| 368 | dvc0: dvc-0 { | 434 | dvc0: dvc-0 { |
| 369 | dmas = <&audma0 0xbc>; | 435 | dmas = <&audma0 0xbc>; |
| @@ -396,7 +462,7 @@ examples: · 26 unmodified lines | |||
| 396 | status = "disabled"; | 462 | status = "disabled"; |
| 397 | }; | 463 | }; |
| 398 | src1: src-1 { | 464 | src1: src-1 { |
| 399 | interrupts = <0 353 0>; | 465 | interrupts = <GIC_SPI 353 IRQ_TYPE_LEVEL_HIGH>; |
| 400 | dmas = <&audma0 0x87>, <&audma1 0x9c>; | 466 | dmas = <&audma0 0x87>, <&audma1 0x9c>; |
| 401 | dma-names = "rx", "tx"; | 467 | dma-names = "rx", "tx"; |
| 402 | }; | 468 | }; |
| @@ -417,12 +483,12 @@ examples: · 14 unmodified lines | |||
| 417 | 483 | ||
| 418 | rcar_sound,ssi { | 484 | rcar_sound,ssi { |
| 419 | ssi0: ssi-0 { | 485 | ssi0: ssi-0 { |
| 420 | interrupts = <0 370 1>; | 486 | interrupts = <GIC_SPI 370 IRQ_TYPE_LEVEL_HIGH>; |
| 421 | dmas = <&audma0 0x01>, <&audma1 0x02>; | 487 | dmas = <&audma0 0x01>, <&audma1 0x02>; |
| 422 | dma-names = "rx", "tx"; | 488 | dma-names = "rx", "tx"; |
| 423 | }; | 489 | }; |
| 424 | ssi1: ssi-1 { | 490 | ssi1: ssi-1 { |
| 425 | interrupts = <0 371 1>; | 491 | interrupts = <GIC_SPI 371 IRQ_TYPE_LEVEL_HIGH>; |
| 426 | dmas = <&audma0 0x03>, <&audma1 0x04>; | 492 | dmas = <&audma0 0x03>, <&audma1 0x04>; |
| 427 | dma-names = "rx", "tx"; | 493 | dma-names = "rx", "tx"; |
| 428 | }; | 494 | }; |
| @@ -464,7 +530,6 @@ examples: · 35 unmodified lines | |||
| 464 | }; | 530 | }; |
| 465 | }; | 531 | }; |
| 466 | 532 | ||
| 467 | |||
| 468 | /* assume audio-graph */ | 533 | /* assume audio-graph */ |
| 469 | codec { | 534 | codec { |
| 470 | port { | 535 | port { |
| @@ -25,14 +25,18 @@ properties: · 24 unmodified lines | |||
| 25 | maxItems: 1 | 25 | maxItems: 1 |
| 26 | 26 | ||
| 27 | interrupts: | 27 | interrupts: |
| 28 | maxItems: 4 | 28 | minItems: 2 |
| 29 | maxItems: 3 | ||
| 29 | 30 | ||
| 30 | interrupt-names: | 31 | interrupt-names: |
| 31 | items: | 32 | oneOf: |
| 32 | - const: int_req | 33 | - items: |
| 33 | - const: dma_rx | 34 | - const: int_req |
| 34 | - const: dma_tx | 35 | - const: dma_rx |
| 35 | - const: dma_rt | 36 | - const: dma_tx |
| 37 | - items: | ||
| 38 | - const: int_req | ||
| 39 | - const: dma_rt | ||
| 36 | 40 | ||
| 37 | clocks: | 41 | clocks: |
| 38 | maxItems: 4 | 42 | maxItems: 4 |
| @@ -106,9 +110,8 @@ examples: · 67 unmodified lines | |||
| 106 | reg = <0x10049c00 0x400>; | 110 | reg = <0x10049c00 0x400>; |
| 107 | interrupts = <GIC_SPI 326 IRQ_TYPE_LEVEL_HIGH>, | 111 | interrupts = <GIC_SPI 326 IRQ_TYPE_LEVEL_HIGH>, |
| 108 | <GIC_SPI 327 IRQ_TYPE_EDGE_RISING>, | 112 | <GIC_SPI 327 IRQ_TYPE_EDGE_RISING>, |
| 109 | <GIC_SPI 328 IRQ_TYPE_EDGE_RISING>, | 113 | <GIC_SPI 328 IRQ_TYPE_EDGE_RISING>; |
| 110 | <GIC_SPI 329 IRQ_TYPE_EDGE_RISING>; | 114 | interrupt-names = "int_req", "dma_rx", "dma_tx"; |
| 111 | interrupt-names = "int_req", "dma_rx", "dma_tx", "dma_rt"; | ||
| 112 | clocks = <&cpg CPG_MOD R9A07G044_SSI0_PCLK2>, | 115 | clocks = <&cpg CPG_MOD R9A07G044_SSI0_PCLK2>, |
| 113 | <&cpg CPG_MOD R9A07G044_SSI0_PCLK_SFR>, | 116 | <&cpg CPG_MOD R9A07G044_SSI0_PCLK_SFR>, |
| 114 | <&audio_clk1>, | 117 | <&audio_clk1>, |
| @@ -86,6 +86,13 @@ properties: · 85 unmodified lines | |||
| 86 | - tx-m | 86 | - tx-m |
| 87 | - rx-m | 87 | - rx-m |
| 88 | 88 | ||
| 89 | port: | ||
| 90 | $ref: audio-graph-port.yaml# | ||
| 91 | unevaluatedProperties: false | ||
| 92 | |||
| 93 | power-domains: | ||
| 94 | maxItems: 1 | ||
| 95 | |||
| 89 | rockchip,grf: | 96 | rockchip,grf: |
| 90 | $ref: /schemas/types.yaml#/definitions/phandle | 97 | $ref: /schemas/types.yaml#/definitions/phandle |
| 91 | description: | 98 | description: |
| @@ -34,6 +34,7 @@ properties: · 33 unmodified lines | |||
| 34 | - rockchip,rk3366-i2s | 34 | - rockchip,rk3366-i2s |
| 35 | - rockchip,rk3368-i2s | 35 | - rockchip,rk3368-i2s |
| 36 | - rockchip,rk3399-i2s | 36 | - rockchip,rk3399-i2s |
| 37 | - rockchip,rk3588-i2s | ||
| 37 | - rockchip,rv1126-i2s | 38 | - rockchip,rv1126-i2s |
| 38 | - const: rockchip,rk3066-i2s | 39 | - const: rockchip,rk3066-i2s |
| 39 | 40 | ||
| @@ -82,6 +83,10 @@ properties: · 42 unmodified lines | |||
| 82 | resets: | 83 | resets: |
| 83 | maxItems: 2 | 84 | maxItems: 2 |
| 84 | 85 | ||
| 86 | port: | ||
| 87 | $ref: audio-graph-port.yaml# | ||
| 88 | unevaluatedProperties: false | ||
| 89 | |||
| 85 | rockchip,capture-channels: | 90 | rockchip,capture-channels: |
| 86 | $ref: /schemas/types.yaml#/definitions/uint32 | 91 | $ref: /schemas/types.yaml#/definitions/uint32 |
| 87 | default: 2 | 92 | default: 2 |
| @@ -50,7 +50,7 @@ properties: · 49 unmodified lines | |||
| 50 | description: The bias voltage to be used in mVolts. The voltage can take | 50 | description: The bias voltage to be used in mVolts. The voltage can take |
| 51 | values from 1.25V to 3V by 250mV steps. If this node is not mentioned | 51 | values from 1.25V to 3V by 250mV steps. If this node is not mentioned |
| 52 | or the value is unknown, then the value is set to 1.25V. | 52 | or the value is unknown, then the value is set to 1.25V. |
| 53 | $ref: "/schemas/types.yaml#/definitions/uint32" | 53 | $ref: /schemas/types.yaml#/definitions/uint32 |
| 54 | enum: [ 1250, 1500, 1750, 2000, 2250, 2500, 2750, 3000 ] | 54 | enum: [ 1250, 1500, 1750, 2000, 2250, 2500, 2750, 3000 ] |
| 55 | 55 | ||
| 56 | lrclk-strength: | 56 | lrclk-strength: |
| @@ -63,7 +63,7 @@ properties: · 6 unmodified lines | |||
| 63 | 1 = 1.66 mA 2.87 mA 4.02 mA | 63 | 1 = 1.66 mA 2.87 mA 4.02 mA |
| 64 | 2 = 3.33 mA 5.74 mA 8.03 mA | 64 | 2 = 3.33 mA 5.74 mA 8.03 mA |
| 65 | 3 = 4.99 mA 8.61 mA 12.05 mA | 65 | 3 = 4.99 mA 8.61 mA 12.05 mA |
| 66 | $ref: "/schemas/types.yaml#/definitions/uint32" | 66 | $ref: /schemas/types.yaml#/definitions/uint32 |
| 67 | enum: [ 0, 1, 2, 3 ] | 67 | enum: [ 0, 1, 2, 3 ] |
| 68 | 68 | ||
| 69 | sclk-strength: | 69 | sclk-strength: |
| @@ -76,7 +76,7 @@ properties: · 6 unmodified lines | |||
| 76 | 1 = 1.66 mA 2.87 mA 4.02 mA | 76 | 1 = 1.66 mA 2.87 mA 4.02 mA |
| 77 | 2 = 3.33 mA 5.74 mA 8.03 mA | 77 | 2 = 3.33 mA 5.74 mA 8.03 mA |
| 78 | 3 = 4.99 mA 8.61 mA 12.05 mA | 78 | 3 = 4.99 mA 8.61 mA 12.05 mA |
| 79 | $ref: "/schemas/types.yaml#/definitions/uint32" | 79 | $ref: /schemas/types.yaml#/definitions/uint32 |
| 80 | enum: [ 0, 1, 2, 3 ] | 80 | enum: [ 0, 1, 2, 3 ] |
| 81 | 81 | ||
| 82 | port: | 82 | port: |
| @@ -78,7 +78,7 @@ definitions: · 77 unmodified lines | |||
| 78 | $ref: /schemas/types.yaml#/definitions/uint32 | 78 | $ref: /schemas/types.yaml#/definitions/uint32 |
| 79 | 79 | ||
| 80 | prefix: | 80 | prefix: |
| 81 | description: "device name prefix" | 81 | description: device name prefix |
| 82 | $ref: /schemas/types.yaml#/definitions/string | 82 | $ref: /schemas/types.yaml#/definitions/string |
| 83 | 83 | ||
| 84 | label: | 84 | label: |
| @@ -42,7 +42,7 @@ properties: · 41 unmodified lines | |||
| 42 | Specifies a phandle to soc-glue, which is used for changing mode of S/PDIF | 42 | Specifies a phandle to soc-glue, which is used for changing mode of S/PDIF |
| 43 | signal pin to output from Hi-Z. This property is optional if you use I2S | 43 | signal pin to output from Hi-Z. This property is optional if you use I2S |
| 44 | signal pins only. | 44 | signal pins only. |
| 45 | $ref: "/schemas/types.yaml#/definitions/phandle" | 45 | $ref: /schemas/types.yaml#/definitions/phandle |
| 46 | 46 | ||
| 47 | "#sound-dai-cells": | 47 | "#sound-dai-cells": |
| 48 | const: 1 | 48 | const: 1 |
| @@ -12,6 +12,7 @@ Required properties: · 11 unmodified lines | |||
| 12 | - "ti,tas5717", | 12 | - "ti,tas5717", |
| 13 | - "ti,tas5719", | 13 | - "ti,tas5719", |
| 14 | - "ti,tas5721" | 14 | - "ti,tas5721" |
| 15 | - "ti,tas5733" | ||
| 15 | - reg: The I2C address of the device | 16 | - reg: The I2C address of the device |
| 16 | - #sound-dai-cells: must be equal to 0 | 17 | - #sound-dai-cells: must be equal to 0 |
| 17 | 18 | ||
| @@ -0,0 +1,41 @@ | |||
| 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,wm8510.yaml# | ||
| 5 | $schema: http://devicetree.org/meta-schemas/core.yaml# | ||
| 6 | |||
| 7 | title: WM8510 audio CODEC | ||
| 8 | |||
| 9 | maintainers: | ||
| 10 | - patches@opensource.cirrus.com | ||
| 11 | |||
| 12 | allOf: | ||
| 13 | - $ref: dai-common.yaml# | ||
| 14 | |||
| 15 | properties: | ||
| 16 | compatible: | ||
| 17 | const: wlf,wm8510 | ||
| 18 | |||
| 19 | reg: | ||
| 20 | maxItems: 1 | ||
| 21 | |||
| 22 | "#sound-dai-cells": | ||
| 23 | const: 0 | ||
| 24 | |||
| 25 | required: | ||
| 26 | - compatible | ||
| 27 | - reg | ||
| 28 | |||
| 29 | unevaluatedProperties: false | ||
| 30 | |||
| 31 | examples: | ||
| 32 | - | | ||
| 33 | i2c { | ||
| 34 | #address-cells = <1>; | ||
| 35 | #size-cells = <0>; | ||
| 36 | |||
| 37 | codec@1a { | ||
| 38 | compatible = "wlf,wm8510"; | ||
| 39 | reg = <0x1a>; | ||
| 40 | }; | ||
| 41 | }; | ||
| @@ -0,0 +1,40 @@ | |||
| 1 | # SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause) | ||
| 2 | %YAML 1.2 | ||
| 3 | --- | ||
| 4 | $id: http://devicetree.org/schemas/sound/wlf,wm8523.yaml# | ||
| 5 | $schema: http://devicetree.org/meta-schemas/core.yaml# | ||
| 6 | |||
| 7 | title: WM8523 audio CODEC | ||
| 8 | |||
| 9 | maintainers: | ||
| 10 | - patches@opensource.cirrus.com | ||
| 11 | |||
| 12 | allOf: | ||
| 13 | - $ref: dai-common.yaml# | ||
| 14 | |||
| 15 | properties: | ||
| 16 | compatible: | ||
| 17 | const: wlf,wm8523 | ||
| 18 | |||
| 19 | reg: | ||
| 20 | maxItems: 1 | ||
| 21 | |||
| 22 | "#sound-dai-cells": | ||
| 23 | const: 0 | ||
| 24 | |||
| 25 | required: | ||
| 26 | - compatible | ||
| 27 | - reg | ||
| 28 | |||
| 29 | unevaluatedProperties: false | ||
| 30 | |||
| 31 | examples: | ||
| 32 | - | | ||
| 33 | i2c { | ||
| 34 | #address-cells = <1>; | ||
| 35 | #size-cells = <0>; | ||
| 36 | codec@1a { | ||
| 37 | compatible = "wlf,wm8523"; | ||
| 38 | reg = <0x1a>; | ||
| 39 | }; | ||
| 40 | }; | ||
| @@ -0,0 +1,40 @@ | |||
| 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,wm8524.yaml# | ||
| 5 | $schema: http://devicetree.org/meta-schemas/core.yaml# | ||
| 6 | |||
| 7 | title: Wolfson WM8524 24-bit 192KHz Stereo DAC | ||
| 8 | |||
| 9 | maintainers: | ||
| 10 | - patches@opensource.cirrus.com | ||
| 11 | |||
| 12 | allOf: | ||
| 13 | - $ref: dai-common.yaml# | ||
| 14 | |||
| 15 | properties: | ||
| 16 | compatible: | ||
| 17 | const: wlf,wm8524 | ||
| 18 | |||
| 19 | "#sound-dai-cells": | ||
| 20 | const: 0 | ||
| 21 | |||
| 22 | wlf,mute-gpios: | ||
| 23 | maxItems: 1 | ||
| 24 | description: | ||
| 25 | a GPIO spec for the MUTE pin. | ||
| 26 | |||
| 27 | required: | ||
| 28 | - compatible | ||
| 29 | - wlf,mute-gpios | ||
| 30 | |||
| 31 | unevaluatedProperties: false | ||
| 32 | |||
| 33 | examples: | ||
| 34 | - | | ||
| 35 | #include <dt-bindings/gpio/gpio.h> | ||
| 36 | |||
| 37 | wm8524: codec { | ||
| 38 | compatible = "wlf,wm8524"; | ||
| 39 | wlf,mute-gpios = <&gpio1 8 GPIO_ACTIVE_LOW>; | ||
| 40 | }; | ||
| @@ -0,0 +1,42 @@ | |||
| 1 | # SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause) | ||
| 2 | %YAML 1.2 | ||
| 3 | --- | ||
| 4 | $id: http://devicetree.org/schemas/sound/wlf,wm8580.yaml# | ||
| 5 | $schema: http://devicetree.org/meta-schemas/core.yaml# | ||
| 6 | |||
| 7 | title: WM8580 and WM8581 audio CODEC | ||
| 8 | |||
| 9 | maintainers: | ||
| 10 | - patches@opensource.cirrus.com | ||
| 11 | |||
| 12 | allOf: | ||
| 13 | - $ref: dai-common.yaml# | ||
| 14 | |||
| 15 | properties: | ||
| 16 | compatible: | ||
| 17 | enum: | ||
| 18 | - wlf,wm8580 | ||
| 19 | - wlf,wm8581 | ||
| 20 | |||
| 21 | reg: | ||
| 22 | maxItems: 1 | ||
| 23 | |||
| 24 | "#sound-dai-cells": | ||
| 25 | const: 0 | ||
| 26 | |||
| 27 | required: | ||
| 28 | - compatible | ||
| 29 | - reg | ||
| 30 | |||
| 31 | unevaluatedProperties: false | ||
| 32 | |||
| 33 | examples: | ||
| 34 | - | | ||
| 35 | i2c { | ||
| 36 | #address-cells = <1>; | ||
| 37 | #size-cells = <0>; | ||
| 38 | codec@1a { | ||
| 39 | compatible = "wlf,wm8580"; | ||
| 40 | reg = <0x1a>; | ||
| 41 | }; | ||
| 42 | }; | ||
| @@ -0,0 +1,40 @@ | |||
| 1 | # SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause) | ||
| 2 | %YAML 1.2 | ||
| 3 | --- | ||
| 4 | $id: http://devicetree.org/schemas/sound/wlf,wm8711.yaml# | ||
| 5 | $schema: http://devicetree.org/meta-schemas/core.yaml# | ||
| 6 | |||
| 7 | title: WM8711 audio CODEC | ||
| 8 | |||
| 9 | maintainers: | ||
| 10 | - patches@opensource.cirrus.com | ||
| 11 | |||
| 12 | allOf: | ||
| 13 | - $ref: dai-common.yaml# | ||
| 14 | |||
| 15 | properties: | ||
| 16 | compatible: | ||
| 17 | const: wlf,wm8711 | ||
| 18 | |||
| 19 | reg: | ||
| 20 | maxItems: 1 | ||
| 21 | |||
| 22 | "#sound-dai-cells": | ||
| 23 | const: 0 | ||
| 24 | |||
| 25 | required: | ||
| 26 | - compatible | ||
| 27 | - reg | ||
| 28 | |||
| 29 | unevaluatedProperties: false | ||
| 30 | |||
| 31 | examples: | ||
| 32 | - | | ||
| 33 | i2c { | ||
| 34 | #address-cells = <1>; | ||
| 35 | #size-cells = <0>; | ||
| 36 | codec@1a { | ||
| 37 | compatible = "wlf,wm8711"; | ||
| 38 | reg = <0x1a>; | ||
| 39 | }; | ||
| 40 | }; | ||
| @@ -0,0 +1,40 @@ | |||
| 1 | # SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause) | ||
| 2 | %YAML 1.2 | ||
| 3 | --- | ||
| 4 | $id: http://devicetree.org/schemas/sound/wlf,wm8728.yaml# | ||
| 5 | $schema: http://devicetree.org/meta-schemas/core.yaml# | ||
| 6 | |||
| 7 | title: WM8728 audio CODEC | ||
| 8 | |||
| 9 | maintainers: | ||
| 10 | - patches@opensource.cirrus.com | ||
| 11 | |||
| 12 | allOf: | ||
| 13 | - $ref: dai-common.yaml# | ||
| 14 | |||
| 15 | properties: | ||
| 16 | compatible: | ||
| 17 | const: wlf,wm8728 | ||
| 18 | |||
| 19 | reg: | ||
| 20 | maxItems: 1 | ||
| 21 | |||
| 22 | "#sound-dai-cells": | ||
| 23 | const: 0 | ||
| 24 | |||
| 25 | required: | ||
| 26 | - compatible | ||
| 27 | - reg | ||
| 28 | |||
| 29 | unevaluatedProperties: false | ||
| 30 | |||
| 31 | examples: | ||
| 32 | - | | ||
| 33 | i2c { | ||
| 34 | #address-cells = <1>; | ||
| 35 | #size-cells = <0>; | ||
| 36 | codec@1a { | ||
| 37 | compatible = "wlf,wm8728"; | ||
| 38 | reg = <0x1a>; | ||
| 39 | }; | ||
| 40 | }; | ||
| @@ -0,0 +1,40 @@ | |||
| 1 | # SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause) | ||
| 2 | %YAML 1.2 | ||
| 3 | --- | ||
| 4 | $id: http://devicetree.org/schemas/sound/wlf,wm8737.yaml# | ||
| 5 | $schema: http://devicetree.org/meta-schemas/core.yaml# | ||
| 6 | |||
| 7 | title: WM8737 audio CODEC | ||
| 8 | |||
| 9 | maintainers: | ||
| 10 | - patches@opensource.cirrus.com | ||
| 11 | |||
| 12 | allOf: | ||
| 13 | - $ref: dai-common.yaml# | ||
| 14 | |||
| 15 | properties: | ||
| 16 | compatible: | ||
| 17 | const: wlf,wm8737 | ||
| 18 | |||
| 19 | reg: | ||
| 20 | maxItems: 1 | ||
| 21 | |||
| 22 | "#sound-dai-cells": | ||
| 23 | const: 0 | ||
| 24 | |||
| 25 | required: | ||
| 26 | - compatible | ||
| 27 | - reg | ||
| 28 | |||
| 29 | unevaluatedProperties: false | ||
| 30 | |||
| 31 | examples: | ||
| 32 | - | | ||
| 33 | i2c { | ||
| 34 | #address-cells = <1>; | ||
| 35 | #size-cells = <0>; | ||
| 36 | codec@1a { | ||
| 37 | compatible = "wlf,wm8737"; | ||
| 38 | reg = <0x1a>; | ||
| 39 | }; | ||
| 40 | }; | ||
| @@ -0,0 +1,62 @@ | |||
| 1 | # SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause) | ||
| 2 | %YAML 1.2 | ||
| 3 | --- | ||
| 4 | $id: http://devicetree.org/schemas/sound/wlf,wm8753.yaml# | ||
| 5 | $schema: http://devicetree.org/meta-schemas/core.yaml# | ||
| 6 | |||
| 7 | title: WM8753 audio CODEC | ||
| 8 | |||
| 9 | description: | | ||
| 10 | Pins on the device (for linking into audio routes): | ||
| 11 | * LOUT1 | ||
| 12 | * LOUT2 | ||
| 13 | * ROUT1 | ||
| 14 | * ROUT2 | ||
| 15 | * MONO1 | ||
| 16 | * MONO2 | ||
| 17 | * OUT3 | ||
| 18 | * OUT4 | ||
| 19 | * LINE1 | ||
| 20 | * LINE2 | ||
| 21 | * RXP | ||
| 22 | * RXN | ||
| 23 | * ACIN | ||
| 24 | * ACOP | ||
| 25 | * MIC1N | ||
| 26 | * MIC1 | ||
| 27 | * MIC2N | ||
| 28 | * MIC2 | ||
| 29 | * Mic Bias | ||
| 30 | |||
| 31 | maintainers: | ||
| 32 | - patches@opensource.cirrus.com | ||
| 33 | |||
| 34 | allOf: | ||
| 35 | - $ref: dai-common.yaml# | ||
| 36 | |||
| 37 | properties: | ||
| 38 | compatible: | ||
| 39 | const: wlf,wm8753 | ||
| 40 | |||
| 41 | reg: | ||
| 42 | maxItems: 1 | ||
| 43 | |||
| 44 | "#sound-dai-cells": | ||
| 45 | const: 0 | ||
| 46 | |||
| 47 | required: | ||
| 48 | - compatible | ||
| 49 | - reg | ||
| 50 | |||
| 51 | unevaluatedProperties: false | ||
| 52 | |||
| 53 | examples: | ||
| 54 | - | | ||
| 55 | i2c { | ||
| 56 | #address-cells = <1>; | ||
| 57 | #size-cells = <0>; | ||
| 58 | codec@1a { | ||
| 59 | compatible = "wlf,wm8753"; | ||
| 60 | reg = <0x1a>; | ||
| 61 | }; | ||
| 62 | }; | ||
| @@ -0,0 +1,88 @@ | |||
| 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,wm8960.yaml# | ||
| 5 | $schema: http://devicetree.org/meta-schemas/core.yaml# | ||
| 6 | |||
| 7 | title: Wolfson WM8960 audio codec | ||
| 8 | |||
| 9 | maintainers: | ||
| 10 | - patches@opensource.cirrus.com | ||
| 11 | |||
| 12 | properties: | ||
| 13 | compatible: | ||
| 14 | const: wlf,wm8960 | ||
| 15 | |||
| 16 | reg: | ||
| 17 | maxItems: 1 | ||
| 18 | |||
| 19 | clocks: | ||
| 20 | maxItems: 1 | ||
| 21 | |||
| 22 | clock-names: | ||
| 23 | items: | ||
| 24 | - const: mclk | ||
| 25 | |||
| 26 | '#sound-dai-cells': | ||
| 27 | const: 0 | ||
| 28 | |||
| 29 | wlf,capless: | ||
| 30 | type: boolean | ||
| 31 | description: | ||
| 32 | If present, OUT3 pin will be enabled and disabled together with HP_L and | ||
| 33 | HP_R pins in response to jack detect events. | ||
| 34 | |||
| 35 | wlf,gpio-cfg: | ||
| 36 | $ref: /schemas/types.yaml#/definitions/uint32-array | ||
| 37 | maxItems: 2 | ||
| 38 | description: | | ||
| 39 | A list of GPIO configuration register values. | ||
| 40 | - gpio-cfg[0]: ALRCGPIO of R9 (Audio interface) | ||
| 41 | - gpio-cfg[1]: {GPIOPOL:GPIOSEL[2:0]} of R48 (Additional Control 4). | ||
| 42 | |||
| 43 | wlf,hp-cfg: | ||
| 44 | $ref: /schemas/types.yaml#/definitions/uint32-array | ||
| 45 | maxItems: 3 | ||
| 46 | description: | | ||
| 47 | A list of headphone jack detect configuration register values: | ||
| 48 | - hp-cfg[0]: HPSEL[1:0] of R48 (Additional Control 4). | ||
| 49 | - hp-cfg[1]: {HPSWEN:HPSWPOL} of R24 (Additional Control 2). | ||
| 50 | - hp-cfg[2]: {TOCLKSEL:TOEN} of R23 (Additional Control 1). | ||
| 51 | |||
| 52 | wlf,shared-lrclk: | ||
| 53 | type: boolean | ||
| 54 | description: | ||
| 55 | If present, the LRCM bit of R24 (Additional control 2) gets set, | ||
| 56 | indicating that ADCLRC and DACLRC pins will be disabled only when ADC | ||
| 57 | (Left and Right) and DAC (Left and Right) are disabled. | ||
| 58 | When WM8960 works on synchronize mode and DACLRC pin is used to supply | ||
| 59 | frame clock, it will no frame clock for captrue unless enable DAC to | ||
| 60 | enable DACLRC pin. If shared-lrclk is present, no need to enable DAC for | ||
| 61 | captrue. | ||
| 62 | |||
| 63 | required: | ||
| 64 | - compatible | ||
| 65 | - reg | ||
| 66 | |||
| 67 | allOf: | ||
| 68 | - $ref: dai-common.yaml# | ||
| 69 | |||
| 70 | unevaluatedProperties: false | ||
| 71 | |||
| 72 | examples: | ||
| 73 | - | | ||
| 74 | i2c { | ||
| 75 | #address-cells = <1>; | ||
| 76 | #size-cells = <0>; | ||
| 77 | |||
| 78 | audio-codec@1a { | ||
| 79 | compatible = "wlf,wm8960"; | ||
| 80 | reg = <0x1a>; | ||
| 81 | clocks = <&clks 0>; | ||
| 82 | clock-names = "mclk"; | ||
| 83 | #sound-dai-cells = <0>; | ||
| 84 | wlf,hp-cfg = <3 2 3>; | ||
| 85 | wlf,gpio-cfg = <1 3>; | ||
| 86 | wlf,shared-lrclk; | ||
| 87 | }; | ||
| 88 | }; | ||
| @@ -0,0 +1,194 @@ | |||
| 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,wm8994.yaml# | ||
| 5 | $schema: http://devicetree.org/meta-schemas/core.yaml# | ||
| 6 | |||
| 7 | title: Wolfson WM1811/WM8994/WM8958 audio codecs | ||
| 8 | |||
| 9 | maintainers: | ||
| 10 | - Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org> | ||
| 11 | - patches@opensource.cirrus.com | ||
| 12 | |||
| 13 | description: | | ||
| 14 | These devices support both I2C and SPI (configured with pin strapping on the | ||
| 15 | board). | ||
| 16 | |||
| 17 | Pins on the device (for linking into audio routes): | ||
| 18 | IN1LN, IN1LP, IN2LN, IN2LP:VXRN, IN1RN, IN1RP, IN2RN, IN2RP:VXRP, SPKOUTLP, | ||
| 19 | SPKOUTLN, SPKOUTRP, SPKOUTRN, HPOUT1L, HPOUT1R, HPOUT2P, HPOUT2N, LINEOUT1P, | ||
| 20 | LINEOUT1N, LINEOUT2P, LINEOUT2N. | ||
| 21 | |||
| 22 | properties: | ||
| 23 | compatible: | ||
| 24 | enum: | ||
| 25 | - wlf,wm1811 | ||
| 26 | - wlf,wm8994 | ||
| 27 | - wlf,wm8958 | ||
| 28 | |||
| 29 | reg: | ||
| 30 | maxItems: 1 | ||
| 31 | |||
| 32 | clocks: | ||
| 33 | minItems: 1 | ||
| 34 | maxItems: 2 | ||
| 35 | |||
| 36 | clock-names: | ||
| 37 | minItems: 1 | ||
| 38 | items: | ||
| 39 | - const: MCLK1 | ||
| 40 | - const: MCLK2 | ||
| 41 | |||
| 42 | gpio-controller: true | ||
| 43 | |||
| 44 | '#gpio-cells': | ||
| 45 | const: 2 | ||
| 46 | |||
| 47 | interrupts: | ||
| 48 | maxItems: 1 | ||
| 49 | |||
| 50 | interrupt-controller: true | ||
| 51 | |||
| 52 | '#interrupt-cells': | ||
| 53 | const: 2 | ||
| 54 | description: | ||
| 55 | The first cell is the IRQ number. The second cell is the flags, encoded | ||
| 56 | as the trigger masks. | ||
| 57 | |||
| 58 | AVDD1-supply: true | ||
| 59 | AVDD2-supply: true | ||
| 60 | CPVDD-supply: true | ||
| 61 | DBVDD-supply: true | ||
| 62 | DBVDD1-supply: true | ||
| 63 | DBVDD2-supply: true | ||
| 64 | DBVDD3-supply: true | ||
| 65 | DCVDD-supply: true | ||
| 66 | LDO1VDD-supply: true | ||
| 67 | LDO2VDD-supply: true | ||
| 68 | SPKVDD1-supply: true | ||
| 69 | SPKVDD2-supply: true | ||
| 70 | |||
| 71 | '#sound-dai-cells': | ||
| 72 | const: 0 | ||
| 73 | |||
| 74 | wlf,gpio-cfg: | ||
| 75 | $ref: /schemas/types.yaml#/definitions/uint32-array | ||
| 76 | maxItems: 11 | ||
| 77 | description: | ||
| 78 | A list of GPIO configuration register values. If absent, no configuration | ||
| 79 | of these registers is performed. If any value is over 0xffff then the | ||
| 80 | register will be left as default. If present 11 values must be supplied. | ||
| 81 | |||
| 82 | wlf,micbias-cfg: | ||
| 83 | $ref: /schemas/types.yaml#/definitions/uint32-array | ||
| 84 | maxItems: 2 | ||
| 85 | description: | ||
| 86 | Two MICBIAS register values for WM1811 or WM8958. If absent the register | ||
| 87 | defaults will be used. | ||
| 88 | |||
| 89 | wlf,ldo1ena-gpios: | ||
| 90 | maxItems: 1 | ||
| 91 | description: | ||
| 92 | Control of LDO1ENA input to device. | ||
| 93 | |||
| 94 | wlf,ldo2ena-gpios: | ||
| 95 | maxItems: 1 | ||
| 96 | description: | ||
| 97 | Control of LDO2ENA input to device. | ||
| 98 | |||
| 99 | wlf,lineout1-se: | ||
| 100 | type: boolean | ||
| 101 | description: | ||
| 102 | LINEOUT1 is in single ended mode. | ||
| 103 | |||
| 104 | wlf,lineout2-se: | ||
| 105 | type: boolean | ||
| 106 | description: | ||
| 107 | INEOUT2 is in single ended mode. | ||
| 108 | |||
| 109 | wlf,lineout1-feedback: | ||
| 110 | type: boolean | ||
| 111 | description: | ||
| 112 | LINEOUT1 has common mode feedback connected. | ||
| 113 | |||
| 114 | wlf,lineout2-feedback: | ||
| 115 | type: boolean | ||
| 116 | description: | ||
| 117 | LINEOUT2 has common mode feedback connected. | ||
| 118 | |||
| 119 | wlf,ldoena-always-driven: | ||
| 120 | type: boolean | ||
| 121 | description: | ||
| 122 | LDOENA is always driven. | ||
| 123 | |||
| 124 | wlf,spkmode-pu: | ||
| 125 | type: boolean | ||
| 126 | description: | ||
| 127 | Enable the internal pull-up resistor on the SPKMODE pin. | ||
| 128 | |||
| 129 | wlf,csnaddr-pd: | ||
| 130 | type: boolean | ||
| 131 | description: | ||
| 132 | Enable the internal pull-down resistor on the CS/ADDR pin. | ||
| 133 | |||
| 134 | required: | ||
| 135 | - compatible | ||
| 136 | - reg | ||
| 137 | - AVDD2-supply | ||
| 138 | - CPVDD-supply | ||
| 139 | - SPKVDD1-supply | ||
| 140 | - SPKVDD2-supply | ||
| 141 | |||
| 142 | allOf: | ||
| 143 | - $ref: dai-common.yaml# | ||
| 144 | - if: | ||
| 145 | properties: | ||
| 146 | compatible: | ||
| 147 | enum: | ||
| 148 | - wlf,wm1811 | ||
| 149 | - wlf,wm8958 | ||
| 150 | then: | ||
| 151 | properties: | ||
| 152 | DBVDD-supply: false | ||
| 153 | LDO2VDD-supply: false | ||
| 154 | required: | ||
| 155 | - DBVDD1-supply | ||
| 156 | - DBVDD2-supply | ||
| 157 | - DBVDD3-supply | ||
| 158 | else: | ||
| 159 | properties: | ||
| 160 | DBVDD1-supply: false | ||
| 161 | DBVDD2-supply: false | ||
| 162 | DBVDD3-supply: false | ||
| 163 | required: | ||
| 164 | - DBVDD-supply | ||
| 165 | |||
| 166 | unevaluatedProperties: false | ||
| 167 | |||
| 168 | examples: | ||
| 169 | - | | ||
| 170 | #include <dt-bindings/gpio/gpio.h> | ||
| 171 | |||
| 172 | i2c { | ||
| 173 | #address-cells = <1>; | ||
| 174 | #size-cells = <0>; | ||
| 175 | |||
| 176 | audio-codec@1a { | ||
| 177 | compatible = "wlf,wm1811"; | ||
| 178 | reg = <0x1a>; | ||
| 179 | clocks = <&i2s0 0>; | ||
| 180 | clock-names = "MCLK1"; | ||
| 181 | |||
| 182 | AVDD2-supply = <&main_dc_reg>; | ||
| 183 | CPVDD-supply = <&main_dc_reg>; | ||
| 184 | DBVDD1-supply = <&main_dc_reg>; | ||
| 185 | DBVDD2-supply = <&main_dc_reg>; | ||
| 186 | DBVDD3-supply = <&main_dc_reg>; | ||
| 187 | LDO1VDD-supply = <&main_dc_reg>; | ||
| 188 | SPKVDD1-supply = <&main_dc_reg>; | ||
| 189 | SPKVDD2-supply = <&main_dc_reg>; | ||
| 190 | |||
| 191 | wlf,ldo1ena-gpios = <&gpb0 0 GPIO_ACTIVE_HIGH>; | ||
| 192 | wlf,ldo2ena-gpios = <&gpb0 1 GPIO_ACTIVE_HIGH>; | ||
| 193 | }; | ||
| 194 | }; | ||
| @@ -1,18 +0,0 @@ | |||
| 1 | WM8510 audio CODEC | ||
| 2 | |||
| 3 | This device supports both I2C and SPI (configured with pin strapping | ||
| 4 | on the board). | ||
| 5 | |||
| 6 | Required properties: | ||
| 7 | |||
| 8 | - compatible : "wlf,wm8510" | ||
| 9 | |||
| 10 | - reg : the I2C address of the device for I2C, the chip select | ||
| 11 | number for SPI. | ||
| 12 | |||
| 13 | Example: | ||
| 14 | |||
| 15 | wm8510: codec@1a { | ||
| 16 | compatible = "wlf,wm8510"; | ||
| 17 | reg = <0x1a>; | ||
| 18 | }; | ||
| @@ -1,16 +0,0 @@ | |||
| 1 | WM8523 audio CODEC | ||
| 2 | |||
| 3 | This device supports I2C only. | ||
| 4 | |||
| 5 | Required properties: | ||
| 6 | |||
| 7 | - compatible : "wlf,wm8523" | ||
| 8 | |||
| 9 | - reg : the I2C address of the device. | ||
| 10 | |||
| 11 | Example: | ||
| 12 | |||
| 13 | wm8523: codec@1a { | ||
| 14 | compatible = "wlf,wm8523"; | ||
| 15 | reg = <0x1a>; | ||
| 16 | }; | ||
| @@ -1,16 +0,0 @@ | |||
| 1 | WM8524 audio CODEC | ||
| 2 | |||
| 3 | This device does not use I2C or SPI but a simple Hardware Control Interface. | ||
| 4 | |||
| 5 | Required properties: | ||
| 6 | |||
| 7 | - compatible : "wlf,wm8524" | ||
| 8 | |||
| 9 | - wlf,mute-gpios: a GPIO spec for the MUTE pin. | ||
| 10 | |||
| 11 | Example: | ||
| 12 | |||
| 13 | wm8524: codec { | ||
| 14 | compatible = "wlf,wm8524"; | ||
| 15 | wlf,mute-gpios = <&gpio1 8 GPIO_ACTIVE_LOW>; | ||
| 16 | }; | ||
| @@ -1,16 +0,0 @@ | |||
| 1 | WM8580 and WM8581 audio CODEC | ||
| 2 | |||
| 3 | This device supports I2C only. | ||
| 4 | |||
| 5 | Required properties: | ||
| 6 | |||
| 7 | - compatible : "wlf,wm8580", "wlf,wm8581" | ||
| 8 | |||
| 9 | - reg : the I2C address of the device. | ||
| 10 | |||
| 11 | Example: | ||
| 12 | |||
| 13 | wm8580: codec@1a { | ||
| 14 | compatible = "wlf,wm8580"; | ||
| 15 | reg = <0x1a>; | ||
| 16 | }; | ||
| @@ -1,18 +0,0 @@ | |||
| 1 | WM8711 audio CODEC | ||
| 2 | |||
| 3 | This device supports both I2C and SPI (configured with pin strapping | ||
| 4 | on the board). | ||
| 5 | |||
| 6 | Required properties: | ||
| 7 | |||
| 8 | - compatible : "wlf,wm8711" | ||
| 9 | |||
| 10 | - reg : the I2C address of the device for I2C, the chip select | ||
| 11 | number for SPI. | ||
| 12 | |||
| 13 | Example: | ||
| 14 | |||
| 15 | wm8711: codec@1a { | ||
| 16 | compatible = "wlf,wm8711"; | ||
| 17 | reg = <0x1a>; | ||
| 18 | }; | ||
| @@ -1,18 +0,0 @@ | |||
| 1 | WM8728 audio CODEC | ||
| 2 | |||
| 3 | This device supports both I2C and SPI (configured with pin strapping | ||
| 4 | on the board). | ||
| 5 | |||
| 6 | Required properties: | ||
| 7 | |||
| 8 | - compatible : "wlf,wm8728" | ||
| 9 | |||
| 10 | - reg : the I2C address of the device for I2C, the chip select | ||
| 11 | number for SPI. | ||
| 12 | |||
| 13 | Example: | ||
| 14 | |||
| 15 | wm8728: codec@1a { | ||
| 16 | compatible = "wlf,wm8728"; | ||
| 17 | reg = <0x1a>; | ||
| 18 | }; | ||
| @@ -1,18 +0,0 @@ | |||
| 1 | WM8737 audio CODEC | ||
| 2 | |||
| 3 | This device supports both I2C and SPI (configured with pin strapping | ||
| 4 | on the board). | ||
| 5 | |||
| 6 | Required properties: | ||
| 7 | |||
| 8 | - compatible : "wlf,wm8737" | ||
| 9 | |||
| 10 | - reg : the I2C address of the device for I2C, the chip select | ||
| 11 | number for SPI. | ||
| 12 | |||
| 13 | Example: | ||
| 14 | |||
| 15 | wm8737: codec@1a { | ||
| 16 | compatible = "wlf,wm8737"; | ||
| 17 | reg = <0x1a>; | ||
| 18 | }; | ||
| @@ -1,40 +0,0 @@ | |||
| 1 | WM8753 audio CODEC | ||
| 2 | |||
| 3 | This device supports both I2C and SPI (configured with pin strapping | ||
| 4 | on the board). | ||
| 5 | |||
| 6 | Required properties: | ||
| 7 | |||
| 8 | - compatible : "wlf,wm8753" | ||
| 9 | |||
| 10 | - reg : the I2C address of the device for I2C, the chip select | ||
| 11 | number for SPI. | ||
| 12 | |||
| 13 | Pins on the device (for linking into audio routes): | ||
| 14 | |||
| 15 | * LOUT1 | ||
| 16 | * LOUT2 | ||
| 17 | * ROUT1 | ||
| 18 | * ROUT2 | ||
| 19 | * MONO1 | ||
| 20 | * MONO2 | ||
| 21 | * OUT3 | ||
| 22 | * OUT4 | ||
| 23 | * LINE1 | ||
| 24 | * LINE2 | ||
| 25 | * RXP | ||
| 26 | * RXN | ||
| 27 | * ACIN | ||
| 28 | * ACOP | ||
| 29 | * MIC1N | ||
| 30 | * MIC1 | ||
| 31 | * MIC2N | ||
| 32 | * MIC2 | ||
| 33 | * Mic Bias | ||
| 34 | |||
| 35 | Example: | ||
| 36 | |||
| 37 | wm8753: codec@1a { | ||
| 38 | compatible = "wlf,wm8753"; | ||
| 39 | reg = <0x1a>; | ||
| 40 | }; | ||
| @@ -1,42 +0,0 @@ | |||
| 1 | WM8960 audio CODEC | ||
| 2 | |||
| 3 | This device supports I2C only. | ||
| 4 | |||
| 5 | Required properties: | ||
| 6 | |||
| 7 | - compatible : "wlf,wm8960" | ||
| 8 | |||
| 9 | - reg : the I2C address of the device. | ||
| 10 | |||
| 11 | Optional properties: | ||
| 12 | - wlf,shared-lrclk: This is a boolean property. If present, the LRCM bit of | ||
| 13 | R24 (Additional control 2) gets set, indicating that ADCLRC and DACLRC pins | ||
| 14 | will be disabled only when ADC (Left and Right) and DAC (Left and Right) | ||
| 15 | are disabled. | ||
| 16 | When wm8960 works on synchronize mode and DACLRC pin is used to supply | ||
| 17 | frame clock, it will no frame clock for captrue unless enable DAC to enable | ||
| 18 | DACLRC pin. If shared-lrclk is present, no need to enable DAC for captrue. | ||
| 19 | |||
| 20 | - wlf,capless: This is a boolean property. If present, OUT3 pin will be | ||
| 21 | enabled and disabled together with HP_L and HP_R pins in response to jack | ||
| 22 | detect events. | ||
| 23 | |||
| 24 | - wlf,hp-cfg: A list of headphone jack detect configuration register values. | ||
| 25 | The list must be 3 entries long. | ||
| 26 | hp-cfg[0]: HPSEL[1:0] of R48 (Additional Control 4). | ||
| 27 | hp-cfg[1]: {HPSWEN:HPSWPOL} of R24 (Additional Control 2). | ||
| 28 | hp-cfg[2]: {TOCLKSEL:TOEN} of R23 (Additional Control 1). | ||
| 29 | |||
| 30 | - wlf,gpio-cfg: A list of GPIO configuration register values. | ||
| 31 | The list must be 2 entries long. | ||
| 32 | gpio-cfg[0]: ALRCGPIO of R9 (Audio interface) | ||
| 33 | gpio-cfg[1]: {GPIOPOL:GPIOSEL[2:0]} of R48 (Additional Control 4). | ||
| 34 | |||
| 35 | Example: | ||
| 36 | |||
| 37 | wm8960: codec@1a { | ||
| 38 | compatible = "wlf,wm8960"; | ||
| 39 | reg = <0x1a>; | ||
| 40 | |||
| 41 | wlf,shared-lrclk; | ||
| 42 | }; | ||
| @@ -1,112 +0,0 @@ | |||
| 1 | WM1811/WM8994/WM8958 audio CODEC | ||
| 2 | |||
| 3 | These devices support both I2C and SPI (configured with pin strapping | ||
| 4 | on the board). | ||
| 5 | |||
| 6 | Required properties: | ||
| 7 | |||
| 8 | - compatible : One of "wlf,wm1811", "wlf,wm8994" or "wlf,wm8958". | ||
| 9 | |||
| 10 | - reg : the I2C address of the device for I2C, the chip select | ||
| 11 | number for SPI. | ||
| 12 | |||
| 13 | - gpio-controller : Indicates this device is a GPIO controller. | ||
| 14 | - #gpio-cells : Must be 2. The first cell is the pin number and the | ||
| 15 | second cell is used to specify optional parameters (currently unused). | ||
| 16 | |||
| 17 | - power supplies for the device, as covered in | ||
| 18 | Documentation/devicetree/bindings/regulator/regulator.txt, depending | ||
| 19 | on compatible: | ||
| 20 | - for wlf,wm1811 and wlf,wm8958: | ||
| 21 | AVDD1-supply, AVDD2-supply, DBVDD1-supply, DBVDD2-supply, DBVDD3-supply, | ||
| 22 | DCVDD-supply, CPVDD-supply, SPKVDD1-supply, SPKVDD2-supply | ||
| 23 | - for wlf,wm8994: | ||
| 24 | AVDD1-supply, AVDD2-supply, DBVDD-supply, DCVDD-supply, CPVDD-supply, | ||
| 25 | SPKVDD1-supply, SPKVDD2-supply | ||
| 26 | |||
| 27 | Optional properties: | ||
| 28 | |||
| 29 | - interrupts : The interrupt line the IRQ signal for the device is | ||
| 30 | connected to. This is optional, if it is not connected then none | ||
| 31 | of the interrupt related properties should be specified. | ||
| 32 | - interrupt-controller : These devices contain interrupt controllers | ||
| 33 | and may provide interrupt services to other devices if they have an | ||
| 34 | interrupt line connected. | ||
| 35 | - #interrupt-cells: the number of cells to describe an IRQ, this should be 2. | ||
| 36 | The first cell is the IRQ number. | ||
| 37 | The second cell is the flags, encoded as the trigger masks from | ||
| 38 | Documentation/devicetree/bindings/interrupt-controller/interrupts.txt | ||
| 39 | |||
| 40 | - clocks : A list of up to two phandle and clock specifier pairs | ||
| 41 | - clock-names : A list of clock names sorted in the same order as clocks. | ||
| 42 | Valid clock names are "MCLK1" and "MCLK2". | ||
| 43 | |||
| 44 | - wlf,gpio-cfg : A list of GPIO configuration register values. If absent, | ||
| 45 | no configuration of these registers is performed. If any value is | ||
| 46 | over 0xffff then the register will be left as default. If present 11 | ||
| 47 | values must be supplied. | ||
| 48 | |||
| 49 | - wlf,micbias-cfg : Two MICBIAS register values for WM1811 or | ||
| 50 | WM8958. If absent the register defaults will be used. | ||
| 51 | |||
| 52 | - wlf,ldo1ena : GPIO specifier for control of LDO1ENA input to device. | ||
| 53 | - wlf,ldo2ena : GPIO specifier for control of LDO2ENA input to device. | ||
| 54 | |||
| 55 | - wlf,lineout1-se : If present LINEOUT1 is in single ended mode. | ||
| 56 | - wlf,lineout2-se : If present LINEOUT2 is in single ended mode. | ||
| 57 | |||
| 58 | - wlf,lineout1-feedback : If present LINEOUT1 has common mode feedback | ||
| 59 | connected. | ||
| 60 | - wlf,lineout2-feedback : If present LINEOUT2 has common mode feedback | ||
| 61 | connected. | ||
| 62 | |||
| 63 | - wlf,ldoena-always-driven : If present LDOENA is always driven. | ||
| 64 | |||
| 65 | - wlf,spkmode-pu : If present enable the internal pull-up resistor on | ||
| 66 | the SPKMODE pin. | ||
| 67 | |||
| 68 | - wlf,csnaddr-pd : If present enable the internal pull-down resistor on | ||
| 69 | the CS/ADDR pin. | ||
| 70 | |||
| 71 | Pins on the device (for linking into audio routes): | ||
| 72 | |||
| 73 | * IN1LN | ||
| 74 | * IN1LP | ||
| 75 | * IN2LN | ||
| 76 | * IN2LP:VXRN | ||
| 77 | * IN1RN | ||
| 78 | * IN1RP | ||
| 79 | * IN2RN | ||
| 80 | * IN2RP:VXRP | ||
| 81 | * SPKOUTLP | ||
| 82 | * SPKOUTLN | ||
| 83 | * SPKOUTRP | ||
| 84 | * SPKOUTRN | ||
| 85 | * HPOUT1L | ||
| 86 | * HPOUT1R | ||
| 87 | * HPOUT2P | ||
| 88 | * HPOUT2N | ||
| 89 | * LINEOUT1P | ||
| 90 | * LINEOUT1N | ||
| 91 | * LINEOUT2P | ||
| 92 | * LINEOUT2N | ||
| 93 | |||
| 94 | Example: | ||
| 95 | |||
| 96 | wm8994: codec@1a { | ||
| 97 | compatible = "wlf,wm8994"; | ||
| 98 | reg = <0x1a>; | ||
| 99 | |||
| 100 | gpio-controller; | ||
| 101 | #gpio-cells = <2>; | ||
| 102 | |||
| 103 | lineout1-se; | ||
| 104 | |||
| 105 | AVDD1-supply = <®ulator>; | ||
| 106 | AVDD2-supply = <®ulator>; | ||
| 107 | CPVDD-supply = <®ulator>; | ||
| 108 | DBVDD-supply = <®ulator>; | ||
| 109 | DCVDD-supply = <®ulator>; | ||
| 110 | SPKVDD1-supply = <®ulator>; | ||
| 111 | SPKVDD2-supply = <®ulator>; | ||
| 112 | }; | ||
| @@ -723,9 +723,10 @@ Module for EMU10K1/EMU10k2 based PCI sound cards. · 722 unmodified lines | |||
| 723 | 723 | ||
| 724 | * Sound Blaster Live! | 724 | * Sound Blaster Live! |
| 725 | * Sound Blaster PCI 512 | 725 | * Sound Blaster PCI 512 |
| 726 | * Emu APS (partially supported) | ||
| 727 | * Sound Blaster Audigy | 726 | * Sound Blaster Audigy |
| 728 | 727 | * E-MU APS (partially supported) | |
| 728 | * E-MU DAS | ||
| 729 | |||
| 729 | extin | 730 | extin |
| 730 | bitmap of available external inputs for FX8010 (see below) | 731 | bitmap of available external inputs for FX8010 (see below) |
| 731 | extout | 732 | extout |
| @@ -19,9 +19,9 @@ Digital mixer controls · 18 unmodified lines | |||
| 19 | These controls are built using the DSP instructions. They offer extended | 19 | These controls are built using the DSP instructions. They offer extended |
| 20 | functionality. Only the default built-in code in the ALSA driver is described | 20 | functionality. Only the default built-in code in the ALSA driver is described |
| 21 | here. Note that the controls work as attenuators: the maximum value is the | 21 | here. Note that the controls work as attenuators: the maximum value is the |
| 22 | neutral position leaving the signal unchanged. Note that if the same destination | 22 | neutral position leaving the signal unchanged. Note that if the same destination |
| 23 | is mentioned in multiple controls, the signal is accumulated and can be wrapped | 23 | is mentioned in multiple controls, the signal is accumulated and can be clipped |
| 24 | (set to maximal or minimal value without checking of overflow). | 24 | (set to maximal or minimal value without checking for overflow). |
| 25 | 25 | ||
| 26 | 26 | ||
| 27 | Explanation of used abbreviations: | 27 | Explanation of used abbreviations: |
| @@ -32,17 +32,17 @@ ADC · 4 unmodified lines | |||
| 32 | analog to digital converter | 32 | analog to digital converter |
| 33 | I2S | 33 | I2S |
| 34 | one-way three wire serial bus for digital sound by Philips Semiconductors | 34 | one-way three wire serial bus for digital sound by Philips Semiconductors |
| 35 | (this standard is used for connecting standalone DAC and ADC converters) | 35 | (this standard is used for connecting standalone D/A and A/D converters) |
| 36 | LFE | 36 | LFE |
| 37 | low frequency effects (subwoofer signal) | 37 | low frequency effects (used as subwoofer signal) |
| 38 | AC97 | 38 | AC97 |
| 39 | a chip containing an analog mixer, DAC and ADC converters | 39 | a chip containing an analog mixer, D/A and A/D converters |
| 40 | IEC958 | 40 | IEC958 |
| 41 | S/PDIF | 41 | S/PDIF |
| 42 | FX-bus | 42 | FX-bus |
| 43 | the EMU10K2 chip has an effect bus containing 64 accumulators. | 43 | the EMU10K2 chip has an effect bus containing 64 accumulators. |
| 44 | Each of the synthesizer voices can feed its output to these accumulators | 44 | Each of the synthesizer voices can feed its output to these accumulators |
| 45 | and the DSP microcontroller can operate with the resulting sum. | 45 | and the DSP microcontroller can operate with the resulting sum. |
| 46 | 46 | ||
| 47 | name='PCM Front Playback Volume',index=0 | 47 | name='PCM Front Playback Volume',index=0 |
| 48 | ---------------------------------------- | 48 | ---------------------------------------- |
| @@ -218,8 +218,8 @@ LFE outputs. · 169 unmodified lines | |||
| 218 | name='IEC958 Optical Raw Playback Switch',index=0 | 218 | name='IEC958 Optical Raw Playback Switch',index=0 |
| 219 | ------------------------------------------------- | 219 | ------------------------------------------------- |
| 220 | If this switch is on, then the samples for the IEC958 (S/PDIF) digital | 220 | If this switch is on, then the samples for the IEC958 (S/PDIF) digital |
| 221 | output are taken only from the raw FX8010 PCM, otherwise standard front | 221 | output are taken only from the raw iec958 ALSA PCM device (which uses |
| 222 | PCM samples are taken. | 222 | accumulators 20 and 21 for left and right PCM by default). |
| 223 | 223 | ||
| 224 | 224 | ||
| 225 | PCM stream related controls | 225 | PCM stream related controls |
| @@ -237,8 +237,8 @@ as follows: · 11 unmodified lines | |||
| 237 | 237 | ||
| 238 | name='EMU10K1 PCM Send Routing',index 0-31 | 238 | name='EMU10K1 PCM Send Routing',index 0-31 |
| 239 | ------------------------------------------ | 239 | ------------------------------------------ |
| 240 | This control specifies the destination - FX-bus accumulators. There 24 | 240 | This control specifies the destination - FX-bus accumulators. There are 24 |
| 241 | values with this mapping: | 241 | values in this mapping: |
| 242 | 242 | ||
| 243 | * 0 - mono, A destination (FX-bus 0-63), default 0 | 243 | * 0 - mono, A destination (FX-bus 0-63), default 0 |
| 244 | * 1 - mono, B destination (FX-bus 0-63), default 1 | 244 | * 1 - mono, B destination (FX-bus 0-63), default 1 |
| @@ -306,6 +306,9 @@ MANUALS/PATENTS · 61 unmodified lines | |||
| 306 | ftp://opensource.creative.com/pub/doc | 306 | ftp://opensource.creative.com/pub/doc |
| 307 | ------------------------------------- | 307 | ------------------------------------- |
| 308 | 308 | ||
| 309 | Note that the site is defunct, but the documents are available | ||
| 310 | from various other locations. | ||
| 311 | |||
| 309 | LM4545.pdf | 312 | LM4545.pdf |
| 310 | AC97 Codec | 313 | AC97 Codec |
| 311 | 314 | ||
| @@ -15,7 +15,7 @@ The ALSA driver programs this portion of chip by default code · 14 unmodified lines | |||
| 15 | IEC958 (S/PDIF) raw PCM | 15 | IEC958 (S/PDIF) raw PCM |
| 16 | ======================= | 16 | ======================= |
| 17 | 17 | ||
| 18 | This PCM device (it's the 4th PCM device (index 3!) and first subdevice | 18 | This PCM device (it's the 3rd PCM device (index 2!) and first subdevice |
| 19 | (index 0) for a given card) allows to forward 48kHz, stereo, 16-bit | 19 | (index 0) for a given card) allows to forward 48kHz, stereo, 16-bit |
| 20 | little endian streams without any modifications to the digital output | 20 | little endian streams without any modifications to the digital output |
| 21 | (coaxial or optical). The universal interface allows the creation of up | 21 | (coaxial or optical). The universal interface allows the creation of up |
| @@ -33,9 +33,9 @@ Digital mixer controls · 11 unmodified lines | |||
| 33 | These controls are built using the DSP instructions. They offer extended | 33 | These controls are built using the DSP instructions. They offer extended |
| 34 | functionality. Only the default built-in code in the ALSA driver is described | 34 | functionality. Only the default built-in code in the ALSA driver is described |
| 35 | here. Note that the controls work as attenuators: the maximum value is the | 35 | here. Note that the controls work as attenuators: the maximum value is the |
| 36 | neutral position leaving the signal unchanged. Note that if the same destination | 36 | neutral position leaving the signal unchanged. Note that if the same destination |
| 37 | is mentioned in multiple controls, the signal is accumulated and can be wrapped | 37 | is mentioned in multiple controls, the signal is accumulated and can be clipped |
| 38 | (set to maximal or minimal value without checking of overflow). | 38 | (set to maximal or minimal value without checking for overflow). |
| 39 | 39 | ||
| 40 | 40 | ||
| 41 | Explanation of used abbreviations: | 41 | Explanation of used abbreviations: |
| @@ -46,11 +46,11 @@ ADC · 4 unmodified lines | |||
| 46 | analog to digital converter | 46 | analog to digital converter |
| 47 | I2S | 47 | I2S |
| 48 | one-way three wire serial bus for digital sound by Philips Semiconductors | 48 | one-way three wire serial bus for digital sound by Philips Semiconductors |
| 49 | (this standard is used for connecting standalone DAC and ADC converters) | 49 | (this standard is used for connecting standalone D/A and A/D converters) |
| 50 | LFE | 50 | LFE |
| 51 | low frequency effects (subwoofer signal) | 51 | low frequency effects (used as subwoofer signal) |
| 52 | AC97 | 52 | AC97 |
| 53 | a chip containing an analog mixer, DAC and ADC converters | 53 | a chip containing an analog mixer, D/A and A/D converters |
| 54 | IEC958 | 54 | IEC958 |
| 55 | S/PDIF | 55 | S/PDIF |
| 56 | FX-bus | 56 | FX-bus |
| @@ -313,6 +313,9 @@ MANUALS/PATENTS · 256 unmodified lines | |||
| 313 | ftp://opensource.creative.com/pub/doc | 313 | ftp://opensource.creative.com/pub/doc |
| 314 | ------------------------------------- | 314 | ------------------------------------- |
| 315 | 315 | ||
| 316 | Note that the site is defunct, but the documents are available | ||
| 317 | from various other locations. | ||
| 318 | |||
| 316 | LM4545.pdf | 319 | LM4545.pdf |
| 317 | AC97 Codec | 320 | AC97 Codec |
| 318 | m2049.pdf | 321 | m2049.pdf |
| @@ -9,3 +9,4 @@ HD-Audio · 8 unmodified lines | |||
| 9 | controls | 9 | controls |
| 10 | dp-mst | 10 | dp-mst |
| 11 | realtek-pc-beep | 11 | realtek-pc-beep |
| 12 | intel-multi-link | ||
| @@ -0,0 +1,312 @@ | |||
| 1 | .. SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause) | ||
| 2 | .. include:: <isonum.txt> | ||
| 3 | |||
| 4 | ================================================ | ||
| 5 | HDAudio multi-link extensions on Intel platforms | ||
| 6 | ================================================ | ||
| 7 | |||
| 8 | :Copyright: |copy| 2023 Intel Corporation | ||
| 9 | |||
| 10 | This file documents the 'multi-link structure' introduced in 2015 with | ||
| 11 | the Skylake processor and recently extended in newer Intel platforms | ||
| 12 | |||
| 13 | HDaudio existing link mapping (2015 addition in SkyLake) | ||
| 14 | ======================================================== | ||
| 15 | |||
| 16 | External HDAudio codecs are handled with link #0, while iDISP codec | ||
| 17 | for HDMI/DisplayPort is handled with link #1. | ||
| 18 | |||
| 19 | The only change to the 2015 definitions is the declaration of the | ||
| 20 | LCAP.ALT=0x0 - since the ALT bit was previously reserved, this is a | ||
| 21 | backwards-compatible change. | ||
| 22 | |||
| 23 | LCTL.SPA and LCTL.CPA are automatically set when exiting reset. They | ||
| 24 | are only used in existing drivers when the SCF value needs to be | ||
| 25 | corrected. | ||
| 26 | |||
| 27 | Basic structure for HDaudio codecs | ||
| 28 | ---------------------------------- | ||
| 29 | |||
| 30 | :: | ||
| 31 | |||
| 32 | +-----------+ | ||
| 33 | | ML cap #0 | | ||
| 34 | +-----------+ | ||
| 35 | | ML cap #1 |---+ | ||
| 36 | +-----------+ | | ||
| 37 | | | ||
| 38 | +--> 0x0 +---------------+ LCAP | ||
| 39 | | ALT=0 | | ||
| 40 | +---------------+ | ||
| 41 | | S192 | | ||
| 42 | +---------------+ | ||
| 43 | | S96 | | ||
| 44 | +---------------+ | ||
| 45 | | S48 | | ||
| 46 | +---------------+ | ||
| 47 | | S24 | | ||
| 48 | +---------------+ | ||
| 49 | | S12 | | ||
| 50 | +---------------+ | ||
| 51 | | S6 | | ||
| 52 | +---------------+ | ||
| 53 | |||
| 54 | 0x4 +---------------+ LCTL | ||
| 55 | | INTSTS | | ||
| 56 | +---------------+ | ||
| 57 | | CPA | | ||
| 58 | +---------------+ | ||
| 59 | | SPA | | ||
| 60 | +---------------+ | ||
| 61 | | SCF | | ||
| 62 | +---------------+ | ||
| 63 | |||
| 64 | 0x8 +---------------+ LOSIDV | ||
| 65 | | L1OSIVD15 | | ||
| 66 | +---------------+ | ||
| 67 | | L1OSIDV.. | | ||
| 68 | +---------------+ | ||
| 69 | | L1OSIDV1 | | ||
| 70 | +---------------+ | ||
| 71 | |||
| 72 | 0xC +---------------+ LSDIID | ||
| 73 | | SDIID14 | | ||
| 74 | +---------------+ | ||
| 75 | | SDIID... | | ||
| 76 | +---------------+ | ||
| 77 | | SDIID0 | | ||
| 78 | +---------------+ | ||
| 79 | |||
| 80 | SoundWire HDaudio extended link mapping | ||
| 81 | ======================================= | ||
| 82 | |||
| 83 | A SoundWire extended link is identified when LCAP.ALT=1 and | ||
| 84 | LEPTR.ID=0. | ||
| 85 | |||
| 86 | DMA control uses the existing LOSIDV register. | ||
| 87 | |||
| 88 | Changes include additional descriptions for enumeration that were not | ||
| 89 | present in earlier generations. | ||
| 90 | |||
| 91 | - multi-link synchronization: capabilities in LCAP.LSS and control in LSYNC | ||
| 92 | - number of sublinks (manager IP) in LCAP.LSCOUNT | ||
| 93 | - power management moved from SHIM to LCTL.SPA bits | ||
| 94 | - hand-over to the DSP for access to multi-link registers, SHIM/IP with LCTL.OFLEN | ||
| 95 | - mapping of SoundWire codecs to SDI ID bits | ||
| 96 | - move of SHIM and Cadence registers to different offsets, with no | ||
| 97 | change in functionality. The LEPTR.PTR value is an offset from the | ||
| 98 | ML address, with a default value of 0x30000. | ||
| 99 | |||
| 100 | Extended structure for SoundWire (assuming 4 Manager IP) | ||
| 101 | -------------------------------------------------------- | ||
| 102 | |||
| 103 | :: | ||
| 104 | |||
| 105 | +-----------+ | ||
| 106 | | ML cap #0 | | ||
| 107 | +-----------+ | ||
| 108 | | ML cap #1 | | ||
| 109 | +-----------+ | ||
| 110 | | ML cap #2 |---+ | ||
| 111 | +-----------+ | | ||
| 112 | | | ||
| 113 | +--> 0x0 +---------------+ LCAP | ||
| 114 | | ALT=1 | | ||
| 115 | +---------------+ | ||
| 116 | | INTC | | ||
| 117 | +---------------+ | ||
| 118 | | OFLS | | ||
| 119 | +---------------+ | ||
| 120 | | LSS | | ||
| 121 | +---------------+ | ||
| 122 | | SLCOUNT=4 |-----------+ | ||
| 123 | +---------------+ | | ||
| 124 | | | ||
| 125 | 0x4 +---------------+ LCTL | | ||
| 126 | | INTSTS | | | ||
| 127 | +---------------+ | | ||
| 128 | | CPA (x bits) | | | ||
| 129 | +---------------+ | | ||
| 130 | | SPA (x bits) | | | ||
| 131 | +---------------+ for each sublink x | ||
| 132 | | INTEN | | | ||
| 133 | +---------------+ | | ||
| 134 | | OFLEN | | | ||
| 135 | +---------------+ | | ||
| 136 | | | ||
| 137 | 0x8 +---------------+ LOSIDV | | ||
| 138 | | L1OSIVD15 | | | ||
| 139 | +---------------+ | | ||
| 140 | | L1OSIDV.. | | | ||
| 141 | +---------------+ | | ||
| 142 | | L1OSIDV1 | +---+----------------------------------------------------------+ | ||
| 143 | +---------------+ | | | ||
| 144 | v | | ||
| 145 | 0xC + 0x2 * x +---------------+ LSDIIDx +---> 0x30000 +-----------------+ 0x00030000 | | ||
| 146 | | SDIID14 | | | SoundWire SHIM | | | ||
| 147 | +---------------+ | | generic | | | ||
| 148 | | SDIID... | | +-----------------+ 0x00030100 | | ||
| 149 | +---------------+ | | SoundWire IP | | | ||
| 150 | | SDIID0 | | +-----------------+ 0x00036000 | | ||
| 151 | +---------------+ | | SoundWire SHIM | | | ||
| 152 | | | vendor-specific | | | ||
| 153 | 0x1C +---------------+ LSYNC | +-----------------+ | | ||
| 154 | | CMDSYNC | | v | ||
| 155 | +---------------+ | +-----------------+ 0x00030000 + 0x8000 * x | ||
| 156 | | SYNCGO | | | SoundWire SHIM | | ||
| 157 | +---------------+ | | generic | | ||
| 158 | | SYNCPU | | +-----------------+ 0x00030100 + 0x8000 * x | ||
| 159 | +---------------+ | | SoundWire IP | | ||
| 160 | | SYNPRD | | +-----------------+ 0x00036000 + 0x8000 * x | ||
| 161 | +---------------+ | | SoundWire SHIM | | ||
| 162 | | | vendor-specific | | ||
| 163 | 0x20 +---------------+ LEPTR | +-----------------+ | ||
| 164 | | ID = 0 | | | ||
| 165 | +---------------+ | | ||
| 166 | | VER | | | ||
| 167 | +---------------+ | | ||
| 168 | | PTR |------------+ | ||
| 169 | +---------------+ | ||
| 170 | |||
| 171 | |||
| 172 | DMIC HDaudio extended link mapping | ||
| 173 | ================================== | ||
| 174 | |||
| 175 | A DMIC extended link is identified when LCAP.ALT=1 and | ||
| 176 | LEPTR.ID=0xC1 are set. | ||
| 177 | |||
| 178 | DMA control uses the existing LOSIDV register | ||
| 179 | |||
| 180 | Changes include additional descriptions for enumeration that were not | ||
| 181 | present in earlier generations. | ||
| 182 | |||
| 183 | - multi-link synchronization: capabilities in LCAP.LSS and control in LSYNC | ||
| 184 | - power management with LCTL.SPA bits | ||
| 185 | - hand-over to the DSP for access to multi-link registers, SHIM/IP with LCTL.OFLEN | ||
| 186 | |||
| 187 | - move of DMIC registers to different offsets, with no change in | ||
| 188 | functionality. The LEPTR.PTR value is an offset from the ML | ||
| 189 | address, with a default value of 0x10000. | ||
| 190 | |||
| 191 | Extended structure for DMIC | ||
| 192 | --------------------------- | ||
| 193 | |||
| 194 | :: | ||
| 195 | |||
| 196 | +-----------+ | ||
| 197 | | ML cap #0 | | ||
| 198 | +-----------+ | ||
| 199 | | ML cap #1 | | ||
| 200 | +-----------+ | ||
| 201 | | ML cap #2 |---+ | ||
| 202 | +-----------+ | | ||
| 203 | | | ||
| 204 | +--> 0x0 +---------------+ LCAP | ||
| 205 | | ALT=1 | | ||
| 206 | +---------------+ | ||
| 207 | | INTC | | ||
| 208 | +---------------+ | ||
| 209 | | OFLS | | ||
| 210 | +---------------+ | ||
| 211 | | SLCOUNT=1 | | ||
| 212 | +---------------+ | ||
| 213 | |||
| 214 | 0x4 +---------------+ LCTL | ||
| 215 | | INTSTS | | ||
| 216 | +---------------+ | ||
| 217 | | CPA | | ||
| 218 | +---------------+ | ||
| 219 | | SPA | | ||
| 220 | +---------------+ | ||
| 221 | | INTEN | | ||
| 222 | +---------------+ | ||
| 223 | | OFLEN | | ||
| 224 | +---------------+ +---> 0x10000 +-----------------+ 0x00010000 | ||
| 225 | | | DMIC SHIM | | ||
| 226 | 0x8 +---------------+ LOSIDV | | generic | | ||
| 227 | | L1OSIVD15 | | +-----------------+ 0x00010100 | ||
| 228 | +---------------+ | | DMIC IP | | ||
| 229 | | L1OSIDV.. | | +-----------------+ 0x00016000 | ||
| 230 | +---------------+ | | DMIC SHIM | | ||
| 231 | | L1OSIDV1 | | | vendor-specific | | ||
| 232 | +---------------+ | +-----------------+ | ||
| 233 | | | ||
| 234 | 0x20 +---------------+ LEPTR | | ||
| 235 | | ID = 0xC1 | | | ||
| 236 | +---------------+ | | ||
| 237 | | VER | | | ||
| 238 | +---------------+ | | ||
| 239 | | PTR |-----------+ | ||
| 240 | +---------------+ | ||
| 241 | |||
| 242 | |||
| 243 | SSP HDaudio extended link mapping | ||
| 244 | ================================= | ||
| 245 | |||
| 246 | A DMIC extended link is identified when LCAP.ALT=1 and | ||
| 247 | LEPTR.ID=0xC0 are set. | ||
| 248 | |||
| 249 | DMA control uses the existing LOSIDV register | ||
| 250 | |||
| 251 | Changes include additional descriptions for enumeration and control that were not | ||
| 252 | present in earlier generations: | ||
| 253 | - number of sublinks (SSP IP instances) in LCAP.LSCOUNT | ||
| 254 | - power management moved from SHIM to LCTL.SPA bits | ||
| 255 | - hand-over to the DSP for access to multi-link registers, SHIM/IP | ||
| 256 | with LCTL.OFLEN | ||
| 257 | - move of SHIM and SSP IP registers to different offsets, with no | ||
| 258 | change in functionality. The LEPTR.PTR value is an offset from the ML | ||
| 259 | address, with a default value of 0x28000. | ||
| 260 | |||
| 261 | Extended structure for SSP (assuming 3 instances of the IP) | ||
| 262 | ----------------------------------------------------------- | ||
| 263 | |||
| 264 | :: | ||
| 265 | |||
| 266 | +-----------+ | ||
| 267 | | ML cap #0 | | ||
| 268 | +-----------+ | ||
| 269 | | ML cap #1 | | ||
| 270 | +-----------+ | ||
| 271 | | ML cap #2 |---+ | ||
| 272 | +-----------+ | | ||
| 273 | | | ||
| 274 | +--> 0x0 +---------------+ LCAP | ||
| 275 | | ALT=1 | | ||
| 276 | +---------------+ | ||
| 277 | | INTC | | ||
| 278 | +---------------+ | ||
| 279 | | OFLS | | ||
| 280 | +---------------+ | ||
| 281 | | SLCOUNT=3 |-------------------------for each sublink x -------------------------+ | ||
| 282 | +---------------+ | | ||
| 283 | | | ||
| 284 | 0x4 +---------------+ LCTL | | ||
| 285 | | INTSTS | | | ||
| 286 | +---------------+ | | ||
| 287 | | CPA (x bits) | | | ||
| 288 | +---------------+ | | ||
| 289 | | SPA (x bits) | | | ||
| 290 | +---------------+ | | ||
| 291 | | INTEN | | | ||
| 292 | +---------------+ | | ||
| 293 | | OFLEN | | | ||
| 294 | +---------------+ +---> 0x28000 +-----------------+ 0x00028000 | | ||
| 295 | | | SSP SHIM | | | ||
| 296 | 0x8 +---------------+ LOSIDV | | generic | | | ||
| 297 | | L1OSIVD15 | | +-----------------+ 0x00028100 | | ||
| 298 | +---------------+ | | SSP IP | | | ||
| 299 | | L1OSIDV.. | | +-----------------+ 0x00028C00 | | ||
| 300 | +---------------+ | | SSP SHIM | | | ||
| 301 | | L1OSIDV1 | | | vendor-specific | | | ||
| 302 | +---------------+ | +-----------------+ | | ||
| 303 | | v | ||
| 304 | 0x20 +---------------+ LEPTR | +-----------------+ 0x00028000 + 0x1000 * x | ||
| 305 | | ID = 0xC0 | | | SSP SHIM | | ||
| 306 | +---------------+ | | generic | | ||
| 307 | | VER | | +-----------------+ 0x00028100 + 0x1000 * x | ||
| 308 | +---------------+ | | SSP IP | | ||
| 309 | | PTR |-----------+ +-----------------+ 0x00028C00 + 0x1000 * x | ||
| 310 | +---------------+ | SSP SHIM | | ||
| 311 | | vendor-specific | | ||
| 312 | +-----------------+ | ||
| @@ -19,18 +19,13 @@ explain the general topic of linux kernel coding and doesn't cover · 18 unmodified lines | |||
| 19 | low-level driver implementation details. It only describes the standard | 19 | low-level driver implementation details. It only describes the standard |
| 20 | way to write a PCI sound driver on ALSA. | 20 | way to write a PCI sound driver on ALSA. |
| 21 | 21 | ||
| 22 | This document is still a draft version. Any feedback and corrections, | ||
| 23 | please!! | ||
| 24 | |||
| 25 | File Tree Structure | 22 | File Tree Structure |
| 26 | =================== | 23 | =================== |
| 27 | 24 | ||
| 28 | General | 25 | General |
| 29 | ------- | 26 | ------- |
| 30 | 27 | ||
| 31 | The file tree structure of ALSA driver is depicted below. | 28 | The file tree structure of ALSA driver is depicted below:: |
| 32 | |||
| 33 | :: | ||
| 34 | 29 | ||
| 35 | sound | 30 | sound |
| 36 | /core | 31 | /core |
| @@ -68,8 +63,8 @@ kernel config. · 31 unmodified lines | |||
| 68 | core/oss | 63 | core/oss |
| 69 | ~~~~~~~~ | 64 | ~~~~~~~~ |
| 70 | 65 | ||
| 71 | The codes for PCM and mixer OSS emulation modules are stored in this | 66 | The code for OSS PCM and mixer emulation modules is stored in this |
| 72 | directory. The rawmidi OSS emulation is included in the ALSA rawmidi | 67 | directory. The OSS rawmidi emulation is included in the ALSA rawmidi |
| 73 | code since it's quite small. The sequencer code is stored in | 68 | code since it's quite small. The sequencer code is stored in |
| 74 | ``core/seq/oss`` directory (see `below <core/seq/oss_>`__). | 69 | ``core/seq/oss`` directory (see `below <core/seq/oss_>`__). |
| 75 | 70 | ||
| @@ -78,19 +73,19 @@ core/seq · 2 unmodified lines | |||
| 78 | 73 | ||
| 79 | This directory and its sub-directories are for the ALSA sequencer. This | 74 | This directory and its sub-directories are for the ALSA sequencer. This |
| 80 | directory contains the sequencer core and primary sequencer modules such | 75 | directory contains the sequencer core and primary sequencer modules such |
| 81 | like snd-seq-midi, snd-seq-virmidi, etc. They are compiled only when | 76 | as snd-seq-midi, snd-seq-virmidi, etc. They are compiled only when |
| 82 | ``CONFIG_SND_SEQUENCER`` is set in the kernel config. | 77 | ``CONFIG_SND_SEQUENCER`` is set in the kernel config. |
| 83 | 78 | ||
| 84 | core/seq/oss | 79 | core/seq/oss |
| 85 | ~~~~~~~~~~~~ | 80 | ~~~~~~~~~~~~ |
| 86 | 81 | ||
| 87 | This contains the OSS sequencer emulation codes. | 82 | This contains the OSS sequencer emulation code. |
| 88 | 83 | ||
| 89 | include directory | 84 | include directory |
| 90 | ----------------- | 85 | ----------------- |
| 91 | 86 | ||
| 92 | This is the place for the public header files of ALSA drivers, which are | 87 | This is the place for the public header files of ALSA drivers, which are |
| 93 | to be exported to user-space, or included by several files at different | 88 | to be exported to user-space, or included by several files in different |
| 94 | directories. Basically, the private header files should not be placed in | 89 | directories. Basically, the private header files should not be placed in |
| 95 | this directory, but you may still find files there, due to historical | 90 | this directory, but you may still find files there, due to historical |
| 96 | reasons :) | 91 | reasons :) |
| @@ -100,7 +95,7 @@ drivers directory · 3 unmodified lines | |||
| 100 | 95 | ||
| 101 | This directory contains code shared among different drivers on different | 96 | This directory contains code shared among different drivers on different |
| 102 | architectures. They are hence supposed not to be architecture-specific. | 97 | architectures. They are hence supposed not to be architecture-specific. |
| 103 | For example, the dummy pcm driver and the serial MIDI driver are found | 98 | For example, the dummy PCM driver and the serial MIDI driver are found |
| 104 | in this directory. In the sub-directories, there is code for components | 99 | in this directory. In the sub-directories, there is code for components |
| 105 | which are independent from bus and cpu architectures. | 100 | which are independent from bus and cpu architectures. |
| 106 | 101 | ||
| @@ -156,8 +151,8 @@ these architectures. · 49 unmodified lines | |||
| 156 | usb directory | 151 | usb directory |
| 157 | ------------- | 152 | ------------- |
| 158 | 153 | ||
| 159 | This directory contains the USB-audio driver. In the latest version, the | 154 | This directory contains the USB-audio driver. |
| 160 | USB MIDI driver is integrated in the usb-audio driver. | 155 | The USB MIDI driver is integrated in the usb-audio driver. |
| 161 | 156 | ||
| 162 | pcmcia directory | 157 | pcmcia directory |
| 163 | ---------------- | 158 | ---------------- |
| @@ -175,9 +170,9 @@ layer including ASoC core, codec and machine drivers. · 11 unmodified lines | |||
| 175 | oss directory | 170 | oss directory |
| 176 | ------------- | 171 | ------------- |
| 177 | 172 | ||
| 178 | Here contains OSS/Lite codes. | 173 | This contains OSS/Lite code. |
| 179 | All codes have been deprecated except for dmasound on m68k as of | 174 | At the time of writing, all code has been removed except for dmasound |
| 180 | writing this. | 175 | on m68k. |
| 181 | 176 | ||
| 182 | 177 | ||
| 183 | Basic Flow for PCI Drivers | 178 | Basic Flow for PCI Drivers |
| @@ -341,7 +336,7 @@ to details explained in the following section. · 157 unmodified lines | |||
| 341 | 336 | ||
| 342 | error: | 337 | error: |
| 343 | snd_card_free(card); | 338 | snd_card_free(card); |
| 344 | return err; | 339 | return err; |
| 345 | } | 340 | } |
| 346 | 341 | ||
| 347 | /* destructor -- see the "Destructor" sub-section */ | 342 | /* destructor -- see the "Destructor" sub-section */ |
| @@ -381,7 +376,7 @@ where ``enable[dev]`` is the module option. · 33 unmodified lines | |||
| 381 | 376 | ||
| 382 | Each time the ``probe`` callback is called, check the availability of | 377 | Each time the ``probe`` callback is called, check the availability of |
| 383 | the device. If not available, simply increment the device index and | 378 | the device. If not available, simply increment the device index and |
| 384 | returns. dev will be incremented also later (`step 7 | 379 | return. dev will be incremented also later (`step 7 |
| 385 | <7) Set the PCI driver data and return zero._>`__). | 380 | <7) Set the PCI driver data and return zero._>`__). |
| 386 | 381 | ||
| 387 | 2) Create a card instance | 382 | 2) Create a card instance |
| @@ -402,9 +397,7 @@ Components`_. · 14 unmodified lines | |||
| 402 | 3) Create a main component | 397 | 3) Create a main component |
| 403 | ~~~~~~~~~~~~~~~~~~~~~~~~~~ | 398 | ~~~~~~~~~~~~~~~~~~~~~~~~~~ |
| 404 | 399 | ||
| 405 | In this part, the PCI resources are allocated. | 400 | In this part, the PCI resources are allocated:: |
| 406 | |||
| 407 | :: | ||
| 408 | 401 | ||
| 409 | struct mychip *chip; | 402 | struct mychip *chip; |
| 410 | .... | 403 | .... |
| @@ -417,13 +410,11 @@ Management`_. · 6 unmodified lines | |||
| 417 | 410 | ||
| 418 | When something goes wrong, the probe function needs to deal with the | 411 | When something goes wrong, the probe function needs to deal with the |
| 419 | error. In this example, we have a single error handling path placed | 412 | error. In this example, we have a single error handling path placed |
| 420 | at the end of the function. | 413 | at the end of the function:: |
| 421 | |||
| 422 | :: | ||
| 423 | 414 | ||
| 424 | error: | 415 | error: |
| 425 | snd_card_free(card); | 416 | snd_card_free(card); |
| 426 | return err; | 417 | return err; |
| 427 | 418 | ||
| 428 | Since each component can be properly freed, the single | 419 | Since each component can be properly freed, the single |
| 429 | :c:func:`snd_card_free()` call should suffice in most cases. | 420 | :c:func:`snd_card_free()` call should suffice in most cases. |
| @@ -483,13 +474,11 @@ remove callback and power-management callbacks, too. · 53 unmodified lines | |||
| 483 | Destructor | 474 | Destructor |
| 484 | ---------- | 475 | ---------- |
| 485 | 476 | ||
| 486 | The destructor, remove callback, simply releases the card instance. Then | 477 | The destructor, the remove callback, simply releases the card instance. |
| 487 | the ALSA middle layer will release all the attached components | 478 | Then the ALSA middle layer will release all the attached components |
| 488 | automatically. | 479 | automatically. |
| 489 | 480 | ||
| 490 | It would be typically just calling :c:func:`snd_card_free()`: | 481 | It would be typically just calling :c:func:`snd_card_free()`:: |
| 491 | |||
| 492 | :: | ||
| 493 | 482 | ||
| 494 | static void snd_mychip_remove(struct pci_dev *pci) | 483 | static void snd_mychip_remove(struct pci_dev *pci) |
| 495 | { | 484 | { |
| @@ -504,9 +493,7 @@ Header Files · 8 unmodified lines | |||
| 504 | ------------ | 493 | ------------ |
| 505 | 494 | ||
| 506 | For the above example, at least the following include files are | 495 | For the above example, at least the following include files are |
| 507 | necessary. | 496 | necessary:: |
| 508 | |||
| 509 | :: | ||
| 510 | 497 | ||
| 511 | #include <linux/init.h> | 498 | #include <linux/init.h> |
| 512 | #include <linux/pci.h> | 499 | #include <linux/pci.h> |
| @@ -544,9 +531,7 @@ list on the card record is used to manage the correct release of · 31 unmodified lines | |||
| 544 | resources at destruction. | 531 | resources at destruction. |
| 545 | 532 | ||
| 546 | As mentioned above, to create a card instance, call | 533 | As mentioned above, to create a card instance, call |
| 547 | :c:func:`snd_card_new()`. | 534 | :c:func:`snd_card_new()`:: |
| 548 | |||
| 549 | :: | ||
| 550 | 535 | ||
| 551 | struct snd_card *card; | 536 | struct snd_card *card; |
| 552 | int err; | 537 | int err; |
| @@ -572,10 +557,8 @@ struct snd_device object. A component · 19 unmodified lines | |||
| 572 | can be a PCM instance, a control interface, a raw MIDI interface, etc. | 557 | can be a PCM instance, a control interface, a raw MIDI interface, etc. |
| 573 | Each such instance has one component entry. | 558 | Each such instance has one component entry. |
| 574 | 559 | ||
| 575 | A component can be created via :c:func:`snd_device_new()` | 560 | A component can be created via the :c:func:`snd_device_new()` |
| 576 | function. | 561 | function:: |
| 577 | |||
| 578 | :: | ||
| 579 | 562 | ||
| 580 | snd_device_new(card, SNDRV_DEV_XXX, chip, &ops); | 563 | snd_device_new(card, SNDRV_DEV_XXX, chip, &ops); |
| 581 | 564 | ||
| @@ -591,7 +574,7 @@ allocated manually beforehand, and its pointer is passed as the · 9 unmodified lines | |||
| 591 | argument. This pointer (``chip`` in the above example) is used as the | 574 | argument. This pointer (``chip`` in the above example) is used as the |
| 592 | identifier for the instance. | 575 | identifier for the instance. |
| 593 | 576 | ||
| 594 | Each pre-defined ALSA component such as ac97 and pcm calls | 577 | Each pre-defined ALSA component such as AC97 and PCM calls |
| 595 | :c:func:`snd_device_new()` inside its constructor. The destructor | 578 | :c:func:`snd_device_new()` inside its constructor. The destructor |
| 596 | for each component is defined in the callback pointers. Hence, you don't | 579 | for each component is defined in the callback pointers. Hence, you don't |
| 597 | need to take care of calling a destructor for such a component. | 580 | need to take care of calling a destructor for such a component. |
| @@ -605,9 +588,7 @@ Chip-Specific Data · 7 unmodified lines | |||
| 605 | ------------------ | 588 | ------------------ |
| 606 | 589 | ||
| 607 | Chip-specific information, e.g. the I/O port address, its resource | 590 | Chip-specific information, e.g. the I/O port address, its resource |
| 608 | pointer, or the irq number, is stored in the chip-specific record. | 591 | pointer, or the irq number, is stored in the chip-specific record:: |
| 609 | |||
| 610 | :: | ||
| 611 | 592 | ||
| 612 | struct mychip { | 593 | struct mychip { |
| 613 | .... | 594 | .... |
| @@ -620,9 +601,7 @@ In general, there are two ways of allocating the chip record. · 6 unmodified lines | |||
| 620 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | 601 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
| 621 | 602 | ||
| 622 | As mentioned above, you can pass the extra-data-length to the 5th | 603 | As mentioned above, you can pass the extra-data-length to the 5th |
| 623 | argument of :c:func:`snd_card_new()`, i.e. | 604 | argument of :c:func:`snd_card_new()`, e.g.:: |
| 624 | |||
| 625 | :: | ||
| 626 | 605 | ||
| 627 | err = snd_card_new(&pci->dev, index[dev], id[dev], THIS_MODULE, | 606 | err = snd_card_new(&pci->dev, index[dev], id[dev], THIS_MODULE, |
| 628 | sizeof(struct mychip), &card); | 607 | sizeof(struct mychip), &card); |
| @@ -642,9 +621,7 @@ released together with the card instance. · 13 unmodified lines | |||
| 642 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | 621 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
| 643 | 622 | ||
| 644 | After allocating a card instance via :c:func:`snd_card_new()` | 623 | After allocating a card instance via :c:func:`snd_card_new()` |
| 645 | (with ``0`` on the 4th arg), call :c:func:`kzalloc()`. | 624 | (with ``0`` on the 4th arg), call :c:func:`kzalloc()`:: |
| 646 | |||
| 647 | :: | ||
| 648 | 625 | ||
| 649 | struct snd_card *card; | 626 | struct snd_card *card; |
| 650 | struct mychip *chip; | 627 | struct mychip *chip; |
| @@ -663,16 +640,12 @@ The chip record should have the field to hold the card pointer at least, · 12 unmodified lines | |||
| 663 | }; | 640 | }; |
| 664 | 641 | ||
| 665 | 642 | ||
| 666 | Then, set the card pointer in the returned chip instance. | 643 | Then, set the card pointer in the returned chip instance:: |
| 667 | |||
| 668 | :: | ||
| 669 | 644 | ||
| 670 | chip->card = card; | 645 | chip->card = card; |
| 671 | 646 | ||
| 672 | Next, initialize the fields, and register this chip record as a | 647 | Next, initialize the fields, and register this chip record as a |
| 673 | low-level device with a specified ``ops``, | 648 | low-level device with a specified ``ops``:: |
| 674 | |||
| 675 | :: | ||
| 676 | 649 | ||
| 677 | static const struct snd_device_ops ops = { | 650 | static const struct snd_device_ops ops = { |
| 678 | .dev_free = snd_mychip_dev_free, | 651 | .dev_free = snd_mychip_dev_free, |
| @@ -681,9 +654,7 @@ low-level device with a specified ``ops``, · 2 unmodified lines | |||
| 681 | snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops); | 654 | snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops); |
| 682 | 655 | ||
| 683 | :c:func:`snd_mychip_dev_free()` is the device-destructor | 656 | :c:func:`snd_mychip_dev_free()` is the device-destructor |
| 684 | function, which will call the real destructor. | 657 | function, which will call the real destructor:: |
| 685 | |||
| 686 | :: | ||
| 687 | 658 | ||
| 688 | static int snd_mychip_dev_free(struct snd_device *device) | 659 | static int snd_mychip_dev_free(struct snd_device *device) |
| 689 | { | 660 | { |
| @@ -692,10 +663,10 @@ function, which will call the real destructor. · 2 unmodified lines | |||
| 692 | 663 | ||
| 693 | where :c:func:`snd_mychip_free()` is the real destructor. | 664 | where :c:func:`snd_mychip_free()` is the real destructor. |
| 694 | 665 | ||
| 695 | The demerit of this method is the obviously more amount of codes. | 666 | The demerit of this method is the obviously larger amount of code. |
| 696 | The merit is, however, you can trigger the own callback at registering | 667 | The merit is, however, that you can trigger your own callback at |
| 697 | and disconnecting the card via setting in snd_device_ops. | 668 | registering and disconnecting the card via a setting in snd_device_ops. |
| 698 | About the registering and disconnecting the card, see the subsections | 669 | About registering and disconnecting the card, see the subsections |
| 699 | below. | 670 | below. |
| 700 | 671 | ||
| 701 | 672 | ||
| @@ -724,9 +695,7 @@ Full Code Example · 22 unmodified lines | |||
| 724 | ----------------- | 695 | ----------------- |
| 725 | 696 | ||
| 726 | In this section, we'll complete the chip-specific constructor, | 697 | In this section, we'll complete the chip-specific constructor, |
| 727 | destructor and PCI entries. Example code is shown first, below. | 698 | destructor and PCI entries. Example code is shown first, below:: |
| 728 | |||
| 729 | :: | ||
| 730 | 699 | ||
| 731 | struct mychip { | 700 | struct mychip { |
| 732 | struct snd_card *card; | 701 | struct snd_card *card; |
| @@ -866,9 +835,7 @@ resources. Also, you need to set the proper PCI DMA mask to limit the · 133 unmodified lines | |||
| 866 | accessed I/O range. In some cases, you might need to call | 835 | accessed I/O range. In some cases, you might need to call |
| 867 | :c:func:`pci_set_master()` function, too. | 836 | :c:func:`pci_set_master()` function, too. |
| 868 | 837 | ||
| 869 | Suppose the 28bit mask, and the code to be added would be like: | 838 | Suppose a 28bit mask, the code to be added would look like:: |
| 870 | |||
| 871 | :: | ||
| 872 | 839 | ||
| 873 | err = pci_enable_device(pci); | 840 | err = pci_enable_device(pci); |
| 874 | if (err < 0) | 841 | if (err < 0) |
| @@ -890,9 +857,7 @@ function (see below). · 15 unmodified lines | |||
| 890 | 857 | ||
| 891 | Now assume that the PCI device has an I/O port with 8 bytes and an | 858 | Now assume that the PCI device has an I/O port with 8 bytes and an |
| 892 | interrupt. Then struct mychip will have the | 859 | interrupt. Then struct mychip will have the |
| 893 | following fields: | 860 | following fields:: |
| 894 | |||
| 895 | :: | ||
| 896 | 861 | ||
| 897 | struct mychip { | 862 | struct mychip { |
| 898 | struct snd_card *card; | 863 | struct snd_card *card; |
| @@ -905,14 +870,12 @@ following fields: · 6 unmodified lines | |||
| 905 | For an I/O port (and also a memory region), you need to have the | 870 | For an I/O port (and also a memory region), you need to have the |
| 906 | resource pointer for the standard resource management. For an irq, you | 871 | resource pointer for the standard resource management. For an irq, you |
| 907 | have to keep only the irq number (integer). But you need to initialize | 872 | have to keep only the irq number (integer). But you need to initialize |
| 908 | this number as -1 before actual allocation, since irq 0 is valid. The | 873 | this number to -1 before actual allocation, since irq 0 is valid. The |
| 909 | port address and its resource pointer can be initialized as null by | 874 | port address and its resource pointer can be initialized as null by |
| 910 | :c:func:`kzalloc()` automatically, so you don't have to take care of | 875 | :c:func:`kzalloc()` automatically, so you don't have to take care of |
| 911 | resetting them. | 876 | resetting them. |
| 912 | 877 | ||
| 913 | The allocation of an I/O port is done like this: | 878 | The allocation of an I/O port is done like this:: |
| 914 | |||
| 915 | :: | ||
| 916 | 879 | ||
| 917 | err = pci_request_regions(pci, "My Chip"); | 880 | err = pci_request_regions(pci, "My Chip"); |
| 918 | if (err < 0) { | 881 | if (err < 0) { |
| @@ -928,9 +891,7 @@ The returned value, ``chip->res_port``, is allocated via · 9 unmodified lines | |||
| 928 | must be released via :c:func:`kfree()`, but there is a problem with | 891 | must be released via :c:func:`kfree()`, but there is a problem with |
| 929 | this. This issue will be explained later. | 892 | this. This issue will be explained later. |
| 930 | 893 | ||
| 931 | The allocation of an interrupt source is done like this: | 894 | The allocation of an interrupt source is done like this:: |
| 932 | |||
| 933 | :: | ||
| 934 | 895 | ||
| 935 | if (request_irq(pci->irq, snd_mychip_interrupt, | 896 | if (request_irq(pci->irq, snd_mychip_interrupt, |
| 936 | IRQF_SHARED, KBUILD_MODNAME, chip)) { | 897 | IRQF_SHARED, KBUILD_MODNAME, chip)) { |
| @@ -954,9 +915,7 @@ used for that, but you can use what you like, too. · 17 unmodified lines | |||
| 954 | 915 | ||
| 955 | I won't give details about the interrupt handler at this point, but at | 916 | I won't give details about the interrupt handler at this point, but at |
| 956 | least its appearance can be explained now. The interrupt handler looks | 917 | least its appearance can be explained now. The interrupt handler looks |
| 957 | usually like the following: | 918 | usually as follows:: |
| 958 | |||
| 959 | :: | ||
| 960 | 919 | ||
| 961 | static irqreturn_t snd_mychip_interrupt(int irq, void *dev_id) | 920 | static irqreturn_t snd_mychip_interrupt(int irq, void *dev_id) |
| 962 | { | 921 | { |
| @@ -966,13 +925,12 @@ usually like the following: · 3 unmodified lines | |||
| 966 | } | 925 | } |
| 967 | 926 | ||
| 968 | After requesting the IRQ, you can passed it to ``card->sync_irq`` | 927 | After requesting the IRQ, you can passed it to ``card->sync_irq`` |
| 969 | field: | 928 | field:: |
| 970 | :: | ||
| 971 | 929 | ||
| 972 | card->irq = chip->irq; | 930 | card->irq = chip->irq; |
| 973 | 931 | ||
| 974 | This allows PCM core automatically performing | 932 | This allows the PCM core to automatically call |
| 975 | :c:func:`synchronize_irq()` at the necessary timing like ``hw_free``. | 933 | :c:func:`synchronize_irq()` at the right time, like before ``hw_free``. |
| 976 | See the later section `sync_stop callback`_ for details. | 934 | See the later section `sync_stop callback`_ for details. |
| 977 | 935 | ||
| 978 | Now let's write the corresponding destructor for the resources above. | 936 | Now let's write the corresponding destructor for the resources above. |
| @@ -981,9 +939,7 @@ activated) and release the resources. So far, we have no hardware part, · 2 unmodified lines | |||
| 981 | so the disabling code is not written here. | 939 | so the disabling code is not written here. |
| 982 | 940 | ||
| 983 | To release the resources, the “check-and-release” method is a safer way. | 941 | To release the resources, the “check-and-release” method is a safer way. |
| 984 | For the interrupt, do like this: | 942 | For the interrupt, do like this:: |
| 985 | |||
| 986 | :: | ||
| 987 | 943 | ||
| 988 | if (chip->irq >= 0) | 944 | if (chip->irq >= 0) |
| 989 | free_irq(chip->irq, chip); | 945 | free_irq(chip->irq, chip); |
| @@ -997,9 +953,7 @@ When you requested I/O ports or memory regions via · 7 unmodified lines | |||
| 997 | :c:func:`pci_request_regions()` like in this example, release the | 953 | :c:func:`pci_request_regions()` like in this example, release the |
| 998 | resource(s) using the corresponding function, | 954 | resource(s) using the corresponding function, |
| 999 | :c:func:`pci_release_region()` or | 955 | :c:func:`pci_release_region()` or |
| 1000 | :c:func:`pci_release_regions()`. | 956 | :c:func:`pci_release_regions()`:: |
| 1001 | |||
| 1002 | :: | ||
| 1003 | 957 | ||
| 1004 | pci_release_regions(chip->pci); | 958 | pci_release_regions(chip->pci); |
| 1005 | 959 | ||
| @@ -1007,39 +961,32 @@ When you requested manually via :c:func:`request_region()` or · 1 unmodified line | |||
| 1007 | :c:func:`request_mem_region()`, you can release it via | 961 | :c:func:`request_mem_region()`, you can release it via |
| 1008 | :c:func:`release_resource()`. Suppose that you keep the resource | 962 | :c:func:`release_resource()`. Suppose that you keep the resource |
| 1009 | pointer returned from :c:func:`request_region()` in | 963 | pointer returned from :c:func:`request_region()` in |
| 1010 | chip->res_port, the release procedure looks like: | 964 | chip->res_port, the release procedure looks like:: |
| 1011 | |||
| 1012 | :: | ||
| 1013 | 965 | ||
| 1014 | release_and_free_resource(chip->res_port); | 966 | release_and_free_resource(chip->res_port); |
| 1015 | 967 | ||
| 1016 | Don't forget to call :c:func:`pci_disable_device()` before the | 968 | Don't forget to call :c:func:`pci_disable_device()` before the |
| 1017 | end. | 969 | end. |
| 1018 | 970 | ||
| 1019 | And finally, release the chip-specific record. | 971 | And finally, release the chip-specific record:: |
| 1020 | |||
| 1021 | :: | ||
| 1022 | 972 | ||
| 1023 | kfree(chip); | 973 | kfree(chip); |
| 1024 | 974 | ||
| 1025 | We didn't implement the hardware disabling part in the above. If you | 975 | We didn't implement the hardware disabling part above. If you |
| 1026 | need to do this, please note that the destructor may be called even | 976 | need to do this, please note that the destructor may be called even |
| 1027 | before the initialization of the chip is completed. It would be better | 977 | before the initialization of the chip is completed. It would be better |
| 1028 | to have a flag to skip hardware disabling if the hardware was not | 978 | to have a flag to skip hardware disabling if the hardware was not |
| 1029 | initialized yet. | 979 | initialized yet. |
| 1030 | 980 | ||
| 1031 | When the chip-data is assigned to the card using | 981 | When the chip-data is assigned to the card using |
| 1032 | :c:func:`snd_device_new()` with ``SNDRV_DEV_LOWLELVEL`` , its | 982 | :c:func:`snd_device_new()` with ``SNDRV_DEV_LOWLELVEL``, its |
| 1033 | destructor is called at the last. That is, it is assured that all other | 983 | destructor is called last. That is, it is assured that all other |
| 1034 | components like PCMs and controls have already been released. You don't | 984 | components like PCMs and controls have already been released. You don't |
| 1035 | have to stop PCMs, etc. explicitly, but just call low-level hardware | 985 | have to stop PCMs, etc. explicitly, but just call low-level hardware |
| 1036 | stopping. | 986 | stopping. |
| 1037 | 987 | ||
| 1038 | The management of a memory-mapped region is almost as same as the | 988 | The management of a memory-mapped region is almost as same as the |
| 1039 | management of an I/O port. You'll need three fields like the | 989 | management of an I/O port. You'll need two fields as follows:: |
| 1040 | following: | ||
| 1041 | |||
| 1042 | :: | ||
| 1043 | 990 | ||
| 1044 | struct mychip { | 991 | struct mychip { |
| 1045 | .... | 992 | .... |
| @@ -1047,9 +994,7 @@ following: · 1 unmodified line | |||
| 1047 | void __iomem *iobase_virt; | 994 | void __iomem *iobase_virt; |
| 1048 | }; | 995 | }; |
| 1049 | 996 | ||
| 1050 | and the allocation would be like below: | 997 | and the allocation would look like below:: |
| 1051 | |||
| 1052 | :: | ||
| 1053 | 998 | ||
| 1054 | err = pci_request_regions(pci, "My Chip"); | 999 | err = pci_request_regions(pci, "My Chip"); |
| 1055 | if (err < 0) { | 1000 | if (err < 0) { |
| @@ -1060,9 +1005,7 @@ and the allocation would be like below: · 4 unmodified lines | |||
| 1060 | chip->iobase_virt = ioremap(chip->iobase_phys, | 1005 | chip->iobase_virt = ioremap(chip->iobase_phys, |
| 1061 | pci_resource_len(pci, 0)); | 1006 | pci_resource_len(pci, 0)); |
| 1062 | 1007 | ||
| 1063 | and the corresponding destructor would be: | 1008 | and the corresponding destructor would be:: |
| 1064 | |||
| 1065 | :: | ||
| 1066 | 1009 | ||
| 1067 | static int snd_mychip_free(struct mychip *chip) | 1010 | static int snd_mychip_free(struct mychip *chip) |
| 1068 | { | 1011 | { |
| @@ -1075,9 +1018,7 @@ and the corresponding destructor would be: · 6 unmodified lines | |||
| 1075 | } | 1018 | } |
| 1076 | 1019 | ||
| 1077 | Of course, a modern way with :c:func:`pci_iomap()` will make things a | 1020 | Of course, a modern way with :c:func:`pci_iomap()` will make things a |
| 1078 | bit easier, too. | 1021 | bit easier, too:: |
| 1079 | |||
| 1080 | :: | ||
| 1081 | 1022 | ||
| 1082 | err = pci_request_regions(pci, "My Chip"); | 1023 | err = pci_request_regions(pci, "My Chip"); |
| 1083 | if (err < 0) { | 1024 | if (err < 0) { |
| @@ -1097,9 +1038,7 @@ struct pci_device_id table for · 13 unmodified lines | |||
| 1097 | this chipset. It's a table of PCI vendor/device ID number, and some | 1038 | this chipset. It's a table of PCI vendor/device ID number, and some |
| 1098 | masks. | 1039 | masks. |
| 1099 | 1040 | ||
| 1100 | For example, | 1041 | For example:: |
| 1101 | |||
| 1102 | :: | ||
| 1103 | 1042 | ||
| 1104 | static struct pci_device_id snd_mychip_ids[] = { | 1043 | static struct pci_device_id snd_mychip_ids[] = { |
| 1105 | { PCI_VENDOR_ID_FOO, PCI_DEVICE_ID_BAR, | 1044 | { PCI_VENDOR_ID_FOO, PCI_DEVICE_ID_BAR, |
| @@ -1120,9 +1059,7 @@ The last entry of this list is the terminator. You must specify this · 14 unmodified lines | |||
| 1120 | all-zero entry. | 1059 | all-zero entry. |
| 1121 | 1060 | ||
| 1122 | Then, prepare the struct pci_driver | 1061 | Then, prepare the struct pci_driver |
| 1123 | record: | 1062 | record:: |
| 1124 | |||
| 1125 | :: | ||
| 1126 | 1063 | ||
| 1127 | static struct pci_driver driver = { | 1064 | static struct pci_driver driver = { |
| 1128 | .name = KBUILD_MODNAME, | 1065 | .name = KBUILD_MODNAME, |
| @@ -1133,11 +1070,9 @@ record: · 4 unmodified lines | |||
| 1133 | 1070 | ||
| 1134 | The ``probe`` and ``remove`` functions have already been defined in | 1071 | The ``probe`` and ``remove`` functions have already been defined in |
| 1135 | the previous sections. The ``name`` field is the name string of this | 1072 | the previous sections. The ``name`` field is the name string of this |
| 1136 | device. Note that you must not use a slash “/” in this string. | 1073 | device. Note that you must not use slashes (“/”) in this string. |
| 1137 | |||
| 1138 | And at last, the module entries: | ||
| 1139 | 1074 | ||
| 1140 | :: | 1075 | And at last, the module entries:: |
| 1141 | 1076 | ||
| 1142 | static int __init alsa_card_mychip_init(void) | 1077 | static int __init alsa_card_mychip_init(void) |
| 1143 | { | 1078 | { |
| @@ -1167,22 +1102,22 @@ The PCM middle layer of ALSA is quite powerful and it is only necessary · 23 unmodified lines | |||
| 1167 | for each driver to implement the low-level functions to access its | 1102 | for each driver to implement the low-level functions to access its |
| 1168 | hardware. | 1103 | hardware. |
| 1169 | 1104 | ||
| 1170 | For accessing to the PCM layer, you need to include ``<sound/pcm.h>`` | 1105 | To access the PCM layer, you need to include ``<sound/pcm.h>`` |
| 1171 | first. In addition, ``<sound/pcm_params.h>`` might be needed if you | 1106 | first. In addition, ``<sound/pcm_params.h>`` might be needed if you |
| 1172 | access to some functions related with hw_param. | 1107 | access some functions related with hw_param. |
| 1173 | 1108 | ||
| 1174 | Each card device can have up to four pcm instances. A pcm instance | 1109 | Each card device can have up to four PCM instances. A PCM instance |
| 1175 | corresponds to a pcm device file. The limitation of number of instances | 1110 | corresponds to a PCM device file. The limitation of number of instances |
| 1176 | comes only from the available bit size of the Linux's device numbers. | 1111 | comes only from the available bit size of Linux' device numbers. |
| 1177 | Once when 64bit device number is used, we'll have more pcm instances | 1112 | Once 64bit device numbers are used, we'll have more PCM instances |
| 1178 | available. | 1113 | available. |
| 1179 | 1114 | ||
| 1180 | A pcm instance consists of pcm playback and capture streams, and each | 1115 | A PCM instance consists of PCM playback and capture streams, and each |
| 1181 | pcm stream consists of one or more pcm substreams. Some soundcards | 1116 | PCM stream consists of one or more PCM substreams. Some soundcards |
| 1182 | support multiple playback functions. For example, emu10k1 has a PCM | 1117 | support multiple playback functions. For example, emu10k1 has a PCM |
| 1183 | playback of 32 stereo substreams. In this case, at each open, a free | 1118 | playback of 32 stereo substreams. In this case, at each open, a free |
| 1184 | substream is (usually) automatically chosen and opened. Meanwhile, when | 1119 | substream is (usually) automatically chosen and opened. Meanwhile, when |
| 1185 | only one substream exists and it was already opened, the successful open | 1120 | only one substream exists and it was already opened, a subsequent open |
| 1186 | will either block or error with ``EAGAIN`` according to the file open | 1121 | will either block or error with ``EAGAIN`` according to the file open |
| 1187 | mode. But you don't have to care about such details in your driver. The | 1122 | mode. But you don't have to care about such details in your driver. The |
| 1188 | PCM middle layer will take care of such work. | 1123 | PCM middle layer will take care of such work. |
| @@ -1191,9 +1126,7 @@ Full Code Example · 2 unmodified lines | |||
| 1191 | ----------------- | 1126 | ----------------- |
| 1192 | 1127 | ||
| 1193 | The example code below does not include any hardware access routines but | 1128 | The example code below does not include any hardware access routines but |
| 1194 | shows only the skeleton, how to build up the PCM interfaces. | 1129 | shows only the skeleton, how to build up the PCM interfaces:: |
| 1195 | |||
| 1196 | :: | ||
| 1197 | 1130 | ||
| 1198 | #include <sound/pcm.h> | 1131 | #include <sound/pcm.h> |
| 1199 | .... | 1132 | .... |
| @@ -1399,10 +1332,8 @@ shows only the skeleton, how to build up the PCM interfaces. · 199 unmodified lines | |||
| 1399 | PCM Constructor | 1332 | PCM Constructor |
| 1400 | --------------- | 1333 | --------------- |
| 1401 | 1334 | ||
| 1402 | A pcm instance is allocated by the :c:func:`snd_pcm_new()` | 1335 | A PCM instance is allocated by the :c:func:`snd_pcm_new()` |
| 1403 | function. It would be better to create a constructor for pcm, namely, | 1336 | function. It would be better to create a constructor for the PCM, namely:: |
| 1404 | |||
| 1405 | :: | ||
| 1406 | 1337 | ||
| 1407 | static int snd_mychip_new_pcm(struct mychip *chip) | 1338 | static int snd_mychip_new_pcm(struct mychip *chip) |
| 1408 | { | 1339 | { |
| @@ -1415,16 +1346,16 @@ function. It would be better to create a constructor for pcm, namely, · 6 unmodified lines | |||
| 1415 | pcm->private_data = chip; | 1346 | pcm->private_data = chip; |
| 1416 | strcpy(pcm->name, "My Chip"); | 1347 | strcpy(pcm->name, "My Chip"); |
| 1417 | chip->pcm = pcm; | 1348 | chip->pcm = pcm; |
| 1418 | .... | 1349 | ... |
| 1419 | return 0; | 1350 | return 0; |
| 1420 | } | 1351 | } |
| 1421 | 1352 | ||
| 1422 | The :c:func:`snd_pcm_new()` function takes four arguments. The | 1353 | The :c:func:`snd_pcm_new()` function takes six arguments. The |
| 1423 | first argument is the card pointer to which this pcm is assigned, and | 1354 | first argument is the card pointer to which this PCM is assigned, and |
| 1424 | the second is the ID string. | 1355 | the second is the ID string. |
| 1425 | 1356 | ||
| 1426 | The third argument (``index``, 0 in the above) is the index of this new | 1357 | The third argument (``index``, 0 in the above) is the index of this new |
| 1427 | pcm. It begins from zero. If you create more than one pcm instances, | 1358 | PCM. It begins from zero. If you create more than one PCM instances, |
| 1428 | specify the different numbers in this argument. For example, ``index = | 1359 | specify the different numbers in this argument. For example, ``index = |
| 1429 | 1`` for the second PCM device. | 1360 | 1`` for the second PCM device. |
| 1430 | 1361 | ||
| @@ -1437,26 +1368,20 @@ If a chip supports multiple playbacks or captures, you can specify more · 6 unmodified lines | |||
| 1437 | numbers, but they must be handled properly in open/close, etc. | 1368 | numbers, but they must be handled properly in open/close, etc. |
| 1438 | callbacks. When you need to know which substream you are referring to, | 1369 | callbacks. When you need to know which substream you are referring to, |
| 1439 | then it can be obtained from struct snd_pcm_substream data passed to each | 1370 | then it can be obtained from struct snd_pcm_substream data passed to each |
| 1440 | callback as follows: | 1371 | callback as follows:: |
| 1441 | |||
| 1442 | :: | ||
| 1443 | 1372 | ||
| 1444 | struct snd_pcm_substream *substream; | 1373 | struct snd_pcm_substream *substream; |
| 1445 | int index = substream->number; | 1374 | int index = substream->number; |
| 1446 | 1375 | ||
| 1447 | 1376 | ||
| 1448 | After the pcm is created, you need to set operators for each pcm stream. | 1377 | After the PCM is created, you need to set operators for each PCM stream:: |
| 1449 | |||
| 1450 | :: | ||
| 1451 | 1378 | ||
| 1452 | snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, | 1379 | snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, |
| 1453 | &snd_mychip_playback_ops); | 1380 | &snd_mychip_playback_ops); |
| 1454 | snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, | 1381 | snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, |
| 1455 | &snd_mychip_capture_ops); | 1382 | &snd_mychip_capture_ops); |
| 1456 | 1383 | ||
| 1457 | The operators are defined typically like this: | 1384 | The operators are defined typically like this:: |
| 1458 | |||
| 1459 | :: | ||
| 1460 | 1385 | ||
| 1461 | static struct snd_pcm_ops snd_mychip_playback_ops = { | 1386 | static struct snd_pcm_ops snd_mychip_playback_ops = { |
| 1462 | .open = snd_mychip_pcm_open, | 1387 | .open = snd_mychip_pcm_open, |
| @@ -1472,25 +1397,21 @@ All the callbacks are described in the Operators_ subsection. · 9 unmodified lines | |||
| 1472 | 1397 | ||
| 1473 | After setting the operators, you probably will want to pre-allocate the | 1398 | After setting the operators, you probably will want to pre-allocate the |
| 1474 | buffer and set up the managed allocation mode. | 1399 | buffer and set up the managed allocation mode. |
| 1475 | For that, simply call the following: | 1400 | For that, simply call the following:: |
| 1476 | |||
| 1477 | :: | ||
| 1478 | 1401 | ||
| 1479 | snd_pcm_set_managed_buffer_all(pcm, SNDRV_DMA_TYPE_DEV, | 1402 | snd_pcm_set_managed_buffer_all(pcm, SNDRV_DMA_TYPE_DEV, |
| 1480 | &chip->pci->dev, | 1403 | &chip->pci->dev, |
| 1481 | 64*1024, 64*1024); | 1404 | 64*1024, 64*1024); |
| 1482 | 1405 | ||
| 1483 | It will allocate a buffer up to 64kB as default. Buffer management | 1406 | It will allocate a buffer up to 64kB by default. Buffer management |
| 1484 | details will be described in the later section `Buffer and Memory | 1407 | details will be described in the later section `Buffer and Memory |
| 1485 | Management`_. | 1408 | Management`_. |
| 1486 | 1409 | ||
| 1487 | Additionally, you can set some extra information for this pcm in | 1410 | Additionally, you can set some extra information for this PCM in |
| 1488 | ``pcm->info_flags``. The available values are defined as | 1411 | ``pcm->info_flags``. The available values are defined as |
| 1489 | ``SNDRV_PCM_INFO_XXX`` in ``<sound/asound.h>``, which is used for the | 1412 | ``SNDRV_PCM_INFO_XXX`` in ``<sound/asound.h>``, which is used for the |
| 1490 | hardware definition (described later). When your soundchip supports only | 1413 | hardware definition (described later). When your soundchip supports only |
| 1491 | half-duplex, specify like this: | 1414 | half-duplex, specify it like this:: |
| 1492 | |||
| 1493 | :: | ||
| 1494 | 1415 | ||
| 1495 | pcm->info_flags = SNDRV_PCM_INFO_HALF_DUPLEX; | 1416 | pcm->info_flags = SNDRV_PCM_INFO_HALF_DUPLEX; |
| 1496 | 1417 | ||
| @@ -1498,15 +1419,13 @@ half-duplex, specify like this: · 1 unmodified line | |||
| 1498 | ... And the Destructor? | 1419 | ... And the Destructor? |
| 1499 | ----------------------- | 1420 | ----------------------- |
| 1500 | 1421 | ||
| 1501 | The destructor for a pcm instance is not always necessary. Since the pcm | 1422 | The destructor for a PCM instance is not always necessary. Since the PCM |
| 1502 | device will be released by the middle layer code automatically, you | 1423 | device will be released by the middle layer code automatically, you |
| 1503 | don't have to call the destructor explicitly. | 1424 | don't have to call the destructor explicitly. |
| 1504 | 1425 | ||
| 1505 | The destructor would be necessary if you created special records | 1426 | The destructor would be necessary if you created special records |
| 1506 | internally and needed to release them. In such a case, set the | 1427 | internally and needed to release them. In such a case, set the |
| 1507 | destructor function to ``pcm->private_free``: | 1428 | destructor function to ``pcm->private_free``:: |
| 1508 | |||
| 1509 | :: | ||
| 1510 | 1429 | ||
| 1511 | static void mychip_pcm_free(struct snd_pcm *pcm) | 1430 | static void mychip_pcm_free(struct snd_pcm *pcm) |
| 1512 | { | 1431 | { |
| @@ -1537,13 +1456,11 @@ Runtime Pointer - The Chest of PCM Information · 24 unmodified lines | |||
| 1537 | When the PCM substream is opened, a PCM runtime instance is allocated | 1456 | When the PCM substream is opened, a PCM runtime instance is allocated |
| 1538 | and assigned to the substream. This pointer is accessible via | 1457 | and assigned to the substream. This pointer is accessible via |
| 1539 | ``substream->runtime``. This runtime pointer holds most information you | 1458 | ``substream->runtime``. This runtime pointer holds most information you |
| 1540 | need to control the PCM: the copy of hw_params and sw_params | 1459 | need to control the PCM: a copy of hw_params and sw_params |
| 1541 | configurations, the buffer pointers, mmap records, spinlocks, etc. | 1460 | configurations, the buffer pointers, mmap records, spinlocks, etc. |
| 1542 | 1461 | ||
| 1543 | The definition of runtime instance is found in ``<sound/pcm.h>``. Here | 1462 | The definition of runtime instance is found in ``<sound/pcm.h>``. Here |
| 1544 | are the contents of this file: | 1463 | is the relevant part of this file:: |
| 1545 | |||
| 1546 | :: | ||
| 1547 | 1464 | ||
| 1548 | struct _snd_pcm_runtime { | 1465 | struct _snd_pcm_runtime { |
| 1549 | /* -- Status -- */ | 1466 | /* -- Status -- */ |
| @@ -1577,14 +1494,19 @@ are the contents of this file: · 27 unmodified lines | |||
| 1577 | unsigned int period_step; | 1494 | unsigned int period_step; |
| 1578 | unsigned int sleep_min; /* min ticks to sleep */ | 1495 | unsigned int sleep_min; /* min ticks to sleep */ |
| 1579 | snd_pcm_uframes_t start_threshold; | 1496 | snd_pcm_uframes_t start_threshold; |
| 1580 | snd_pcm_uframes_t stop_threshold; | 1497 | /* |
| 1581 | snd_pcm_uframes_t silence_threshold; /* Silence filling happens when | 1498 | * The following two thresholds alleviate playback buffer underruns; when |
| 1582 | noise is nearest than this */ | 1499 | * hw_avail drops below the threshold, the respective action is triggered: |
| 1583 | snd_pcm_uframes_t silence_size; /* Silence filling size */ | 1500 | */ |
| 1501 | snd_pcm_uframes_t stop_threshold; /* - stop playback */ | ||
| 1502 | snd_pcm_uframes_t silence_threshold; /* - pre-fill buffer with silence */ | ||
| 1503 | snd_pcm_uframes_t silence_size; /* max size of silence pre-fill; when >= boundary, | ||
| 1504 | * fill played area with silence immediately */ | ||
| 1584 | snd_pcm_uframes_t boundary; /* pointers wrap point */ | 1505 | snd_pcm_uframes_t boundary; /* pointers wrap point */ |
| 1585 | 1506 | ||
| 1586 | snd_pcm_uframes_t silenced_start; | 1507 | /* internal data of auto-silencer */ |
| 1587 | snd_pcm_uframes_t silenced_size; | 1508 | snd_pcm_uframes_t silence_start; /* starting pointer to silence area */ |
| 1509 | snd_pcm_uframes_t silence_filled; /* size filled with silence */ | ||
| 1588 | 1510 | ||
| 1589 | snd_pcm_sync_id_t sync; /* hardware synchronization ID */ | 1511 | snd_pcm_sync_id_t sync; /* hardware synchronization ID */ |
| 1590 | 1512 | ||
| @@ -1638,14 +1560,12 @@ Hardware Description · 47 unmodified lines | |||
| 1638 | 1560 | ||
| 1639 | The hardware descriptor (struct snd_pcm_hardware) contains the definitions of | 1561 | The hardware descriptor (struct snd_pcm_hardware) contains the definitions of |
| 1640 | the fundamental hardware configuration. Above all, you'll need to define this | 1562 | the fundamental hardware configuration. Above all, you'll need to define this |
| 1641 | in the `PCM open callback`_. Note that the runtime instance holds the copy of | 1563 | in the `PCM open callback`_. Note that the runtime instance holds a copy of |
| 1642 | the descriptor, not the pointer to the existing descriptor. That is, | 1564 | the descriptor, not a pointer to the existing descriptor. That is, |
| 1643 | in the open callback, you can modify the copied descriptor | 1565 | in the open callback, you can modify the copied descriptor |
| 1644 | (``runtime->hw``) as you need. For example, if the maximum number of | 1566 | (``runtime->hw``) as you need. For example, if the maximum number of |
| 1645 | channels is 1 only on some chip models, you can still use the same | 1567 | channels is 1 only on some chip models, you can still use the same |
| 1646 | hardware descriptor and change the channels_max later: | 1568 | hardware descriptor and change the channels_max later:: |
| 1647 | |||
| 1648 | :: | ||
| 1649 | 1569 | ||
| 1650 | struct snd_pcm_runtime *runtime = substream->runtime; | 1570 | struct snd_pcm_runtime *runtime = substream->runtime; |
| 1651 | ... | 1571 | ... |
| @@ -1653,9 +1573,7 @@ hardware descriptor and change the channels_max later: · 1 unmodified line | |||
| 1653 | if (chip->model == VERY_OLD_ONE) | 1573 | if (chip->model == VERY_OLD_ONE) |
| 1654 | runtime->hw.channels_max = 1; | 1574 | runtime->hw.channels_max = 1; |
| 1655 | 1575 | ||
| 1656 | Typically, you'll have a hardware descriptor as below: | 1576 | Typically, you'll have a hardware descriptor as below:: |
| 1657 | |||
| 1658 | :: | ||
| 1659 | 1577 | ||
| 1660 | static struct snd_pcm_hardware snd_mychip_playback_hw = { | 1578 | static struct snd_pcm_hardware snd_mychip_playback_hw = { |
| 1661 | .info = (SNDRV_PCM_INFO_MMAP | | 1579 | .info = (SNDRV_PCM_INFO_MMAP | |
| @@ -1676,51 +1594,51 @@ Typically, you'll have a hardware descriptor as below: · 14 unmodified lines | |||
| 1676 | }; | 1594 | }; |
| 1677 | 1595 | ||
| 1678 | - The ``info`` field contains the type and capabilities of this | 1596 | - The ``info`` field contains the type and capabilities of this |
| 1679 | pcm. The bit flags are defined in ``<sound/asound.h>`` as | 1597 | PCM. The bit flags are defined in ``<sound/asound.h>`` as |
| 1680 | ``SNDRV_PCM_INFO_XXX``. Here, at least, you have to specify whether | 1598 | ``SNDRV_PCM_INFO_XXX``. Here, at least, you have to specify whether |
| 1681 | the mmap is supported and which interleaved format is | 1599 | mmap is supported and which interleaving formats are |
| 1682 | supported. When the hardware supports mmap, add the | 1600 | supported. When the hardware supports mmap, add the |
| 1683 | ``SNDRV_PCM_INFO_MMAP`` flag here. When the hardware supports the | 1601 | ``SNDRV_PCM_INFO_MMAP`` flag here. When the hardware supports the |
| 1684 | interleaved or the non-interleaved formats, | 1602 | interleaved or the non-interleaved formats, the |
| 1685 | ``SNDRV_PCM_INFO_INTERLEAVED`` or ``SNDRV_PCM_INFO_NONINTERLEAVED`` | 1603 | ``SNDRV_PCM_INFO_INTERLEAVED`` or ``SNDRV_PCM_INFO_NONINTERLEAVED`` |
| 1686 | flag must be set, respectively. If both are supported, you can set | 1604 | flag must be set, respectively. If both are supported, you can set |
| 1687 | both, too. | 1605 | both, too. |
| 1688 | 1606 | ||
| 1689 | In the above example, ``MMAP_VALID`` and ``BLOCK_TRANSFER`` are | 1607 | In the above example, ``MMAP_VALID`` and ``BLOCK_TRANSFER`` are |
| 1690 | specified for the OSS mmap mode. Usually both are set. Of course, | 1608 | specified for the OSS mmap mode. Usually both are set. Of course, |
| 1691 | ``MMAP_VALID`` is set only if the mmap is really supported. | 1609 | ``MMAP_VALID`` is set only if mmap is really supported. |
| 1692 | 1610 | ||
| 1693 | The other possible flags are ``SNDRV_PCM_INFO_PAUSE`` and | 1611 | The other possible flags are ``SNDRV_PCM_INFO_PAUSE`` and |
| 1694 | ``SNDRV_PCM_INFO_RESUME``. The ``PAUSE`` bit means that the pcm | 1612 | ``SNDRV_PCM_INFO_RESUME``. The ``PAUSE`` bit means that the PCM |
| 1695 | supports the “pause” operation, while the ``RESUME`` bit means that | 1613 | supports the “pause” operation, while the ``RESUME`` bit means that |
| 1696 | the pcm supports the full “suspend/resume” operation. If the | 1614 | the PCM supports the full “suspend/resume” operation. If the |
| 1697 | ``PAUSE`` flag is set, the ``trigger`` callback below must handle | 1615 | ``PAUSE`` flag is set, the ``trigger`` callback below must handle |
| 1698 | the corresponding (pause push/release) commands. The suspend/resume | 1616 | the corresponding (pause push/release) commands. The suspend/resume |
| 1699 | trigger commands can be defined even without the ``RESUME`` | 1617 | trigger commands can be defined even without the ``RESUME`` |
| 1700 | flag. See `Power Management`_ section for details. | 1618 | flag. See the `Power Management`_ section for details. |
| 1701 | 1619 | ||
| 1702 | When the PCM substreams can be synchronized (typically, | 1620 | When the PCM substreams can be synchronized (typically, |
| 1703 | synchronized start/stop of a playback and a capture streams), you | 1621 | synchronized start/stop of a playback and a capture stream), you |
| 1704 | can give ``SNDRV_PCM_INFO_SYNC_START``, too. In this case, you'll | 1622 | can give ``SNDRV_PCM_INFO_SYNC_START``, too. In this case, you'll |
| 1705 | need to check the linked-list of PCM substreams in the trigger | 1623 | need to check the linked-list of PCM substreams in the trigger |
| 1706 | callback. This will be described in the later section. | 1624 | callback. This will be described in a later section. |
| 1707 | 1625 | ||
| 1708 | - ``formats`` field contains the bit-flags of supported formats | 1626 | - The ``formats`` field contains the bit-flags of supported formats |
| 1709 | (``SNDRV_PCM_FMTBIT_XXX``). If the hardware supports more than one | 1627 | (``SNDRV_PCM_FMTBIT_XXX``). If the hardware supports more than one |
| 1710 | format, give all or'ed bits. In the example above, the signed 16bit | 1628 | format, give all or'ed bits. In the example above, the signed 16bit |
| 1711 | little-endian format is specified. | 1629 | little-endian format is specified. |
| 1712 | 1630 | ||
| 1713 | - ``rates`` field contains the bit-flags of supported rates | 1631 | - The ``rates`` field contains the bit-flags of supported rates |
| 1714 | (``SNDRV_PCM_RATE_XXX``). When the chip supports continuous rates, | 1632 | (``SNDRV_PCM_RATE_XXX``). When the chip supports continuous rates, |
| 1715 | pass ``CONTINUOUS`` bit additionally. The pre-defined rate bits are | 1633 | pass the ``CONTINUOUS`` bit additionally. The pre-defined rate bits |
| 1716 | provided only for typical rates. If your chip supports | 1634 | are provided only for typical rates. If your chip supports |
| 1717 | unconventional rates, you need to add the ``KNOT`` bit and set up | 1635 | unconventional rates, you need to add the ``KNOT`` bit and set up |
| 1718 | the hardware constraint manually (explained later). | 1636 | the hardware constraint manually (explained later). |
| 1719 | 1637 | ||
| 1720 | - ``rate_min`` and ``rate_max`` define the minimum and maximum sample | 1638 | - ``rate_min`` and ``rate_max`` define the minimum and maximum sample |
| 1721 | rate. This should correspond somehow to ``rates`` bits. | 1639 | rate. This should correspond somehow to ``rates`` bits. |
| 1722 | 1640 | ||
| 1723 | - ``channels_min`` and ``channels_max`` define, as you might already | 1641 | - ``channels_min`` and ``channels_max`` define, as you might have already |
| 1724 | expected, the minimum and maximum number of channels. | 1642 | expected, the minimum and maximum number of channels. |
| 1725 | 1643 | ||
| 1726 | - ``buffer_bytes_max`` defines the maximum buffer size in | 1644 | - ``buffer_bytes_max`` defines the maximum buffer size in |
| @@ -1732,15 +1650,16 @@ Typically, you'll have a hardware descriptor as below: · 5 unmodified lines | |||
| 1732 | number of periods in the buffer. | 1650 | number of periods in the buffer. |
| 1733 | 1651 | ||
| 1734 | The “period” is a term that corresponds to a fragment in the OSS | 1652 | The “period” is a term that corresponds to a fragment in the OSS |
| 1735 | world. The period defines the size at which a PCM interrupt is | 1653 | world. The period defines the point at which a PCM interrupt is |
| 1736 | generated. This size strongly depends on the hardware. Generally, | 1654 | generated. This point strongly depends on the hardware. Generally, |
| 1737 | the smaller period size will give you more interrupts, that is, | 1655 | a smaller period size will give you more interrupts, which results |
| 1738 | more controls. In the case of capture, this size defines the input | 1656 | in being able to fill/drain the buffer more timely. In the case of |
| 1739 | latency. On the other hand, the whole buffer size defines the | 1657 | capture, this size defines the input latency. On the other hand, |
| 1740 | output latency for the playback direction. | 1658 | the whole buffer size defines the output latency for the playback |
| 1659 | direction. | ||
| 1741 | 1660 | ||
| 1742 | - There is also a field ``fifo_size``. This specifies the size of the | 1661 | - There is also a field ``fifo_size``. This specifies the size of the |
| 1743 | hardware FIFO, but currently it is neither used in the driver nor | 1662 | hardware FIFO, but currently it is neither used by the drivers nor |
| 1744 | in the alsa-lib. So, you can ignore this field. | 1663 | in the alsa-lib. So, you can ignore this field. |
| 1745 | 1664 | ||
| 1746 | PCM Configurations | 1665 | PCM Configurations |
| @@ -1759,34 +1678,32 @@ One thing to be noted is that the configured buffer and period sizes · 12 unmodified lines | |||
| 1759 | are stored in “frames” in the runtime. In the ALSA world, ``1 frame = | 1678 | are stored in “frames” in the runtime. In the ALSA world, ``1 frame = |
| 1760 | channels \* samples-size``. For conversion between frames and bytes, | 1679 | channels \* samples-size``. For conversion between frames and bytes, |
| 1761 | you can use the :c:func:`frames_to_bytes()` and | 1680 | you can use the :c:func:`frames_to_bytes()` and |
| 1762 | :c:func:`bytes_to_frames()` helper functions. | 1681 | :c:func:`bytes_to_frames()` helper functions:: |
| 1763 | |||
| 1764 | :: | ||
| 1765 | 1682 | ||
| 1766 | period_bytes = frames_to_bytes(runtime, runtime->period_size); | 1683 | period_bytes = frames_to_bytes(runtime, runtime->period_size); |
| 1767 | 1684 | ||
| 1768 | Also, many software parameters (sw_params) are stored in frames, too. | 1685 | Also, many software parameters (sw_params) are stored in frames, too. |
| 1769 | Please check the type of the field. ``snd_pcm_uframes_t`` is for the | 1686 | Please check the type of the field. ``snd_pcm_uframes_t`` is for |
| 1770 | frames as unsigned integer while ``snd_pcm_sframes_t`` is for the | 1687 | frames as unsigned integer while ``snd_pcm_sframes_t`` is for |
| 1771 | frames as signed integer. | 1688 | frames as signed integer. |
| 1772 | 1689 | ||
| 1773 | DMA Buffer Information | 1690 | DMA Buffer Information |
| 1774 | ~~~~~~~~~~~~~~~~~~~~~~ | 1691 | ~~~~~~~~~~~~~~~~~~~~~~ |
| 1775 | 1692 | ||
| 1776 | The DMA buffer is defined by the following four fields, ``dma_area``, | 1693 | The DMA buffer is defined by the following four fields: ``dma_area``, |
| 1777 | ``dma_addr``, ``dma_bytes`` and ``dma_private``. The ``dma_area`` | 1694 | ``dma_addr``, ``dma_bytes`` and ``dma_private``. ``dma_area`` |
| 1778 | holds the buffer pointer (the logical address). You can call | 1695 | holds the buffer pointer (the logical address). You can call |
| 1779 | :c:func:`memcpy()` from/to this pointer. Meanwhile, ``dma_addr`` holds | 1696 | :c:func:`memcpy()` from/to this pointer. Meanwhile, ``dma_addr`` holds |
| 1780 | the physical address of the buffer. This field is specified only when | 1697 | the physical address of the buffer. This field is specified only when |
| 1781 | the buffer is a linear buffer. ``dma_bytes`` holds the size of buffer | 1698 | the buffer is a linear buffer. ``dma_bytes`` holds the size of the |
| 1782 | in bytes. ``dma_private`` is used for the ALSA DMA allocator. | 1699 | buffer in bytes. ``dma_private`` is used for the ALSA DMA allocator. |
| 1783 | 1700 | ||
| 1784 | If you use either the managed buffer allocation mode or the standard | 1701 | If you use either the managed buffer allocation mode or the standard |
| 1785 | API function :c:func:`snd_pcm_lib_malloc_pages()` for allocating the buffer, | 1702 | API function :c:func:`snd_pcm_lib_malloc_pages()` for allocating the buffer, |
| 1786 | these fields are set by the ALSA middle layer, and you should *not* | 1703 | these fields are set by the ALSA middle layer, and you should *not* |
| 1787 | change them by yourself. You can read them but not write them. On the | 1704 | change them by yourself. You can read them but not write them. On the |
| 1788 | other hand, if you want to allocate the buffer by yourself, you'll | 1705 | other hand, if you want to allocate the buffer by yourself, you'll |
| 1789 | need to manage it in hw_params callback. At least, ``dma_bytes`` is | 1706 | need to manage it in the hw_params callback. At least, ``dma_bytes`` is |
| 1790 | mandatory. ``dma_area`` is necessary when the buffer is mmapped. If | 1707 | mandatory. ``dma_area`` is necessary when the buffer is mmapped. If |
| 1791 | your driver doesn't support mmap, this field is not | 1708 | your driver doesn't support mmap, this field is not |
| 1792 | necessary. ``dma_addr`` is also optional. You can use dma_private as | 1709 | necessary. ``dma_addr`` is also optional. You can use dma_private as |
| @@ -1796,13 +1713,13 @@ Running Status · 3 unmodified lines | |||
| 1796 | ~~~~~~~~~~~~~~ | 1713 | ~~~~~~~~~~~~~~ |
| 1797 | 1714 | ||
| 1798 | The running status can be referred via ``runtime->status``. This is | 1715 | The running status can be referred via ``runtime->status``. This is |
| 1799 | the pointer to the struct snd_pcm_mmap_status record. | 1716 | a pointer to a struct snd_pcm_mmap_status record. |
| 1800 | For example, you can get the current | 1717 | For example, you can get the current |
| 1801 | DMA hardware pointer via ``runtime->status->hw_ptr``. | 1718 | DMA hardware pointer via ``runtime->status->hw_ptr``. |
| 1802 | 1719 | ||
| 1803 | The DMA application pointer can be referred via ``runtime->control``, | 1720 | The DMA application pointer can be referred via ``runtime->control``, |
| 1804 | which points to the struct snd_pcm_mmap_control record. | 1721 | which points to a struct snd_pcm_mmap_control record. |
| 1805 | However, accessing directly to this value is not recommended. | 1722 | However, accessing this value directly is not recommended. |
| 1806 | 1723 | ||
| 1807 | Private Data | 1724 | Private Data |
| 1808 | ~~~~~~~~~~~~ | 1725 | ~~~~~~~~~~~~ |
| @@ -1811,11 +1728,10 @@ You can allocate a record for the substream and store it in · 2 unmodified lines | |||
| 1811 | ``runtime->private_data``. Usually, this is done in the `PCM open | 1728 | ``runtime->private_data``. Usually, this is done in the `PCM open |
| 1812 | callback`_. Don't mix this with ``pcm->private_data``. The | 1729 | callback`_. Don't mix this with ``pcm->private_data``. The |
| 1813 | ``pcm->private_data`` usually points to the chip instance assigned | 1730 | ``pcm->private_data`` usually points to the chip instance assigned |
| 1814 | statically at the creation of PCM, while the ``runtime->private_data`` | 1731 | statically at creation time of the PCM device, while |
| 1815 | points to a dynamic data structure created at the PCM open | 1732 | ``runtime->private_data`` |
| 1816 | callback. | 1733 | points to a dynamic data structure created in the PCM open |
| 1817 | 1734 | callback:: | |
| 1818 | :: | ||
| 1819 | 1735 | ||
| 1820 | static int snd_xxx_open(struct snd_pcm_substream *substream) | 1736 | static int snd_xxx_open(struct snd_pcm_substream *substream) |
| 1821 | { | 1737 | { |
| @@ -1832,20 +1748,18 @@ The allocated object must be released in the `close callback`_. · 10 unmodified lines | |||
| 1832 | Operators | 1748 | Operators |
| 1833 | --------- | 1749 | --------- |
| 1834 | 1750 | ||
| 1835 | OK, now let me give details about each pcm callback (``ops``). In | 1751 | OK, now let me give details about each PCM callback (``ops``). In |
| 1836 | general, every callback must return 0 if successful, or a negative | 1752 | general, every callback must return 0 if successful, or a negative |
| 1837 | error number such as ``-EINVAL``. To choose an appropriate error | 1753 | error number such as ``-EINVAL``. To choose an appropriate error |
| 1838 | number, it is advised to check what value other parts of the kernel | 1754 | number, it is advised to check what value other parts of the kernel |
| 1839 | return when the same kind of request fails. | 1755 | return when the same kind of request fails. |
| 1840 | 1756 | ||
| 1841 | The callback function takes at least the argument with | 1757 | Each callback function takes at least one argument containing a |
| 1842 | struct snd_pcm_substream pointer. To retrieve the chip | 1758 | struct snd_pcm_substream pointer. To retrieve the chip |
| 1843 | record from the given substream instance, you can use the following | 1759 | record from the given substream instance, you can use the following |
| 1844 | macro. | 1760 | macro:: |
| 1845 | |||
| 1846 | :: | ||
| 1847 | 1761 | ||
| 1848 | int xxx() { | 1762 | int xxx(...) { |
| 1849 | struct mychip *chip = snd_pcm_substream_chip(substream); | 1763 | struct mychip *chip = snd_pcm_substream_chip(substream); |
| 1850 | .... | 1764 | .... |
| 1851 | } | 1765 | } |
| @@ -1864,12 +1778,10 @@ PCM open callback · 12 unmodified lines | |||
| 1864 | 1778 | ||
| 1865 | static int snd_xxx_open(struct snd_pcm_substream *substream); | 1779 | static int snd_xxx_open(struct snd_pcm_substream *substream); |
| 1866 | 1780 | ||
| 1867 | This is called when a pcm substream is opened. | 1781 | This is called when a PCM substream is opened. |
| 1868 | 1782 | ||
| 1869 | At least, here you have to initialize the ``runtime->hw`` | 1783 | At least, here you have to initialize the ``runtime->hw`` |
| 1870 | record. Typically, this is done by like this: | 1784 | record. Typically, this is done like this:: |
| 1871 | |||
| 1872 | :: | ||
| 1873 | 1785 | ||
| 1874 | static int snd_xxx_open(struct snd_pcm_substream *substream) | 1786 | static int snd_xxx_open(struct snd_pcm_substream *substream) |
| 1875 | { | 1787 | { |
| @@ -1883,7 +1795,7 @@ record. Typically, this is done by like this: · 7 unmodified lines | |||
| 1883 | where ``snd_mychip_playback_hw`` is the pre-defined hardware | 1795 | where ``snd_mychip_playback_hw`` is the pre-defined hardware |
| 1884 | description. | 1796 | description. |
| 1885 | 1797 | ||
| 1886 | You can allocate a private data in this callback, as described in | 1798 | You can allocate private data in this callback, as described in the |
| 1887 | `Private Data`_ section. | 1799 | `Private Data`_ section. |
| 1888 | 1800 | ||
| 1889 | If the hardware configuration needs more constraints, set the hardware | 1801 | If the hardware configuration needs more constraints, set the hardware |
| @@ -1897,12 +1809,10 @@ close callback · 7 unmodified lines | |||
| 1897 | static int snd_xxx_close(struct snd_pcm_substream *substream); | 1809 | static int snd_xxx_close(struct snd_pcm_substream *substream); |
| 1898 | 1810 | ||
| 1899 | 1811 | ||
| 1900 | Obviously, this is called when a pcm substream is closed. | 1812 | Obviously, this is called when a PCM substream is closed. |
| 1901 | |||
| 1902 | Any private instance for a pcm substream allocated in the ``open`` | ||
| 1903 | callback will be released here. | ||
| 1904 | 1813 | ||
| 1905 | :: | 1814 | Any private instance for a PCM substream allocated in the ``open`` |
| 1815 | callback will be released here:: | ||
| 1906 | 1816 | ||
| 1907 | static int snd_xxx_close(struct snd_pcm_substream *substream) | 1817 | static int snd_xxx_close(struct snd_pcm_substream *substream) |
| 1908 | { | 1818 | { |
| @@ -1914,9 +1824,9 @@ callback will be released here. · 5 unmodified lines | |||
| 1914 | ioctl callback | 1824 | ioctl callback |
| 1915 | ~~~~~~~~~~~~~~ | 1825 | ~~~~~~~~~~~~~~ |
| 1916 | 1826 | ||
| 1917 | This is used for any special call to pcm ioctls. But usually you can | 1827 | This is used for any special call to PCM ioctls. But usually you can |
| 1918 | leave it as NULL, then PCM core calls the generic ioctl callback | 1828 | leave it NULL, then the PCM core calls the generic ioctl callback |
| 1919 | function :c:func:`snd_pcm_lib_ioctl()`. If you need to deal with the | 1829 | function :c:func:`snd_pcm_lib_ioctl()`. If you need to deal with a |
| 1920 | unique setup of channel info or reset procedure, you can pass your own | 1830 | unique setup of channel info or reset procedure, you can pass your own |
| 1921 | callback function here. | 1831 | callback function here. |
| 1922 | 1832 | ||
| @@ -1928,22 +1838,20 @@ hw_params callback · 5 unmodified lines | |||
| 1928 | static int snd_xxx_hw_params(struct snd_pcm_substream *substream, | 1838 | static int snd_xxx_hw_params(struct snd_pcm_substream *substream, |
| 1929 | struct snd_pcm_hw_params *hw_params); | 1839 | struct snd_pcm_hw_params *hw_params); |
| 1930 | 1840 | ||
| 1931 | This is called when the hardware parameter (``hw_params``) is set up | 1841 | This is called when the hardware parameters (``hw_params``) are set up |
| 1932 | by the application, that is, once when the buffer size, the period | 1842 | by the application, that is, once when the buffer size, the period |
| 1933 | size, the format, etc. are defined for the pcm substream. | 1843 | size, the format, etc. are defined for the PCM substream. |
| 1934 | 1844 | ||
| 1935 | Many hardware setups should be done in this callback, including the | 1845 | Many hardware setups should be done in this callback, including the |
| 1936 | allocation of buffers. | 1846 | allocation of buffers. |
| 1937 | 1847 | ||
| 1938 | Parameters to be initialized are retrieved by | 1848 | Parameters to be initialized are retrieved by the |
| 1939 | :c:func:`params_xxx()` macros. | 1849 | :c:func:`params_xxx()` macros. |
| 1940 | 1850 | ||
| 1941 | When you set up the managed buffer allocation mode for the substream, | 1851 | When you choose managed buffer allocation mode for the substream, |
| 1942 | a buffer is already allocated before this callback gets | 1852 | a buffer is already allocated before this callback gets |
| 1943 | called. Alternatively, you can call a helper function below for | 1853 | called. Alternatively, you can call a helper function below for |
| 1944 | allocating the buffer, too. | 1854 | allocating the buffer:: |
| 1945 | |||
| 1946 | :: | ||
| 1947 | 1855 | ||
| 1948 | snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params)); | 1856 | snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params)); |
| 1949 | 1857 | ||
| @@ -1951,8 +1859,8 @@ allocating the buffer, too. · 1 unmodified line | |||
| 1951 | DMA buffers have been pre-allocated. See the section `Buffer Types`_ | 1859 | DMA buffers have been pre-allocated. See the section `Buffer Types`_ |
| 1952 | for more details. | 1860 | for more details. |
| 1953 | 1861 | ||
| 1954 | Note that this and ``prepare`` callbacks may be called multiple times | 1862 | Note that this one and the ``prepare`` callback may be called multiple |
| 1955 | per initialization. For example, the OSS emulation may call these | 1863 | times per initialization. For example, the OSS emulation may call these |
| 1956 | callbacks at each change via its ioctl. | 1864 | callbacks at each change via its ioctl. |
| 1957 | 1865 | ||
| 1958 | Thus, you need to be careful not to allocate the same buffers many | 1866 | Thus, you need to be careful not to allocate the same buffers many |
| @@ -1960,10 +1868,10 @@ times, which will lead to memory leaks! Calling the helper function · 1 unmodified line | |||
| 1960 | above many times is OK. It will release the previous buffer | 1868 | above many times is OK. It will release the previous buffer |
| 1961 | automatically when it was already allocated. | 1869 | automatically when it was already allocated. |
| 1962 | 1870 | ||
| 1963 | Another note is that this callback is non-atomic (schedulable) as | 1871 | Another note is that this callback is non-atomic (schedulable) by |
| 1964 | default, i.e. when no ``nonatomic`` flag set. This is important, | 1872 | default, i.e. when no ``nonatomic`` flag set. This is important, |
| 1965 | because the ``trigger`` callback is atomic (non-schedulable). That is, | 1873 | because the ``trigger`` callback is atomic (non-schedulable). That is, |
| 1966 | mutexes or any schedule-related functions are not available in | 1874 | mutexes or any schedule-related functions are not available in the |
| 1967 | ``trigger`` callback. Please see the subsection Atomicity_ for | 1875 | ``trigger`` callback. Please see the subsection Atomicity_ for |
| 1968 | details. | 1876 | details. |
| 1969 | 1877 | ||
| @@ -1979,16 +1887,14 @@ This is called to release the resources allocated via · 9 unmodified lines | |||
| 1979 | 1887 | ||
| 1980 | This function is always called before the close callback is called. | 1888 | This function is always called before the close callback is called. |
| 1981 | Also, the callback may be called multiple times, too. Keep track | 1889 | Also, the callback may be called multiple times, too. Keep track |
| 1982 | whether the resource was already released. | 1890 | whether each resource was already released. |
| 1983 | 1891 | ||
| 1984 | When you have set up the managed buffer allocation mode for the PCM | 1892 | When you have chosen managed buffer allocation mode for the PCM |
| 1985 | substream, the allocated PCM buffer will be automatically released | 1893 | substream, the allocated PCM buffer will be automatically released |
| 1986 | after this callback gets called. Otherwise you'll have to release the | 1894 | after this callback gets called. Otherwise you'll have to release the |
| 1987 | buffer manually. Typically, when the buffer was allocated from the | 1895 | buffer manually. Typically, when the buffer was allocated from the |
| 1988 | pre-allocated pool, you can use the standard API function | 1896 | pre-allocated pool, you can use the standard API function |
| 1989 | :c:func:`snd_pcm_lib_malloc_pages()` like: | 1897 | :c:func:`snd_pcm_lib_malloc_pages()` like:: |
| 1990 | |||
| 1991 | :: | ||
| 1992 | 1898 | ||
| 1993 | snd_pcm_lib_free_pages(substream); | 1899 | snd_pcm_lib_free_pages(substream); |
| 1994 | 1900 | ||
| @@ -1999,13 +1905,13 @@ prepare callback · 4 unmodified lines | |||
| 1999 | 1905 | ||
| 2000 | static int snd_xxx_prepare(struct snd_pcm_substream *substream); | 1906 | static int snd_xxx_prepare(struct snd_pcm_substream *substream); |
| 2001 | 1907 | ||
| 2002 | This callback is called when the pcm is “prepared”. You can set the | 1908 | This callback is called when the PCM is “prepared”. You can set the |
| 2003 | format type, sample rate, etc. here. The difference from ``hw_params`` | 1909 | format type, sample rate, etc. here. The difference from ``hw_params`` |
| 2004 | is that the ``prepare`` callback will be called each time | 1910 | is that the ``prepare`` callback will be called each time |
| 2005 | :c:func:`snd_pcm_prepare()` is called, i.e. when recovering after | 1911 | :c:func:`snd_pcm_prepare()` is called, i.e. when recovering after |
| 2006 | underruns, etc. | 1912 | underruns, etc. |
| 2007 | 1913 | ||
| 2008 | Note that this callback is now non-atomic. You can use | 1914 | Note that this callback is non-atomic. You can use |
| 2009 | schedule-related functions safely in this callback. | 1915 | schedule-related functions safely in this callback. |
| 2010 | 1916 | ||
| 2011 | In this and the following callbacks, you can refer to the values via | 1917 | In this and the following callbacks, you can refer to the values via |
| @@ -2026,13 +1932,11 @@ trigger callback · 14 unmodified lines | |||
| 2026 | 1932 | ||
| 2027 | static int snd_xxx_trigger(struct snd_pcm_substream *substream, int cmd); | 1933 | static int snd_xxx_trigger(struct snd_pcm_substream *substream, int cmd); |
| 2028 | 1934 | ||
| 2029 | This is called when the pcm is started, stopped or paused. | 1935 | This is called when the PCM is started, stopped or paused. |
| 2030 | |||
| 2031 | Which action is specified in the second argument, | ||
| 2032 | ``SNDRV_PCM_TRIGGER_XXX`` in ``<sound/pcm.h>``. At least, the ``START`` | ||
| 2033 | and ``STOP`` commands must be defined in this callback. | ||
| 2034 | 1936 | ||
| 2035 | :: | 1937 | The action is specified in the second argument, ``SNDRV_PCM_TRIGGER_XXX`` |
| 1938 | defined in ``<sound/pcm.h>``. At least, the ``START`` | ||
| 1939 | and ``STOP`` commands must be defined in this callback:: | ||
| 2036 | 1940 | ||
| 2037 | switch (cmd) { | 1941 | switch (cmd) { |
| 2038 | case SNDRV_PCM_TRIGGER_START: | 1942 | case SNDRV_PCM_TRIGGER_START: |
| @@ -2045,23 +1949,23 @@ and ``STOP`` commands must be defined in this callback. · 6 unmodified lines | |||
| 2045 | return -EINVAL; | 1949 | return -EINVAL; |
| 2046 | } | 1950 | } |
| 2047 | 1951 | ||
| 2048 | When the pcm supports the pause operation (given in the info field of | 1952 | When the PCM supports the pause operation (given in the info field of |
| 2049 | the hardware table), the ``PAUSE_PUSH`` and ``PAUSE_RELEASE`` commands | 1953 | the hardware table), the ``PAUSE_PUSH`` and ``PAUSE_RELEASE`` commands |
| 2050 | must be handled here, too. The former is the command to pause the pcm, | 1954 | must be handled here, too. The former is the command to pause the PCM, |
| 2051 | and the latter to restart the pcm again. | 1955 | and the latter to restart the PCM again. |
| 2052 | 1956 | ||
| 2053 | When the pcm supports the suspend/resume operation, regardless of full | 1957 | When the PCM supports the suspend/resume operation, regardless of full |
| 2054 | or partial suspend/resume support, the ``SUSPEND`` and ``RESUME`` | 1958 | or partial suspend/resume support, the ``SUSPEND`` and ``RESUME`` |
| 2055 | commands must be handled, too. These commands are issued when the | 1959 | commands must be handled, too. These commands are issued when the |
| 2056 | power-management status is changed. Obviously, the ``SUSPEND`` and | 1960 | power-management status is changed. Obviously, the ``SUSPEND`` and |
| 2057 | ``RESUME`` commands suspend and resume the pcm substream, and usually, | 1961 | ``RESUME`` commands suspend and resume the PCM substream, and usually, |
| 2058 | they are identical to the ``STOP`` and ``START`` commands, respectively. | 1962 | they are identical to the ``STOP`` and ``START`` commands, respectively. |
| 2059 | See the `Power Management`_ section for details. | 1963 | See the `Power Management`_ section for details. |
| 2060 | 1964 | ||
| 2061 | As mentioned, this callback is atomic as default unless ``nonatomic`` | 1965 | As mentioned, this callback is atomic by default unless the ``nonatomic`` |
| 2062 | flag set, and you cannot call functions which may sleep. The | 1966 | flag set, and you cannot call functions which may sleep. The |
| 2063 | ``trigger`` callback should be as minimal as possible, just really | 1967 | ``trigger`` callback should be as minimal as possible, just really |
| 2064 | triggering the DMA. The other stuff should be initialized | 1968 | triggering the DMA. The other stuff should be initialized in |
| 2065 | ``hw_params`` and ``prepare`` callbacks properly beforehand. | 1969 | ``hw_params`` and ``prepare`` callbacks properly beforehand. |
| 2066 | 1970 | ||
| 2067 | sync_stop callback | 1971 | sync_stop callback |
| @@ -2072,22 +1976,22 @@ sync_stop callback · 4 unmodified lines | |||
| 2072 | static int snd_xxx_sync_stop(struct snd_pcm_substream *substream); | 1976 | static int snd_xxx_sync_stop(struct snd_pcm_substream *substream); |
| 2073 | 1977 | ||
| 2074 | This callback is optional, and NULL can be passed. It's called after | 1978 | This callback is optional, and NULL can be passed. It's called after |
| 2075 | the PCM core stops the stream and changes the stream state | 1979 | the PCM core stops the stream, before it changes the stream state via |
| 2076 | ``prepare``, ``hw_params`` or ``hw_free``. | 1980 | ``prepare``, ``hw_params`` or ``hw_free``. |
| 2077 | Since the IRQ handler might be still pending, we need to wait until | 1981 | Since the IRQ handler might be still pending, we need to wait until |
| 2078 | the pending task finishes before moving to the next step; otherwise it | 1982 | the pending task finishes before moving to the next step; otherwise it |
| 2079 | might lead to a crash due to resource conflicts or access to the freed | 1983 | might lead to a crash due to resource conflicts or access to freed |
| 2080 | resources. A typical behavior is to call a synchronization function | 1984 | resources. A typical behavior is to call a synchronization function |
| 2081 | like :c:func:`synchronize_irq()` here. | 1985 | like :c:func:`synchronize_irq()` here. |
| 2082 | 1986 | ||
| 2083 | For majority of drivers that need only a call of | 1987 | For the majority of drivers that need only a call of |
| 2084 | :c:func:`synchronize_irq()`, there is a simpler setup, too. | 1988 | :c:func:`synchronize_irq()`, there is a simpler setup, too. |
| 2085 | While keeping NULL to ``sync_stop`` PCM callback, the driver can set | 1989 | While keeping the ``sync_stop`` PCM callback NULL, the driver can set |
| 2086 | ``card->sync_irq`` field to store the valid interrupt number after | 1990 | the ``card->sync_irq`` field to the returned interrupt number after |
| 2087 | requesting an IRQ, instead. Then PCM core will look call | 1991 | requesting an IRQ, instead. Then PCM core will call |
| 2088 | :c:func:`synchronize_irq()` with the given IRQ appropriately. | 1992 | :c:func:`synchronize_irq()` with the given IRQ appropriately. |
| 2089 | 1993 | ||
| 2090 | If the IRQ handler is released at the card destructor, you don't need | 1994 | If the IRQ handler is released by the card destructor, you don't need |
| 2091 | to clear ``card->sync_irq``, as the card itself is being released. | 1995 | to clear ``card->sync_irq``, as the card itself is being released. |
| 2092 | So, usually you'll need to add just a single line for assigning | 1996 | So, usually you'll need to add just a single line for assigning |
| 2093 | ``card->sync_irq`` in the driver code unless the driver re-acquires | 1997 | ``card->sync_irq`` in the driver code unless the driver re-acquires |
| @@ -2103,30 +2007,30 @@ pointer callback · 9 unmodified lines | |||
| 2103 | static snd_pcm_uframes_t snd_xxx_pointer(struct snd_pcm_substream *substream) | 2007 | static snd_pcm_uframes_t snd_xxx_pointer(struct snd_pcm_substream *substream) |
| 2104 | 2008 | ||
| 2105 | This callback is called when the PCM middle layer inquires the current | 2009 | This callback is called when the PCM middle layer inquires the current |
| 2106 | hardware position on the buffer. The position must be returned in | 2010 | hardware position in the buffer. The position must be returned in |
| 2107 | frames, ranging from 0 to ``buffer_size - 1``. | 2011 | frames, ranging from 0 to ``buffer_size - 1``. |
| 2108 | 2012 | ||
| 2109 | This is called usually from the buffer-update routine in the pcm | 2013 | This is usually called from the buffer-update routine in the PCM |
| 2110 | middle layer, which is invoked when :c:func:`snd_pcm_period_elapsed()` | 2014 | middle layer, which is invoked when :c:func:`snd_pcm_period_elapsed()` |
| 2111 | is called in the interrupt routine. Then the pcm middle layer updates | 2015 | is called by the interrupt routine. Then the PCM middle layer updates |
| 2112 | the position and calculates the available space, and wakes up the | 2016 | the position and calculates the available space, and wakes up the |
| 2113 | sleeping poll threads, etc. | 2017 | sleeping poll threads, etc. |
| 2114 | 2018 | ||
| 2115 | This callback is also atomic as default. | 2019 | This callback is also atomic by default. |
| 2116 | 2020 | ||
| 2117 | copy_user, copy_kernel and fill_silence ops | 2021 | copy_user, copy_kernel and fill_silence ops |
| 2118 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | 2022 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
| 2119 | 2023 | ||
| 2120 | These callbacks are not mandatory, and can be omitted in most cases. | 2024 | These callbacks are not mandatory, and can be omitted in most cases. |
| 2121 | These callbacks are used when the hardware buffer cannot be in the | 2025 | These callbacks are used when the hardware buffer cannot be in the |
| 2122 | normal memory space. Some chips have their own buffer on the hardware | 2026 | normal memory space. Some chips have their own buffer in the hardware |
| 2123 | which is not mappable. In such a case, you have to transfer the data | 2027 | which is not mappable. In such a case, you have to transfer the data |
| 2124 | manually from the memory buffer to the hardware buffer. Or, if the | 2028 | manually from the memory buffer to the hardware buffer. Or, if the |
| 2125 | buffer is non-contiguous on both physical and virtual memory spaces, | 2029 | buffer is non-contiguous on both physical and virtual memory spaces, |
| 2126 | these callbacks must be defined, too. | 2030 | these callbacks must be defined, too. |
| 2127 | 2031 | ||
| 2128 | If these two callbacks are defined, copy and set-silence operations | 2032 | If these two callbacks are defined, copy and set-silence operations |
| 2129 | are done by them. The detailed will be described in the later section | 2033 | are done by them. The details will be described in the later section |
| 2130 | `Buffer and Memory Management`_. | 2034 | `Buffer and Memory Management`_. |
| 2131 | 2035 | ||
| 2132 | ack callback | 2036 | ack callback |
| @@ -2137,7 +2041,11 @@ This callback is also not mandatory. This callback is called when the · 4 unmodified lines | |||
| 2137 | emu10k1-fx and cs46xx need to track the current ``appl_ptr`` for the | 2041 | emu10k1-fx and cs46xx need to track the current ``appl_ptr`` for the |
| 2138 | internal buffer, and this callback is useful only for such a purpose. | 2042 | internal buffer, and this callback is useful only for such a purpose. |
| 2139 | 2043 | ||
| 2140 | This callback is atomic as default. | 2044 | The callback function may return 0 or a negative error. When the |
| 2045 | return value is ``-EPIPE``, PCM core treats that as a buffer XRUN, | ||
| 2046 | and changes the state to ``SNDRV_PCM_STATE_XRUN`` automatically. | ||
| 2047 | |||
| 2048 | This callback is atomic by default. | ||
| 2141 | 2049 | ||
| 2142 | page callback | 2050 | page callback |
| 2143 | ~~~~~~~~~~~~~ | 2051 | ~~~~~~~~~~~~~ |
| @@ -2145,16 +2053,15 @@ page callback · 1 unmodified line | |||
| 2145 | This callback is optional too. The mmap calls this callback to get the | 2053 | This callback is optional too. The mmap calls this callback to get the |
| 2146 | page fault address. | 2054 | page fault address. |
| 2147 | 2055 | ||
| 2148 | Since the recent changes, you need no special callback any longer for | 2056 | You need no special callback for the standard SG-buffer or vmalloc- |
| 2149 | the standard SG-buffer or vmalloc-buffer. Hence this callback should | 2057 | buffer. Hence this callback should be rarely used. |
| 2150 | be rarely used. | ||
| 2151 | 2058 | ||
| 2152 | mmap calllback | 2059 | mmap callback |
| 2153 | ~~~~~~~~~~~~~~ | 2060 | ~~~~~~~~~~~~~ |
| 2154 | 2061 | ||
| 2155 | This is another optional callback for controlling mmap behavior. | 2062 | This is another optional callback for controlling mmap behavior. |
| 2156 | Once when defined, PCM core calls this callback when a page is | 2063 | When defined, the PCM core calls this callback when a page is |
| 2157 | memory-mapped instead of dealing via the standard helper. | 2064 | memory-mapped, instead of using the standard helper. |
| 2158 | If you need special handling (due to some architecture or | 2065 | If you need special handling (due to some architecture or |
| 2159 | device-specific issues), implement everything here as you like. | 2066 | device-specific issues), implement everything here as you like. |
| 2160 | 2067 | ||
| @@ -2162,13 +2069,14 @@ device-specific issues), implement everything here as you like. · 1 unmodified line | |||
| 2162 | PCM Interrupt Handler | 2069 | PCM Interrupt Handler |
| 2163 | --------------------- | 2070 | --------------------- |
| 2164 | 2071 | ||
| 2165 | The rest of pcm stuff is the PCM interrupt handler. The role of PCM | 2072 | The remainder of the PCM stuff is the PCM interrupt handler. The role |
| 2073 | of the PCM | ||
| 2166 | interrupt handler in the sound driver is to update the buffer position | 2074 | interrupt handler in the sound driver is to update the buffer position |
| 2167 | and to tell the PCM middle layer when the buffer position goes across | 2075 | and to tell the PCM middle layer when the buffer position goes across |
| 2168 | the prescribed period size. To inform this, call the | 2076 | the specified period boundary. To inform about this, call the |
| 2169 | :c:func:`snd_pcm_period_elapsed()` function. | 2077 | :c:func:`snd_pcm_period_elapsed()` function. |
| 2170 | 2078 | ||
| 2171 | There are several types of sound chips to generate the interrupts. | 2079 | There are several ways sound chips can generate interrupts. |
| 2172 | 2080 | ||
| 2173 | Interrupts at the period (fragment) boundary | 2081 | Interrupts at the period (fragment) boundary |
| 2174 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | 2082 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
| @@ -2184,14 +2092,12 @@ chip record to hold the current running substream pointer, and set the · 9 unmodified lines | |||
| 2184 | pointer value at ``open`` callback (and reset at ``close`` callback). | 2092 | pointer value at ``open`` callback (and reset at ``close`` callback). |
| 2185 | 2093 | ||
| 2186 | If you acquire a spinlock in the interrupt handler, and the lock is used | 2094 | If you acquire a spinlock in the interrupt handler, and the lock is used |
| 2187 | in other pcm callbacks, too, then you have to release the lock before | 2095 | in other PCM callbacks, too, then you have to release the lock before |
| 2188 | calling :c:func:`snd_pcm_period_elapsed()`, because | 2096 | calling :c:func:`snd_pcm_period_elapsed()`, because |
| 2189 | :c:func:`snd_pcm_period_elapsed()` calls other pcm callbacks | 2097 | :c:func:`snd_pcm_period_elapsed()` calls other PCM callbacks |
| 2190 | inside. | 2098 | inside. |
| 2191 | 2099 | ||
| 2192 | Typical code would be like: | 2100 | Typical code would look like:: |
| 2193 | |||
| 2194 | :: | ||
| 2195 | 2101 | ||
| 2196 | 2102 | ||
| 2197 | static irqreturn_t snd_mychip_interrupt(int irq, void *dev_id) | 2103 | static irqreturn_t snd_mychip_interrupt(int irq, void *dev_id) |
| @@ -2211,6 +2117,12 @@ Typical code would be like: · 13 unmodified lines | |||
| 2211 | return IRQ_HANDLED; | 2117 | return IRQ_HANDLED; |
| 2212 | } | 2118 | } |
| 2213 | 2119 | ||
| 2120 | Also, when the device can detect a buffer underrun/overrun, the driver | ||
| 2121 | can notify the XRUN status to the PCM core by calling | ||
| 2122 | :c:func:`snd_pcm_stop_xrun()`. This function stops the stream and sets | ||
| 2123 | the PCM state to ``SNDRV_PCM_STATE_XRUN``. Note that it must be called | ||
| 2124 | outside the PCM stream lock, hence it can't be called from the atomic | ||
| 2125 | callback. | ||
| 2214 | 2126 | ||
| 2215 | 2127 | ||
| 2216 | High frequency timer interrupts | 2128 | High frequency timer interrupts |
| @@ -2223,9 +2135,7 @@ position and accumulate the processed sample length at each interrupt. · 6 unmodified lines | |||
| 2223 | When the accumulated size exceeds the period size, call | 2135 | When the accumulated size exceeds the period size, call |
| 2224 | :c:func:`snd_pcm_period_elapsed()` and reset the accumulator. | 2136 | :c:func:`snd_pcm_period_elapsed()` and reset the accumulator. |
| 2225 | 2137 | ||
| 2226 | Typical code would be like the following. | 2138 | Typical code would look as follows:: |
| 2227 | |||
| 2228 | :: | ||
| 2229 | 2139 | ||
| 2230 | 2140 | ||
| 2231 | static irqreturn_t snd_mychip_interrupt(int irq, void *dev_id) | 2141 | static irqreturn_t snd_mychip_interrupt(int irq, void *dev_id) |
| @@ -2270,9 +2180,9 @@ Typical code would be like the following. · 38 unmodified lines | |||
| 2270 | On calling :c:func:`snd_pcm_period_elapsed()` | 2180 | On calling :c:func:`snd_pcm_period_elapsed()` |
| 2271 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | 2181 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
| 2272 | 2182 | ||
| 2273 | In both cases, even if more than one period are elapsed, you don't have | 2183 | In both cases, even if more than one period has elapsed, you don't have |
| 2274 | to call :c:func:`snd_pcm_period_elapsed()` many times. Call only | 2184 | to call :c:func:`snd_pcm_period_elapsed()` many times. Call only |
| 2275 | once. And the pcm layer will check the current hardware pointer and | 2185 | once. And the PCM layer will check the current hardware pointer and |
| 2276 | update to the latest status. | 2186 | update to the latest status. |
| 2277 | 2187 | ||
| 2278 | Atomicity | 2188 | Atomicity |
| @@ -2283,15 +2193,16 @@ kernel programming are race conditions. In the Linux kernel, they are · 4 unmodified lines | |||
| 2283 | usually avoided via spin-locks, mutexes or semaphores. In general, if a | 2193 | usually avoided via spin-locks, mutexes or semaphores. In general, if a |
| 2284 | race condition can happen in an interrupt handler, it has to be managed | 2194 | race condition can happen in an interrupt handler, it has to be managed |
| 2285 | atomically, and you have to use a spinlock to protect the critical | 2195 | atomically, and you have to use a spinlock to protect the critical |
| 2286 | session. If the critical section is not in interrupt handler code and if | 2196 | section. If the critical section is not in interrupt handler code and if |
| 2287 | taking a relatively long time to execute is acceptable, you should use | 2197 | taking a relatively long time to execute is acceptable, you should use |
| 2288 | mutexes or semaphores instead. | 2198 | mutexes or semaphores instead. |
| 2289 | 2199 | ||
| 2290 | As already seen, some pcm callbacks are atomic and some are not. For | 2200 | As already seen, some PCM callbacks are atomic and some are not. For |
| 2291 | example, the ``hw_params`` callback is non-atomic, while ``trigger`` | 2201 | example, the ``hw_params`` callback is non-atomic, while the ``trigger`` |
| 2292 | callback is atomic. This means, the latter is called already in a | 2202 | callback is atomic. This means, the latter is called already in a |
| 2293 | spinlock held by the PCM middle layer. Please take this atomicity into | 2203 | spinlock held by the PCM middle layer, the PCM stream lock. Please |
| 2294 | account when you choose a locking scheme in the callbacks. | 2204 | take this atomicity into account when you choose a locking scheme in |
| 2205 | the callbacks. | ||
| 2295 | 2206 | ||
| 2296 | In the atomic callbacks, you cannot use functions which may call | 2207 | In the atomic callbacks, you cannot use functions which may call |
| 2297 | :c:func:`schedule()` or go to :c:func:`sleep()`. Semaphores and | 2208 | :c:func:`schedule()` or go to :c:func:`sleep()`. Semaphores and |
| @@ -2302,29 +2213,34 @@ callback, please use :c:func:`udelay()` or :c:func:`mdelay()`. · 4 unmodified lines | |||
| 2302 | All three atomic callbacks (trigger, pointer, and ack) are called with | 2213 | All three atomic callbacks (trigger, pointer, and ack) are called with |
| 2303 | local interrupts disabled. | 2214 | local interrupts disabled. |
| 2304 | 2215 | ||
| 2305 | The recent changes in PCM core code, however, allow all PCM operations | 2216 | However, it is possible to request all PCM operations to be non-atomic. |
| 2306 | to be non-atomic. This assumes that the all caller sides are in | 2217 | This assumes that all call sites are in |
| 2307 | non-atomic contexts. For example, the function | 2218 | non-atomic contexts. For example, the function |
| 2308 | :c:func:`snd_pcm_period_elapsed()` is called typically from the | 2219 | :c:func:`snd_pcm_period_elapsed()` is called typically from the |
| 2309 | interrupt handler. But, if you set up the driver to use a threaded | 2220 | interrupt handler. But, if you set up the driver to use a threaded |
| 2310 | interrupt handler, this call can be in non-atomic context, too. In such | 2221 | interrupt handler, this call can be in non-atomic context, too. In such |
| 2311 | a case, you can set ``nonatomic`` filed of struct snd_pcm object | 2222 | a case, you can set the ``nonatomic`` field of the struct snd_pcm object |
| 2312 | after creating it. When this flag is set, mutex and rwsem are used internally | 2223 | after creating it. When this flag is set, mutex and rwsem are used internally |
| 2313 | in the PCM core instead of spin and rwlocks, so that you can call all PCM | 2224 | in the PCM core instead of spin and rwlocks, so that you can call all PCM |
| 2314 | functions safely in a non-atomic | 2225 | functions safely in a non-atomic |
| 2315 | context. | 2226 | context. |
| 2316 | 2227 | ||
| 2228 | Also, in some cases, you might need to call | ||
| 2229 | :c:func:`snd_pcm_period_elapsed()` in the atomic context (e.g. the | ||
| 2230 | period gets elapsed during ``ack`` or other callback). There is a | ||
| 2231 | variant that can be called inside the PCM stream lock | ||
| 2232 | :c:func:`snd_pcm_period_elapsed_under_stream_lock()` for that purpose, | ||
| 2233 | too. | ||
| 2234 | |||
| 2317 | Constraints | 2235 | Constraints |
| 2318 | ----------- | 2236 | ----------- |
| 2319 | 2237 | ||
| 2320 | If your chip supports unconventional sample rates, or only the limited | 2238 | Due to physical limitations, hardware is not infinitely configurable. |
| 2321 | samples, you need to set a constraint for the condition. | 2239 | These limitations are expressed by setting constraints. |
| 2322 | 2240 | ||
| 2323 | For example, in order to restrict the sample rates in the some supported | 2241 | For example, in order to restrict the sample rates to some supported |
| 2324 | values, use :c:func:`snd_pcm_hw_constraint_list()`. You need to | 2242 | values, use :c:func:`snd_pcm_hw_constraint_list()`. You need to |
| 2325 | call this function in the open callback. | 2243 | call this function in the open callback:: |
| 2326 | |||
| 2327 | :: | ||
| 2328 | 2244 | ||
| 2329 | static unsigned int rates[] = | 2245 | static unsigned int rates[] = |
| 2330 | {4000, 10000, 22050, 44100}; | 2246 | {4000, 10000, 22050, 44100}; |
| @@ -2346,16 +2262,12 @@ call this function in the open callback. · 15 unmodified lines | |||
| 2346 | .... | 2262 | .... |
| 2347 | } | 2263 | } |
| 2348 | 2264 | ||
| 2349 | |||
| 2350 | |||
| 2351 | There are many different constraints. Look at ``sound/pcm.h`` for a | 2265 | There are many different constraints. Look at ``sound/pcm.h`` for a |
| 2352 | complete list. You can even define your own constraint rules. For | 2266 | complete list. You can even define your own constraint rules. For |
| 2353 | example, let's suppose my_chip can manage a substream of 1 channel if | 2267 | example, let's suppose my_chip can manage a substream of 1 channel if |
| 2354 | and only if the format is ``S16_LE``, otherwise it supports any format | 2268 | and only if the format is ``S16_LE``, otherwise it supports any format |
| 2355 | specified in struct snd_pcm_hardware> (or in any other | 2269 | specified in struct snd_pcm_hardware (or in any other |
| 2356 | constraint_list). You can build a rule like this: | 2270 | constraint_list). You can build a rule like this:: |
| 2357 | |||
| 2358 | :: | ||
| 2359 | 2271 | ||
| 2360 | static int hw_rule_channels_by_format(struct snd_pcm_hw_params *params, | 2272 | static int hw_rule_channels_by_format(struct snd_pcm_hw_params *params, |
| 2361 | struct snd_pcm_hw_rule *rule) | 2273 | struct snd_pcm_hw_rule *rule) |
| @@ -2375,9 +2287,7 @@ constraint_list). You can build a rule like this: · 13 unmodified lines | |||
| 2375 | } | 2287 | } |
| 2376 | 2288 | ||
| 2377 | 2289 | ||
| 2378 | Then you need to call this function to add your rule: | 2290 | Then you need to call this function to add your rule:: |
| 2379 | |||
| 2380 | :: | ||
| 2381 | 2291 | ||
| 2382 | snd_pcm_hw_rule_add(substream->runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS, | 2292 | snd_pcm_hw_rule_add(substream->runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS, |
| 2383 | hw_rule_channels_by_format, NULL, | 2293 | hw_rule_channels_by_format, NULL, |
| @@ -2386,9 +2296,7 @@ Then you need to call this function to add your rule: · 2 unmodified lines | |||
| 2386 | The rule function is called when an application sets the PCM format, and | 2296 | The rule function is called when an application sets the PCM format, and |
| 2387 | it refines the number of channels accordingly. But an application may | 2297 | it refines the number of channels accordingly. But an application may |
| 2388 | set the number of channels before setting the format. Thus you also need | 2298 | set the number of channels before setting the format. Thus you also need |
| 2389 | to define the inverse rule: | 2299 | to define the inverse rule:: |
| 2390 | |||
| 2391 | :: | ||
| 2392 | 2300 | ||
| 2393 | static int hw_rule_format_by_channels(struct snd_pcm_hw_params *params, | 2301 | static int hw_rule_format_by_channels(struct snd_pcm_hw_params *params, |
| 2394 | struct snd_pcm_hw_rule *rule) | 2302 | struct snd_pcm_hw_rule *rule) |
| @@ -2407,16 +2315,14 @@ to define the inverse rule: · 12 unmodified lines | |||
| 2407 | } | 2315 | } |
| 2408 | 2316 | ||
| 2409 | 2317 | ||
| 2410 | ... and in the open callback: | 2318 | ... and in the open callback:: |
| 2411 | |||
| 2412 | :: | ||
| 2413 | 2319 | ||
| 2414 | snd_pcm_hw_rule_add(substream->runtime, 0, SNDRV_PCM_HW_PARAM_FORMAT, | 2320 | snd_pcm_hw_rule_add(substream->runtime, 0, SNDRV_PCM_HW_PARAM_FORMAT, |
| 2415 | hw_rule_format_by_channels, NULL, | 2321 | hw_rule_format_by_channels, NULL, |
| 2416 | SNDRV_PCM_HW_PARAM_CHANNELS, -1); | 2322 | SNDRV_PCM_HW_PARAM_CHANNELS, -1); |
| 2417 | 2323 | ||
| 2418 | One typical usage of the hw constraints is to align the buffer size | 2324 | One typical usage of the hw constraints is to align the buffer size |
| 2419 | with the period size. As default, ALSA PCM core doesn't enforce the | 2325 | with the period size. By default, ALSA PCM core doesn't enforce the |
| 2420 | buffer size to be aligned with the period size. For example, it'd be | 2326 | buffer size to be aligned with the period size. For example, it'd be |
| 2421 | possible to have a combination like 256 period bytes with 999 buffer | 2327 | possible to have a combination like 256 period bytes with 999 buffer |
| 2422 | bytes. | 2328 | bytes. |
| @@ -2424,9 +2330,7 @@ bytes. · 1 unmodified line | |||
| 2424 | Many device chips, however, require the buffer to be a multiple of | 2330 | Many device chips, however, require the buffer to be a multiple of |
| 2425 | periods. In such a case, call | 2331 | periods. In such a case, call |
| 2426 | :c:func:`snd_pcm_hw_constraint_integer()` for | 2332 | :c:func:`snd_pcm_hw_constraint_integer()` for |
| 2427 | ``SNDRV_PCM_HW_PARAM_PERIODS``. | 2333 | ``SNDRV_PCM_HW_PARAM_PERIODS``:: |
| 2428 | |||
| 2429 | :: | ||
| 2430 | 2334 | ||
| 2431 | snd_pcm_hw_constraint_integer(substream->runtime, | 2335 | snd_pcm_hw_constraint_integer(substream->runtime, |
| 2432 | SNDRV_PCM_HW_PARAM_PERIODS); | 2336 | SNDRV_PCM_HW_PARAM_PERIODS); |
| @@ -2434,7 +2338,7 @@ periods. In such a case, call · 1 unmodified line | |||
| 2434 | This assures that the number of periods is integer, hence the buffer | 2338 | This assures that the number of periods is integer, hence the buffer |
| 2435 | size is aligned with the period size. | 2339 | size is aligned with the period size. |
| 2436 | 2340 | ||
| 2437 | The hw constraint is a very much powerful mechanism to define the | 2341 | The hw constraint is a very powerful mechanism to define the |
| 2438 | preferred PCM configuration, and there are relevant helpers. | 2342 | preferred PCM configuration, and there are relevant helpers. |
| 2439 | I won't give more details here, rather I would like to say, “Luke, use | 2343 | I won't give more details here, rather I would like to say, “Luke, use |
| 2440 | the source.” | 2344 | the source.” |
| @@ -2461,9 +2365,7 @@ Definition of Controls · 20 unmodified lines | |||
| 2461 | 2365 | ||
| 2462 | To create a new control, you need to define the following three | 2366 | To create a new control, you need to define the following three |
| 2463 | callbacks: ``info``, ``get`` and ``put``. Then, define a | 2367 | callbacks: ``info``, ``get`` and ``put``. Then, define a |
| 2464 | struct snd_kcontrol_new record, such as: | 2368 | struct snd_kcontrol_new record, such as:: |
| 2465 | |||
| 2466 | :: | ||
| 2467 | 2369 | ||
| 2468 | 2370 | ||
| 2469 | static struct snd_kcontrol_new my_control = { | 2371 | static struct snd_kcontrol_new my_control = { |
| @@ -2506,7 +2408,7 @@ The ``private_value`` field contains an arbitrary long integer value · 36 unmodified lines | |||
| 2506 | for this record. When using the generic ``info``, ``get`` and ``put`` | 2408 | for this record. When using the generic ``info``, ``get`` and ``put`` |
| 2507 | callbacks, you can pass a value through this field. If several small | 2409 | callbacks, you can pass a value through this field. If several small |
| 2508 | numbers are necessary, you can combine them in bitwise. Or, it's | 2410 | numbers are necessary, you can combine them in bitwise. Or, it's |
| 2509 | possible to give a pointer (casted to unsigned long) of some record to | 2411 | possible to store a pointer (casted to unsigned long) of some record in |
| 2510 | this field, too. | 2412 | this field, too. |
| 2511 | 2413 | ||
| 2512 | The ``tlv`` field can be used to provide metadata about the control; | 2414 | The ``tlv`` field can be used to provide metadata about the control; |
| @@ -2573,7 +2475,7 @@ The access flag is the bitmask which specifies the access type of the · 60 unmodified lines | |||
| 2573 | given control. The default access type is | 2475 | given control. The default access type is |
| 2574 | ``SNDRV_CTL_ELEM_ACCESS_READWRITE``, which means both read and write are | 2476 | ``SNDRV_CTL_ELEM_ACCESS_READWRITE``, which means both read and write are |
| 2575 | allowed to this control. When the access flag is omitted (i.e. = 0), it | 2477 | allowed to this control. When the access flag is omitted (i.e. = 0), it |
| 2576 | is considered as ``READWRITE`` access as default. | 2478 | is considered as ``READWRITE`` access by default. |
| 2577 | 2479 | ||
| 2578 | When the control is read-only, pass ``SNDRV_CTL_ELEM_ACCESS_READ`` | 2480 | When the control is read-only, pass ``SNDRV_CTL_ELEM_ACCESS_READ`` |
| 2579 | instead. In this case, you don't have to define the ``put`` callback. | 2481 | instead. In this case, you don't have to define the ``put`` callback. |
| @@ -2586,8 +2488,11 @@ If the control value changes frequently (e.g. the VU meter), · 6 unmodified lines | |||
| 2586 | changed without `Change notification`_. Applications should poll such | 2488 | changed without `Change notification`_. Applications should poll such |
| 2587 | a control constantly. | 2489 | a control constantly. |
| 2588 | 2490 | ||
| 2589 | When the control is inactive, set the ``INACTIVE`` flag, too. There are | 2491 | When the control may be updated, but currently has no effect on anything, |
| 2590 | ``LOCK`` and ``OWNER`` flags to change the write permissions. | 2492 | setting the ``INACTIVE`` flag may be appropriate. For example, PCM |
| 2493 | controls should be inactive while no PCM device is open. | ||
| 2494 | |||
| 2495 | There are ``LOCK`` and ``OWNER`` flags to change the write permissions. | ||
| 2591 | 2496 | ||
| 2592 | Control Callbacks | 2497 | Control Callbacks |
| 2593 | ----------------- | 2498 | ----------------- |
| @@ -2598,9 +2503,7 @@ info callback · 4 unmodified lines | |||
| 2598 | The ``info`` callback is used to get detailed information on this | 2503 | The ``info`` callback is used to get detailed information on this |
| 2599 | control. This must store the values of the given | 2504 | control. This must store the values of the given |
| 2600 | struct snd_ctl_elem_info object. For example, | 2505 | struct snd_ctl_elem_info object. For example, |
| 2601 | for a boolean control with a single element: | 2506 | for a boolean control with a single element:: |
| 2602 | |||
| 2603 | :: | ||
| 2604 | 2507 | ||
| 2605 | 2508 | ||
| 2606 | static int snd_myctl_mono_info(struct snd_kcontrol *kcontrol, | 2509 | static int snd_myctl_mono_info(struct snd_kcontrol *kcontrol, |
| @@ -2619,13 +2522,11 @@ The ``type`` field specifies the type of the control. There are · 12 unmodified lines | |||
| 2619 | ``BOOLEAN``, ``INTEGER``, ``ENUMERATED``, ``BYTES``, ``IEC958`` and | 2522 | ``BOOLEAN``, ``INTEGER``, ``ENUMERATED``, ``BYTES``, ``IEC958`` and |
| 2620 | ``INTEGER64``. The ``count`` field specifies the number of elements in | 2523 | ``INTEGER64``. The ``count`` field specifies the number of elements in |
| 2621 | this control. For example, a stereo volume would have count = 2. The | 2524 | this control. For example, a stereo volume would have count = 2. The |
| 2622 | ``value`` field is a union, and the values stored are depending on the | 2525 | ``value`` field is a union, and the values stored depend on the |
| 2623 | type. The boolean and integer types are identical. | 2526 | type. The boolean and integer types are identical. |
| 2624 | 2527 | ||
| 2625 | The enumerated type is a bit different from others. You'll need to set | 2528 | The enumerated type is a bit different from the others. You'll need to |
| 2626 | the string for the currently given item index. | 2529 | set the string for the selectec item index:: |
| 2627 | |||
| 2628 | :: | ||
| 2629 | 2530 | ||
| 2630 | static int snd_myctl_enum_info(struct snd_kcontrol *kcontrol, | 2531 | static int snd_myctl_enum_info(struct snd_kcontrol *kcontrol, |
| 2631 | struct snd_ctl_elem_info *uinfo) | 2532 | struct snd_ctl_elem_info *uinfo) |
| @@ -2670,13 +2571,10 @@ stereo channel boolean item. · 38 unmodified lines | |||
| 2670 | get callback | 2571 | get callback |
| 2671 | ~~~~~~~~~~~~ | 2572 | ~~~~~~~~~~~~ |
| 2672 | 2573 | ||
| 2673 | This callback is used to read the current value of the control and to | 2574 | This callback is used to read the current value of the control, so it |
| 2674 | return to user-space. | 2575 | can be returned to user-space. |
| 2675 | |||
| 2676 | For example, | ||
| 2677 | |||
| 2678 | :: | ||
| 2679 | 2576 | ||
| 2577 | For example:: | ||
| 2680 | 2578 | ||
| 2681 | static int snd_myctl_get(struct snd_kcontrol *kcontrol, | 2579 | static int snd_myctl_get(struct snd_kcontrol *kcontrol, |
| 2682 | struct snd_ctl_elem_value *ucontrol) | 2580 | struct snd_ctl_elem_value *ucontrol) |
| @@ -2691,15 +2589,11 @@ For example, · 8 unmodified lines | |||
| 2691 | The ``value`` field depends on the type of control as well as on the | 2589 | The ``value`` field depends on the type of control as well as on the |
| 2692 | info callback. For example, the sb driver uses this field to store the | 2590 | info callback. For example, the sb driver uses this field to store the |
| 2693 | register offset, the bit-shift and the bit-mask. The ``private_value`` | 2591 | register offset, the bit-shift and the bit-mask. The ``private_value`` |
| 2694 | field is set as follows: | 2592 | field is set as follows:: |
| 2695 | |||
| 2696 | :: | ||
| 2697 | 2593 | ||
| 2698 | .private_value = reg | (shift << 16) | (mask << 24) | 2594 | .private_value = reg | (shift << 16) | (mask << 24) |
| 2699 | 2595 | ||
| 2700 | and is retrieved in callbacks like | 2596 | and is retrieved in callbacks like:: |
| 2701 | |||
| 2702 | :: | ||
| 2703 | 2597 | ||
| 2704 | static int snd_sbmixer_get_single(struct snd_kcontrol *kcontrol, | 2598 | static int snd_sbmixer_get_single(struct snd_kcontrol *kcontrol, |
| 2705 | struct snd_ctl_elem_value *ucontrol) | 2599 | struct snd_ctl_elem_value *ucontrol) |
| @@ -2711,19 +2605,16 @@ and is retrieved in callbacks like · 5 unmodified lines | |||
| 2711 | } | 2605 | } |
| 2712 | 2606 | ||
| 2713 | In the ``get`` callback, you have to fill all the elements if the | 2607 | In the ``get`` callback, you have to fill all the elements if the |
| 2714 | control has more than one elements, i.e. ``count > 1``. In the example | 2608 | control has more than one element, i.e. ``count > 1``. In the example |
| 2715 | above, we filled only one element (``value.integer.value[0]``) since | 2609 | above, we filled only one element (``value.integer.value[0]``) since |
| 2716 | it's assumed as ``count = 1``. | 2610 | ``count = 1`` is assumed. |
| 2717 | 2611 | ||
| 2718 | put callback | 2612 | put callback |
| 2719 | ~~~~~~~~~~~~ | 2613 | ~~~~~~~~~~~~ |
| 2720 | 2614 | ||
| 2721 | This callback is used to write a value from user-space. | 2615 | This callback is used to write a value coming from user-space. |
| 2722 | |||
| 2723 | For example, | ||
| 2724 | |||
| 2725 | :: | ||
| 2726 | 2616 | ||
| 2617 | For example:: | ||
| 2727 | 2618 | ||
| 2728 | static int snd_myctl_put(struct snd_kcontrol *kcontrol, | 2619 | static int snd_myctl_put(struct snd_kcontrol *kcontrol, |
| 2729 | struct snd_ctl_elem_value *ucontrol) | 2620 | struct snd_ctl_elem_value *ucontrol) |
| @@ -2746,12 +2637,12 @@ value is not changed, return 0 instead. If any fatal error happens, · 16 unmodified lines | |||
| 2746 | return a negative error code as usual. | 2637 | return a negative error code as usual. |
| 2747 | 2638 | ||
| 2748 | As in the ``get`` callback, when the control has more than one | 2639 | As in the ``get`` callback, when the control has more than one |
| 2749 | elements, all elements must be evaluated in this callback, too. | 2640 | element, all elements must be evaluated in this callback, too. |
| 2750 | 2641 | ||
| 2751 | Callbacks are not atomic | 2642 | Callbacks are not atomic |
| 2752 | ~~~~~~~~~~~~~~~~~~~~~~~~ | 2643 | ~~~~~~~~~~~~~~~~~~~~~~~~ |
| 2753 | 2644 | ||
| 2754 | All these three callbacks are basically not atomic. | 2645 | All these three callbacks are not-atomic. |
| 2755 | 2646 | ||
| 2756 | Control Constructor | 2647 | Control Constructor |
| 2757 | ------------------- | 2648 | ------------------- |
| @@ -2760,9 +2651,7 @@ When everything is ready, finally we can create a new control. To create · 2 unmodified lines | |||
| 2760 | a control, there are two functions to be called, | 2651 | a control, there are two functions to be called, |
| 2761 | :c:func:`snd_ctl_new1()` and :c:func:`snd_ctl_add()`. | 2652 | :c:func:`snd_ctl_new1()` and :c:func:`snd_ctl_add()`. |
| 2762 | 2653 | ||
| 2763 | In the simplest way, you can do like this: | 2654 | In the simplest way, you can do it like this:: |
| 2764 | |||
| 2765 | :: | ||
| 2766 | 2655 | ||
| 2767 | err = snd_ctl_add(card, snd_ctl_new1(&my_control, chip)); | 2656 | err = snd_ctl_add(card, snd_ctl_new1(&my_control, chip)); |
| 2768 | if (err < 0) | 2657 | if (err < 0) |
| @@ -2780,9 +2669,7 @@ Change Notification · 11 unmodified lines | |||
| 2780 | ------------------- | 2669 | ------------------- |
| 2781 | 2670 | ||
| 2782 | If you need to change and update a control in the interrupt routine, you | 2671 | If you need to change and update a control in the interrupt routine, you |
| 2783 | can call :c:func:`snd_ctl_notify()`. For example, | 2672 | can call :c:func:`snd_ctl_notify()`. For example:: |
| 2784 | |||
| 2785 | :: | ||
| 2786 | 2673 | ||
| 2787 | snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_VALUE, id_pointer); | 2674 | snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_VALUE, id_pointer); |
| 2788 | 2675 | ||
| @@ -2796,13 +2683,11 @@ for hardware volume interrupts. · 7 unmodified lines | |||
| 2796 | Metadata | 2683 | Metadata |
| 2797 | -------- | 2684 | -------- |
| 2798 | 2685 | ||
| 2799 | To provide information about the dB values of a mixer control, use on of | 2686 | To provide information about the dB values of a mixer control, use one of |
| 2800 | the ``DECLARE_TLV_xxx`` macros from ``<sound/tlv.h>`` to define a | 2687 | the ``DECLARE_TLV_xxx`` macros from ``<sound/tlv.h>`` to define a |
| 2801 | variable containing this information, set the ``tlv.p`` field to point to | 2688 | variable containing this information, set the ``tlv.p`` field to point to |
| 2802 | this variable, and include the ``SNDRV_CTL_ELEM_ACCESS_TLV_READ`` flag | 2689 | this variable, and include the ``SNDRV_CTL_ELEM_ACCESS_TLV_READ`` flag |
| 2803 | in the ``access`` field; like this: | 2690 | in the ``access`` field; like this:: |
| 2804 | |||
| 2805 | :: | ||
| 2806 | 2691 | ||
| 2807 | static DECLARE_TLV_DB_SCALE(db_scale_my_control, -4050, 150, 0); | 2692 | static DECLARE_TLV_DB_SCALE(db_scale_my_control, -4050, 150, 0); |
| 2808 | 2693 | ||
| @@ -2892,9 +2777,7 @@ AC97 Constructor · 83 unmodified lines | |||
| 2892 | ---------------- | 2777 | ---------------- |
| 2893 | 2778 | ||
| 2894 | To create an ac97 instance, first call :c:func:`snd_ac97_bus()` | 2779 | To create an ac97 instance, first call :c:func:`snd_ac97_bus()` |
| 2895 | with an ``ac97_bus_ops_t`` record with callback functions. | 2780 | with an ``ac97_bus_ops_t`` record with callback functions:: |
| 2896 | |||
| 2897 | :: | ||
| 2898 | 2781 | ||
| 2899 | struct snd_ac97_bus *bus; | 2782 | struct snd_ac97_bus *bus; |
| 2900 | static struct snd_ac97_bus_ops ops = { | 2783 | static struct snd_ac97_bus_ops ops = { |
| @@ -2906,10 +2789,8 @@ with an ``ac97_bus_ops_t`` record with callback functions. · 5 unmodified lines | |||
| 2906 | 2789 | ||
| 2907 | The bus record is shared among all belonging ac97 instances. | 2790 | The bus record is shared among all belonging ac97 instances. |
| 2908 | 2791 | ||
| 2909 | And then call :c:func:`snd_ac97_mixer()` with an struct snd_ac97_template | 2792 | And then call :c:func:`snd_ac97_mixer()` with a struct snd_ac97_template |
| 2910 | record together with the bus pointer created above. | 2793 | record together with the bus pointer created above:: |
| 2911 | |||
| 2912 | :: | ||
| 2913 | 2794 | ||
| 2914 | struct snd_ac97_template ac97; | 2795 | struct snd_ac97_template ac97; |
| 2915 | int err; | 2796 | int err; |
| @@ -2934,9 +2815,7 @@ correspond to the functions for read and write accesses to the · 18 unmodified lines | |||
| 2934 | hardware low-level codes. | 2815 | hardware low-level codes. |
| 2935 | 2816 | ||
| 2936 | The ``read`` callback returns the register value specified in the | 2817 | The ``read`` callback returns the register value specified in the |
| 2937 | argument. | 2818 | argument:: |
| 2938 | |||
| 2939 | :: | ||
| 2940 | 2819 | ||
| 2941 | static unsigned short snd_mychip_ac97_read(struct snd_ac97 *ac97, | 2820 | static unsigned short snd_mychip_ac97_read(struct snd_ac97 *ac97, |
| 2942 | unsigned short reg) | 2821 | unsigned short reg) |
| @@ -2949,9 +2828,7 @@ argument. · 6 unmodified lines | |||
| 2949 | Here, the chip can be cast from ``ac97->private_data``. | 2828 | Here, the chip can be cast from ``ac97->private_data``. |
| 2950 | 2829 | ||
| 2951 | Meanwhile, the ``write`` callback is used to set the register | 2830 | Meanwhile, the ``write`` callback is used to set the register |
| 2952 | value | 2831 | value:: |
| 2953 | |||
| 2954 | :: | ||
| 2955 | 2832 | ||
| 2956 | static void snd_mychip_ac97_write(struct snd_ac97 *ac97, | 2833 | static void snd_mychip_ac97_write(struct snd_ac97 *ac97, |
| 2957 | unsigned short reg, unsigned short val) | 2834 | unsigned short reg, unsigned short val) |
| @@ -2984,32 +2861,24 @@ Both :c:func:`snd_ac97_write()` and · 26 unmodified lines | |||
| 2984 | the given register (``AC97_XXX``). The difference between them is that | 2861 | the given register (``AC97_XXX``). The difference between them is that |
| 2985 | :c:func:`snd_ac97_update()` doesn't write a value if the given | 2862 | :c:func:`snd_ac97_update()` doesn't write a value if the given |
| 2986 | value has been already set, while :c:func:`snd_ac97_write()` | 2863 | value has been already set, while :c:func:`snd_ac97_write()` |
| 2987 | always rewrites the value. | 2864 | always rewrites the value:: |
| 2988 | |||
| 2989 | :: | ||
| 2990 | 2865 | ||
| 2991 | snd_ac97_write(ac97, AC97_MASTER, 0x8080); | 2866 | snd_ac97_write(ac97, AC97_MASTER, 0x8080); |
| 2992 | snd_ac97_update(ac97, AC97_MASTER, 0x8080); | 2867 | snd_ac97_update(ac97, AC97_MASTER, 0x8080); |
| 2993 | 2868 | ||
| 2994 | :c:func:`snd_ac97_read()` is used to read the value of the given | 2869 | :c:func:`snd_ac97_read()` is used to read the value of the given |
| 2995 | register. For example, | 2870 | register. For example:: |
| 2996 | |||
| 2997 | :: | ||
| 2998 | 2871 | ||
| 2999 | value = snd_ac97_read(ac97, AC97_MASTER); | 2872 | value = snd_ac97_read(ac97, AC97_MASTER); |
| 3000 | 2873 | ||
| 3001 | :c:func:`snd_ac97_update_bits()` is used to update some bits in | 2874 | :c:func:`snd_ac97_update_bits()` is used to update some bits in |
| 3002 | the given register. | 2875 | the given register:: |
| 3003 | |||
| 3004 | :: | ||
| 3005 | 2876 | ||
| 3006 | snd_ac97_update_bits(ac97, reg, mask, value); | 2877 | snd_ac97_update_bits(ac97, reg, mask, value); |
| 3007 | 2878 | ||
| 3008 | Also, there is a function to change the sample rate (of a given register | 2879 | Also, there is a function to change the sample rate (of a given register |
| 3009 | such as ``AC97_PCM_FRONT_DAC_RATE``) when VRA or DRA is supported by the | 2880 | such as ``AC97_PCM_FRONT_DAC_RATE``) when VRA or DRA is supported by the |
| 3010 | codec: :c:func:`snd_ac97_set_rate()`. | 2881 | codec: :c:func:`snd_ac97_set_rate()`:: |
| 3011 | |||
| 3012 | :: | ||
| 3013 | 2882 | ||
| 3014 | snd_ac97_set_rate(ac97, AC97_PCM_FRONT_DAC_RATE, 44100); | 2883 | snd_ac97_set_rate(ac97, AC97_PCM_FRONT_DAC_RATE, 44100); |
| 3015 | 2884 | ||
| @@ -3064,9 +2933,7 @@ mpu401 stuff. For example, emu10k1 has its own mpu401 routines. · 48 unmodified lines | |||
| 3064 | MIDI Constructor | 2933 | MIDI Constructor |
| 3065 | ---------------- | 2934 | ---------------- |
| 3066 | 2935 | ||
| 3067 | To create a rawmidi object, call :c:func:`snd_mpu401_uart_new()`. | 2936 | To create a rawmidi object, call :c:func:`snd_mpu401_uart_new()`:: |
| 3068 | |||
| 3069 | :: | ||
| 3070 | 2937 | ||
| 3071 | struct snd_rawmidi *rmidi; | 2938 | struct snd_rawmidi *rmidi; |
| 3072 | snd_mpu401_uart_new(card, 0, MPU401_HW_MPU401, port, info_flags, | 2939 | snd_mpu401_uart_new(card, 0, MPU401_HW_MPU401, port, info_flags, |
| @@ -3111,16 +2978,12 @@ corresponds to the data port. If not, you may change the ``cport`` · 38 unmodified lines | |||
| 3111 | field of struct snd_mpu401 manually afterward. | 2978 | field of struct snd_mpu401 manually afterward. |
| 3112 | However, struct snd_mpu401 pointer is | 2979 | However, struct snd_mpu401 pointer is |
| 3113 | not returned explicitly by :c:func:`snd_mpu401_uart_new()`. You | 2980 | not returned explicitly by :c:func:`snd_mpu401_uart_new()`. You |
| 3114 | need to cast ``rmidi->private_data`` to struct snd_mpu401 explicitly, | 2981 | need to cast ``rmidi->private_data`` to struct snd_mpu401 explicitly:: |
| 3115 | |||
| 3116 | :: | ||
| 3117 | 2982 | ||
| 3118 | struct snd_mpu401 *mpu; | 2983 | struct snd_mpu401 *mpu; |
| 3119 | mpu = rmidi->private_data; | 2984 | mpu = rmidi->private_data; |
| 3120 | 2985 | ||
| 3121 | and reset the ``cport`` as you like: | 2986 | and reset the ``cport`` as you like:: |
| 3122 | |||
| 3123 | :: | ||
| 3124 | 2987 | ||
| 3125 | mpu->cport = my_own_control_port; | 2988 | mpu->cport = my_own_control_port; |
| 3126 | 2989 | ||
| @@ -3144,9 +3007,7 @@ occurred. · 17 unmodified lines | |||
| 3144 | 3007 | ||
| 3145 | In this case, you need to pass the private_data of the returned rawmidi | 3008 | In this case, you need to pass the private_data of the returned rawmidi |
| 3146 | object from :c:func:`snd_mpu401_uart_new()` as the second | 3009 | object from :c:func:`snd_mpu401_uart_new()` as the second |
| 3147 | argument of :c:func:`snd_mpu401_uart_interrupt()`. | 3010 | argument of :c:func:`snd_mpu401_uart_interrupt()`:: |
| 3148 | |||
| 3149 | :: | ||
| 3150 | 3011 | ||
| 3151 | snd_mpu401_uart_interrupt(irq, rmidi->private_data, regs); | 3012 | snd_mpu401_uart_interrupt(irq, rmidi->private_data, regs); |
| 3152 | 3013 | ||
| @@ -3170,9 +3031,7 @@ RawMIDI Constructor · 17 unmodified lines | |||
| 3170 | ------------------- | 3031 | ------------------- |
| 3171 | 3032 | ||
| 3172 | To create a rawmidi device, call the :c:func:`snd_rawmidi_new()` | 3033 | To create a rawmidi device, call the :c:func:`snd_rawmidi_new()` |
| 3173 | function: | 3034 | function:: |
| 3174 | |||
| 3175 | :: | ||
| 3176 | 3035 | ||
| 3177 | struct snd_rawmidi *rmidi; | 3036 | struct snd_rawmidi *rmidi; |
| 3178 | err = snd_rawmidi_new(chip->card, "MyMIDI", 0, outs, ins, &rmidi); | 3037 | err = snd_rawmidi_new(chip->card, "MyMIDI", 0, outs, ins, &rmidi); |
| @@ -3202,16 +3061,12 @@ output and input at the same time. · 23 unmodified lines | |||
| 3202 | 3061 | ||
| 3203 | After the rawmidi device is created, you need to set the operators | 3062 | After the rawmidi device is created, you need to set the operators |
| 3204 | (callbacks) for each substream. There are helper functions to set the | 3063 | (callbacks) for each substream. There are helper functions to set the |
| 3205 | operators for all the substreams of a device: | 3064 | operators for all the substreams of a device:: |
| 3206 | |||
| 3207 | :: | ||
| 3208 | 3065 | ||
| 3209 | snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_OUTPUT, &snd_mymidi_output_ops); | 3066 | snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_OUTPUT, &snd_mymidi_output_ops); |
| 3210 | snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_INPUT, &snd_mymidi_input_ops); | 3067 | snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_INPUT, &snd_mymidi_input_ops); |
| 3211 | 3068 | ||
| 3212 | The operators are usually defined like this: | 3069 | The operators are usually defined like this:: |
| 3213 | |||
| 3214 | :: | ||
| 3215 | 3070 | ||
| 3216 | static struct snd_rawmidi_ops snd_mymidi_output_ops = { | 3071 | static struct snd_rawmidi_ops snd_mymidi_output_ops = { |
| 3217 | .open = snd_mymidi_output_open, | 3072 | .open = snd_mymidi_output_open, |
| @@ -3222,9 +3077,7 @@ The operators are usually defined like this: · 4 unmodified lines | |||
| 3222 | These callbacks are explained in the `RawMIDI Callbacks`_ section. | 3077 | These callbacks are explained in the `RawMIDI Callbacks`_ section. |
| 3223 | 3078 | ||
| 3224 | If there are more than one substream, you should give a unique name to | 3079 | If there are more than one substream, you should give a unique name to |
| 3225 | each of them: | 3080 | each of them:: |
| 3226 | |||
| 3227 | :: | ||
| 3228 | 3081 | ||
| 3229 | struct snd_rawmidi_substream *substream; | 3082 | struct snd_rawmidi_substream *substream; |
| 3230 | list_for_each_entry(substream, | 3083 | list_for_each_entry(substream, |
| @@ -3242,9 +3095,7 @@ device can be accessed as ``substream->rmidi->private_data``. · 11 unmodified lines | |||
| 3242 | 3095 | ||
| 3243 | If there is more than one port, your callbacks can determine the port | 3096 | If there is more than one port, your callbacks can determine the port |
| 3244 | index from the struct snd_rawmidi_substream data passed to each | 3097 | index from the struct snd_rawmidi_substream data passed to each |
| 3245 | callback: | 3098 | callback:: |
| 3246 | |||
| 3247 | :: | ||
| 3248 | 3099 | ||
| 3249 | struct snd_rawmidi_substream *substream; | 3100 | struct snd_rawmidi_substream *substream; |
| 3250 | int index = substream->number; | 3101 | int index = substream->number; |
| @@ -3289,9 +3140,7 @@ of bytes that have been read; this will be less than the number of bytes · 38 unmodified lines | |||
| 3289 | requested when there are no more data in the buffer. After the data have | 3140 | requested when there are no more data in the buffer. After the data have |
| 3290 | been transmitted successfully, call | 3141 | been transmitted successfully, call |
| 3291 | :c:func:`snd_rawmidi_transmit_ack()` to remove the data from the | 3142 | :c:func:`snd_rawmidi_transmit_ack()` to remove the data from the |
| 3292 | substream buffer: | 3143 | substream buffer:: |
| 3293 | |||
| 3294 | :: | ||
| 3295 | 3144 | ||
| 3296 | unsigned char data; | 3145 | unsigned char data; |
| 3297 | while (snd_rawmidi_transmit_peek(substream, &data, 1) == 1) { | 3146 | while (snd_rawmidi_transmit_peek(substream, &data, 1) == 1) { |
| @@ -3303,9 +3152,7 @@ substream buffer: · 5 unmodified lines | |||
| 3303 | 3152 | ||
| 3304 | If you know beforehand that the hardware will accept data, you can use | 3153 | If you know beforehand that the hardware will accept data, you can use |
| 3305 | the :c:func:`snd_rawmidi_transmit()` function which reads some | 3154 | the :c:func:`snd_rawmidi_transmit()` function which reads some |
| 3306 | data and removes them from the buffer at once: | 3155 | data and removes them from the buffer at once:: |
| 3307 | |||
| 3308 | :: | ||
| 3309 | 3156 | ||
| 3310 | while (snd_mychip_transmit_possible()) { | 3157 | while (snd_mychip_transmit_possible()) { |
| 3311 | unsigned char data; | 3158 | unsigned char data; |
| @@ -3340,9 +3187,7 @@ The ``trigger`` callback must not sleep; the actual reading of data · 28 unmodified lines | |||
| 3340 | from the device is usually done in an interrupt handler. | 3187 | from the device is usually done in an interrupt handler. |
| 3341 | 3188 | ||
| 3342 | When data reception is enabled, your interrupt handler should call | 3189 | When data reception is enabled, your interrupt handler should call |
| 3343 | :c:func:`snd_rawmidi_receive()` for all received data: | 3190 | :c:func:`snd_rawmidi_receive()` for all received data:: |
| 3344 | |||
| 3345 | :: | ||
| 3346 | 3191 | ||
| 3347 | void snd_mychip_midi_interrupt(...) | 3192 | void snd_mychip_midi_interrupt(...) |
| 3348 | { | 3193 | { |
| @@ -3388,9 +3233,7 @@ whereas in OSS compatible mode, FM registers can be accessed with the · 39 unmodified lines | |||
| 3388 | OSS direct-FM compatible API in ``/dev/dmfmX`` device. | 3233 | OSS direct-FM compatible API in ``/dev/dmfmX`` device. |
| 3389 | 3234 | ||
| 3390 | To create the OPL3 component, you have two functions to call. The first | 3235 | To create the OPL3 component, you have two functions to call. The first |
| 3391 | one is a constructor for the ``opl3_t`` instance. | 3236 | one is a constructor for the ``opl3_t`` instance:: |
| 3392 | |||
| 3393 | :: | ||
| 3394 | 3237 | ||
| 3395 | struct snd_opl3 *opl3; | 3238 | struct snd_opl3 *opl3; |
| 3396 | snd_opl3_create(card, lport, rport, OPL3_HW_OPL3_XXX, | 3239 | snd_opl3_create(card, lport, rport, OPL3_HW_OPL3_XXX, |
| @@ -3408,9 +3251,7 @@ the opl3 module will allocate the specified ports by itself. · 11 unmodified lines | |||
| 3408 | 3251 | ||
| 3409 | When the accessing the hardware requires special method instead of the | 3252 | When the accessing the hardware requires special method instead of the |
| 3410 | standard I/O access, you can create opl3 instance separately with | 3253 | standard I/O access, you can create opl3 instance separately with |
| 3411 | :c:func:`snd_opl3_new()`. | 3254 | :c:func:`snd_opl3_new()`:: |
| 3412 | |||
| 3413 | :: | ||
| 3414 | 3255 | ||
| 3415 | struct snd_opl3 *opl3; | 3256 | struct snd_opl3 *opl3; |
| 3416 | snd_opl3_new(card, OPL3_HW_OPL3_XXX, &opl3); | 3257 | snd_opl3_new(card, OPL3_HW_OPL3_XXX, &opl3); |
| @@ -3427,9 +3268,7 @@ proper state. Note that :c:func:`snd_opl3_create()` always calls · 10 unmodified lines | |||
| 3427 | it internally. | 3268 | it internally. |
| 3428 | 3269 | ||
| 3429 | If the opl3 instance is created successfully, then create a hwdep device | 3270 | If the opl3 instance is created successfully, then create a hwdep device |
| 3430 | for this opl3. | 3271 | for this opl3:: |
| 3431 | |||
| 3432 | :: | ||
| 3433 | 3272 | ||
| 3434 | struct snd_hwdep *opl3hwdep; | 3273 | struct snd_hwdep *opl3hwdep; |
| 3435 | snd_opl3_hwdep_new(opl3, 0, 1, &opl3hwdep); | 3274 | snd_opl3_hwdep_new(opl3, 0, 1, &opl3hwdep); |
| @@ -3451,9 +3290,7 @@ the micro code. In such a case, you can create a hwdep · 15 unmodified lines | |||
| 3451 | ``isa/sb/sb16_csp.c``. | 3290 | ``isa/sb/sb16_csp.c``. |
| 3452 | 3291 | ||
| 3453 | The creation of the ``hwdep`` instance is done via | 3292 | The creation of the ``hwdep`` instance is done via |
| 3454 | :c:func:`snd_hwdep_new()`. | 3293 | :c:func:`snd_hwdep_new()`:: |
| 3455 | |||
| 3456 | :: | ||
| 3457 | 3294 | ||
| 3458 | struct snd_hwdep *hw; | 3295 | struct snd_hwdep *hw; |
| 3459 | snd_hwdep_new(card, "My HWDEP", 0, &hw); | 3296 | snd_hwdep_new(card, "My HWDEP", 0, &hw); |
| @@ -3461,18 +3298,14 @@ The creation of the ``hwdep`` instance is done via · 1 unmodified line | |||
| 3461 | where the third argument is the index number. | 3298 | where the third argument is the index number. |
| 3462 | 3299 | ||
| 3463 | You can then pass any pointer value to the ``private_data``. If you | 3300 | You can then pass any pointer value to the ``private_data``. If you |
| 3464 | assign a private data, you should define the destructor, too. The | 3301 | assign private data, you should define a destructor, too. The |
| 3465 | destructor function is set in the ``private_free`` field. | 3302 | destructor function is set in the ``private_free`` field:: |
| 3466 | |||
| 3467 | :: | ||
| 3468 | 3303 | ||
| 3469 | struct mydata *p = kmalloc(sizeof(*p), GFP_KERNEL); | 3304 | struct mydata *p = kmalloc(sizeof(*p), GFP_KERNEL); |
| 3470 | hw->private_data = p; | 3305 | hw->private_data = p; |
| 3471 | hw->private_free = mydata_free; | 3306 | hw->private_free = mydata_free; |
| 3472 | 3307 | ||
| 3473 | and the implementation of the destructor would be: | 3308 | and the implementation of the destructor would be:: |
| 3474 | |||
| 3475 | :: | ||
| 3476 | 3309 | ||
| 3477 | static void mydata_free(struct snd_hwdep *hw) | 3310 | static void mydata_free(struct snd_hwdep *hw) |
| 3478 | { | 3311 | { |
| @@ -3482,9 +3315,7 @@ and the implementation of the destructor would be: · 3 unmodified lines | |||
| 3482 | 3315 | ||
| 3483 | The arbitrary file operations can be defined for this instance. The file | 3316 | The arbitrary file operations can be defined for this instance. The file |
| 3484 | operators are defined in the ``ops`` table. For example, assume that | 3317 | operators are defined in the ``ops`` table. For example, assume that |
| 3485 | this chip needs an ioctl. | 3318 | this chip needs an ioctl:: |
| 3486 | |||
| 3487 | :: | ||
| 3488 | 3319 | ||
| 3489 | hw->ops.open = mydata_open; | 3320 | hw->ops.open = mydata_open; |
| 3490 | hw->ops.ioctl = mydata_ioctl; | 3321 | hw->ops.ioctl = mydata_ioctl; |
| @@ -3534,31 +3365,30 @@ Buffer Types · 43 unmodified lines | |||
| 3534 | 3365 | ||
| 3535 | ALSA provides several different buffer allocation functions depending on | 3366 | ALSA provides several different buffer allocation functions depending on |
| 3536 | the bus and the architecture. All these have a consistent API. The | 3367 | the bus and the architecture. All these have a consistent API. The |
| 3537 | allocation of physically-contiguous pages is done via | 3368 | allocation of physically-contiguous pages is done via the |
| 3538 | :c:func:`snd_malloc_xxx_pages()` function, where xxx is the bus | 3369 | :c:func:`snd_malloc_xxx_pages()` function, where xxx is the bus |
| 3539 | type. | 3370 | type. |
| 3540 | 3371 | ||
| 3541 | The allocation of pages with fallback is | 3372 | The allocation of pages with fallback is done via |
| 3542 | :c:func:`snd_malloc_xxx_pages_fallback()`. This function tries | 3373 | :c:func:`snd_dma_alloc_pages_fallback()`. This function tries |
| 3543 | to allocate the specified pages but if the pages are not available, it | 3374 | to allocate the specified number of pages, but if not enough pages are |
| 3544 | tries to reduce the page sizes until enough space is found. | 3375 | available, it tries to reduce the request size until enough space |
| 3376 | is found, down to one page. | ||
| 3545 | 3377 | ||
| 3546 | The release the pages, call :c:func:`snd_free_xxx_pages()` | 3378 | To release the pages, call the :c:func:`snd_dma_free_pages()` |
| 3547 | function. | 3379 | function. |
| 3548 | 3380 | ||
| 3549 | Usually, ALSA drivers try to allocate and reserve a large contiguous | 3381 | Usually, ALSA drivers try to allocate and reserve a large contiguous |
| 3550 | physical space at the time the module is loaded for the later use. This | 3382 | physical space at the time the module is loaded for later use. This |
| 3551 | is called “pre-allocation”. As already written, you can call the | 3383 | is called “pre-allocation”. As already written, you can call the |
| 3552 | following function at pcm instance construction time (in the case of PCI | 3384 | following function at PCM instance construction time (in the case of PCI |
| 3553 | bus). | 3385 | bus):: |
| 3554 | |||
| 3555 | :: | ||
| 3556 | 3386 | ||
| 3557 | snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV, | 3387 | snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV, |
| 3558 | &pci->dev, size, max); | 3388 | &pci->dev, size, max); |
| 3559 | 3389 | ||
| 3560 | where ``size`` is the byte size to be pre-allocated and the ``max`` is | 3390 | where ``size`` is the byte size to be pre-allocated and ``max`` is |
| 3561 | the maximum size to be changed via the ``prealloc`` proc file. The | 3391 | the maximum size settable via the ``prealloc`` proc file. The |
| 3562 | allocator will try to get an area as large as possible within the | 3392 | allocator will try to get an area as large as possible within the |
| 3563 | given size. | 3393 | given size. |
| 3564 | 3394 | ||
| @@ -3567,10 +3397,10 @@ dependent on the bus. For normal devices, pass the device pointer · 2 unmodified lines | |||
| 3567 | (typically identical as ``card->dev``) to the third argument with | 3397 | (typically identical as ``card->dev``) to the third argument with |
| 3568 | ``SNDRV_DMA_TYPE_DEV`` type. | 3398 | ``SNDRV_DMA_TYPE_DEV`` type. |
| 3569 | 3399 | ||
| 3570 | For the continuous buffer unrelated to the | 3400 | A continuous buffer unrelated to the |
| 3571 | bus can be pre-allocated with ``SNDRV_DMA_TYPE_CONTINUOUS`` type. | 3401 | bus can be pre-allocated with ``SNDRV_DMA_TYPE_CONTINUOUS`` type. |
| 3572 | You can pass NULL to the device pointer in that case, which is the | 3402 | You can pass NULL to the device pointer in that case, which is the |
| 3573 | default mode implying to allocate with ``GFP_KERNEL`` flag. | 3403 | default mode implying to allocate with the ``GFP_KERNEL`` flag. |
| 3574 | If you need a restricted (lower) address, set up the coherent DMA mask | 3404 | If you need a restricted (lower) address, set up the coherent DMA mask |
| 3575 | bits for the device, and pass the device pointer, like the normal | 3405 | bits for the device, and pass the device pointer, like the normal |
| 3576 | device memory allocations. For this type, it's still allowed to pass | 3406 | device memory allocations. For this type, it's still allowed to pass |
| @@ -3580,37 +3410,33 @@ For the scatter-gather buffers, use ``SNDRV_DMA_TYPE_DEV_SG`` with the · 3 unmodified lines | |||
| 3580 | device pointer (see the `Non-Contiguous Buffers`_ section). | 3410 | device pointer (see the `Non-Contiguous Buffers`_ section). |
| 3581 | 3411 | ||
| 3582 | Once the buffer is pre-allocated, you can use the allocator in the | 3412 | Once the buffer is pre-allocated, you can use the allocator in the |
| 3583 | ``hw_params`` callback: | 3413 | ``hw_params`` callback:: |
| 3584 | |||
| 3585 | :: | ||
| 3586 | 3414 | ||
| 3587 | snd_pcm_lib_malloc_pages(substream, size); | 3415 | snd_pcm_lib_malloc_pages(substream, size); |
| 3588 | 3416 | ||
| 3589 | Note that you have to pre-allocate to use this function. | 3417 | Note that you have to pre-allocate to use this function. |
| 3590 | 3418 | ||
| 3591 | Most of drivers use, though, rather the newly introduced "managed | 3419 | But most drivers use the "managed buffer allocation mode" instead |
| 3592 | buffer allocation mode" instead of the manual allocation or release. | 3420 | of manual allocation and release. |
| 3593 | This is done by calling :c:func:`snd_pcm_set_managed_buffer_all()` | 3421 | This is done by calling :c:func:`snd_pcm_set_managed_buffer_all()` |
| 3594 | instead of :c:func:`snd_pcm_lib_preallocate_pages_for_all()`. | 3422 | instead of :c:func:`snd_pcm_lib_preallocate_pages_for_all()`:: |
| 3595 | |||
| 3596 | :: | ||
| 3597 | 3423 | ||
| 3598 | snd_pcm_set_managed_buffer_all(pcm, SNDRV_DMA_TYPE_DEV, | 3424 | snd_pcm_set_managed_buffer_all(pcm, SNDRV_DMA_TYPE_DEV, |
| 3599 | &pci->dev, size, max); | 3425 | &pci->dev, size, max); |
| 3600 | 3426 | ||
| 3601 | where passed arguments are identical in both functions. | 3427 | where the passed arguments are identical for both functions. |
| 3602 | The difference in the managed mode is that PCM core will call | 3428 | The difference in the managed mode is that PCM core will call |
| 3603 | :c:func:`snd_pcm_lib_malloc_pages()` internally already before calling | 3429 | :c:func:`snd_pcm_lib_malloc_pages()` internally already before calling |
| 3604 | the PCM ``hw_params`` callback, and call :c:func:`snd_pcm_lib_free_pages()` | 3430 | the PCM ``hw_params`` callback, and call :c:func:`snd_pcm_lib_free_pages()` |
| 3605 | after the PCM ``hw_free`` callback automatically. So the driver | 3431 | after the PCM ``hw_free`` callback automatically. So the driver |
| 3606 | doesn't have to call these functions explicitly in its callback any | 3432 | doesn't have to call these functions explicitly in its callback any |
| 3607 | longer. This made many driver code having NULL ``hw_params`` and | 3433 | longer. This allows many drivers to have NULL ``hw_params`` and |
| 3608 | ``hw_free`` entries. | 3434 | ``hw_free`` entries. |
| 3609 | 3435 | ||
| 3610 | External Hardware Buffers | 3436 | External Hardware Buffers |
| 3611 | ------------------------- | 3437 | ------------------------- |
| 3612 | 3438 | ||
| 3613 | Some chips have their own hardware buffers and the DMA transfer from the | 3439 | Some chips have their own hardware buffers and DMA transfer from the |
| 3614 | host memory is not available. In such a case, you need to either 1) | 3440 | host memory is not available. In such a case, you need to either 1) |
| 3615 | copy/set the audio data directly to the external hardware buffer, or 2) | 3441 | copy/set the audio data directly to the external hardware buffer, or 2) |
| 3616 | make an intermediate buffer and copy/set the data from it to the | 3442 | make an intermediate buffer and copy/set the data from it to the |
| @@ -3618,8 +3444,8 @@ external hardware buffer in interrupts (or in tasklets, preferably). · 1 unmodified line | |||
| 3618 | 3444 | ||
| 3619 | The first case works fine if the external hardware buffer is large | 3445 | The first case works fine if the external hardware buffer is large |
| 3620 | enough. This method doesn't need any extra buffers and thus is more | 3446 | enough. This method doesn't need any extra buffers and thus is more |
| 3621 | effective. You need to define the ``copy_user`` and ``copy_kernel`` | 3447 | efficient. You need to define the ``copy_user`` and ``copy_kernel`` |
| 3622 | callbacks for the data transfer, in addition to ``fill_silence`` | 3448 | callbacks for the data transfer, in addition to the ``fill_silence`` |
| 3623 | callback for playback. However, there is a drawback: it cannot be | 3449 | callback for playback. However, there is a drawback: it cannot be |
| 3624 | mmapped. The examples are GUS's GF1 PCM or emu8000's wavetable PCM. | 3450 | mmapped. The examples are GUS's GF1 PCM or emu8000's wavetable PCM. |
| 3625 | 3451 | ||
| @@ -3633,16 +3459,14 @@ buffer instead of the host memory. In this case, mmap is available only · 7 unmodified lines | |||
| 3633 | on certain architectures like the Intel one. In non-mmap mode, the data | 3459 | on certain architectures like the Intel one. In non-mmap mode, the data |
| 3634 | cannot be transferred as in the normal way. Thus you need to define the | 3460 | cannot be transferred as in the normal way. Thus you need to define the |
| 3635 | ``copy_user``, ``copy_kernel`` and ``fill_silence`` callbacks as well, | 3461 | ``copy_user``, ``copy_kernel`` and ``fill_silence`` callbacks as well, |
| 3636 | as in the cases above. The examples are found in ``rme32.c`` and | 3462 | as in the cases above. Examples are found in ``rme32.c`` and |
| 3637 | ``rme96.c``. | 3463 | ``rme96.c``. |
| 3638 | 3464 | ||
| 3639 | The implementation of the ``copy_user``, ``copy_kernel`` and | 3465 | The implementation of the ``copy_user``, ``copy_kernel`` and |
| 3640 | ``silence`` callbacks depends upon whether the hardware supports | 3466 | ``silence`` callbacks depends upon whether the hardware supports |
| 3641 | interleaved or non-interleaved samples. The ``copy_user`` callback is | 3467 | interleaved or non-interleaved samples. The ``copy_user`` callback is |
| 3642 | defined like below, a bit differently depending whether the direction | 3468 | defined like below, a bit differently depending on whether the direction |
| 3643 | is playback or capture: | 3469 | is playback or capture:: |
| 3644 | |||
| 3645 | :: | ||
| 3646 | 3470 | ||
| 3647 | static int playback_copy_user(struct snd_pcm_substream *substream, | 3471 | static int playback_copy_user(struct snd_pcm_substream *substream, |
| 3648 | int channel, unsigned long pos, | 3472 | int channel, unsigned long pos, |
| @@ -3652,8 +3476,7 @@ is playback or capture: · 3 unmodified lines | |||
| 3652 | void __user *dst, unsigned long count); | 3476 | void __user *dst, unsigned long count); |
| 3653 | 3477 | ||
| 3654 | In the case of interleaved samples, the second argument (``channel``) is | 3478 | In the case of interleaved samples, the second argument (``channel``) is |
| 3655 | not used. The third argument (``pos``) points the current position | 3479 | not used. The third argument (``pos``) specifies the position in bytes. |
| 3656 | offset in bytes. | ||
| 3657 | 3480 | ||
| 3658 | The meaning of the fourth argument is different between playback and | 3481 | The meaning of the fourth argument is different between playback and |
| 3659 | capture. For playback, it holds the source data pointer, and for | 3482 | capture. For playback, it holds the source data pointer, and for |
| @@ -3664,49 +3487,42 @@ The last argument is the number of bytes to be copied. · 4 unmodified lines | |||
| 3664 | What you have to do in this callback is again different between playback | 3487 | What you have to do in this callback is again different between playback |
| 3665 | and capture directions. In the playback case, you copy the given amount | 3488 | and capture directions. In the playback case, you copy the given amount |
| 3666 | of data (``count``) at the specified pointer (``src``) to the specified | 3489 | of data (``count``) at the specified pointer (``src``) to the specified |
| 3667 | offset (``pos``) on the hardware buffer. When coded like memcpy-like | 3490 | offset (``pos``) in the hardware buffer. When coded like memcpy-like |
| 3668 | way, the copy would be like: | 3491 | way, the copy would look like:: |
| 3669 | |||
| 3670 | :: | ||
| 3671 | 3492 | ||
| 3672 | my_memcpy_from_user(my_buffer + pos, src, count); | 3493 | my_memcpy_from_user(my_buffer + pos, src, count); |
| 3673 | 3494 | ||
| 3674 | For the capture direction, you copy the given amount of data (``count``) | 3495 | For the capture direction, you copy the given amount of data (``count``) |
| 3675 | at the specified offset (``pos``) on the hardware buffer to the | 3496 | at the specified offset (``pos``) in the hardware buffer to the |
| 3676 | specified pointer (``dst``). | 3497 | specified pointer (``dst``):: |
| 3677 | |||
| 3678 | :: | ||
| 3679 | 3498 | ||
| 3680 | my_memcpy_to_user(dst, my_buffer + pos, count); | 3499 | my_memcpy_to_user(dst, my_buffer + pos, count); |
| 3681 | 3500 | ||
| 3682 | Here the functions are named as ``from_user`` and ``to_user`` because | 3501 | Here the functions are named ``from_user`` and ``to_user`` because |
| 3683 | it's the user-space buffer that is passed to these callbacks. That | 3502 | it's the user-space buffer that is passed to these callbacks. That |
| 3684 | is, the callback is supposed to copy from/to the user-space data | 3503 | is, the callback is supposed to copy data from/to the user-space |
| 3685 | directly to/from the hardware buffer. | 3504 | directly to/from the hardware buffer. |
| 3686 | 3505 | ||
| 3687 | Careful readers might notice that these callbacks receive the | 3506 | Careful readers might notice that these callbacks receive the |
| 3688 | arguments in bytes, not in frames like other callbacks. It's because | 3507 | arguments in bytes, not in frames like other callbacks. It's because |
| 3689 | it would make coding easier like the examples above, and also it makes | 3508 | this makes coding easier like in the examples above, and also it makes |
| 3690 | easier to unify both the interleaved and non-interleaved cases, as | 3509 | it easier to unify both the interleaved and non-interleaved cases, as |
| 3691 | explained in the following. | 3510 | explained below. |
| 3692 | 3511 | ||
| 3693 | In the case of non-interleaved samples, the implementation will be a bit | 3512 | In the case of non-interleaved samples, the implementation will be a bit |
| 3694 | more complicated. The callback is called for each channel, passed by | 3513 | more complicated. The callback is called for each channel, passed in |
| 3695 | the second argument, so totally it's called for N-channels times per | 3514 | the second argument, so in total it's called N times per transfer. |
| 3696 | transfer. | ||
| 3697 | |||
| 3698 | The meaning of other arguments are almost same as the interleaved | ||
| 3699 | case. The callback is supposed to copy the data from/to the given | ||
| 3700 | user-space buffer, but only for the given channel. For the detailed | ||
| 3701 | implementations, please check ``isa/gus/gus_pcm.c`` or | ||
| 3702 | "pci/rme9652/rme9652.c" as examples. | ||
| 3703 | 3515 | ||
| 3704 | The above callbacks are the copy from/to the user-space buffer. There | 3516 | The meaning of the other arguments are almost the same as in the |
| 3705 | are some cases where we want copy from/to the kernel-space buffer | 3517 | interleaved case. The callback is supposed to copy the data from/to |
| 3706 | instead. In such a case, ``copy_kernel`` callback is called. It'd | 3518 | the given user-space buffer, but only for the given channel. For |
| 3707 | look like: | 3519 | details, please check ``isa/gus/gus_pcm.c`` or ``pci/rme9652/rme9652.c`` |
| 3520 | as examples. | ||
| 3708 | 3521 | ||
| 3709 | :: | 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:: | ||
| 3710 | 3526 | ||
| 3711 | static int playback_copy_kernel(struct snd_pcm_substream *substream, | 3527 | static int playback_copy_kernel(struct snd_pcm_substream *substream, |
| 3712 | int channel, unsigned long pos, | 3528 | int channel, unsigned long pos, |
| @@ -3716,19 +3532,15 @@ look like: · 3 unmodified lines | |||
| 3716 | void *dst, unsigned long count); | 3532 | void *dst, unsigned long count); |
| 3717 | 3533 | ||
| 3718 | As found easily, the only difference is that the buffer pointer is | 3534 | As found easily, the only difference is that the buffer pointer is |
| 3719 | without ``__user`` prefix; that is, a kernel-buffer pointer is passed | 3535 | without a ``__user`` prefix; that is, a kernel-buffer pointer is passed |
| 3720 | in the fourth argument. Correspondingly, the implementation would be | 3536 | in the fourth argument. Correspondingly, the implementation would be |
| 3721 | a version without the user-copy, such as: | 3537 | a version without the user-copy, such as:: |
| 3722 | |||
| 3723 | :: | ||
| 3724 | 3538 | ||
| 3725 | my_memcpy(my_buffer + pos, src, count); | 3539 | my_memcpy(my_buffer + pos, src, count); |
| 3726 | 3540 | ||
| 3727 | Usually for the playback, another callback ``fill_silence`` is | 3541 | Usually for the playback, another callback ``fill_silence`` is |
| 3728 | defined. It's implemented in a similar way as the copy callbacks | 3542 | defined. It's implemented in a similar way as the copy callbacks |
| 3729 | above: | 3543 | above:: |
| 3730 | |||
| 3731 | :: | ||
| 3732 | 3544 | ||
| 3733 | static int silence(struct snd_pcm_substream *substream, int channel, | 3545 | static int silence(struct snd_pcm_substream *substream, int channel, |
| 3734 | unsigned long pos, unsigned long count); | 3546 | unsigned long pos, unsigned long count); |
| @@ -3736,54 +3548,47 @@ above: · 1 unmodified line | |||
| 3736 | The meanings of arguments are the same as in the ``copy_user`` and | 3548 | The meanings of arguments are the same as in the ``copy_user`` and |
| 3737 | ``copy_kernel`` callbacks, although there is no buffer pointer | 3549 | ``copy_kernel`` callbacks, although there is no buffer pointer |
| 3738 | argument. In the case of interleaved samples, the channel argument has | 3550 | argument. In the case of interleaved samples, the channel argument has |
| 3739 | no meaning, as well as on ``copy_*`` callbacks. | 3551 | no meaning, as for the ``copy_*`` callbacks. |
| 3740 | 3552 | ||
| 3741 | The role of ``fill_silence`` callback is to set the given amount | 3553 | The role of the ``fill_silence`` callback is to set the given amount |
| 3742 | (``count``) of silence data at the specified offset (``pos``) on the | 3554 | (``count``) of silence data at the specified offset (``pos``) in the |
| 3743 | hardware buffer. Suppose that the data format is signed (that is, the | 3555 | hardware buffer. Suppose that the data format is signed (that is, the |
| 3744 | silent-data is 0), and the implementation using a memset-like function | 3556 | silent-data is 0), and the implementation using a memset-like function |
| 3745 | would be like: | 3557 | would look like:: |
| 3746 | |||
| 3747 | :: | ||
| 3748 | 3558 | ||
| 3749 | my_memset(my_buffer + pos, 0, count); | 3559 | my_memset(my_buffer + pos, 0, count); |
| 3750 | 3560 | ||
| 3751 | In the case of non-interleaved samples, again, the implementation | 3561 | In the case of non-interleaved samples, again, the implementation |
| 3752 | becomes a bit more complicated, as it's called N-times per transfer | 3562 | becomes a bit more complicated, as it's called N times per transfer |
| 3753 | for each channel. See, for example, ``isa/gus/gus_pcm.c``. | 3563 | for each channel. See, for example, ``isa/gus/gus_pcm.c``. |
| 3754 | 3564 | ||
| 3755 | Non-Contiguous Buffers | 3565 | Non-Contiguous Buffers |
| 3756 | ---------------------- | 3566 | ---------------------- |
| 3757 | 3567 | ||
| 3758 | If your hardware supports the page table as in emu10k1 or the buffer | 3568 | If your hardware supports a page table as in emu10k1 or buffer |
| 3759 | descriptors as in via82xx, you can use the scatter-gather (SG) DMA. ALSA | 3569 | descriptors as in via82xx, you can use scatter-gather (SG) DMA. ALSA |
| 3760 | provides an interface for handling SG-buffers. The API is provided in | 3570 | provides an interface for handling SG-buffers. The API is provided in |
| 3761 | ``<sound/pcm.h>``. | 3571 | ``<sound/pcm.h>``. |
| 3762 | 3572 | ||
| 3763 | For creating the SG-buffer handler, call | 3573 | For creating the SG-buffer handler, call |
| 3764 | :c:func:`snd_pcm_set_managed_buffer()` or | 3574 | :c:func:`snd_pcm_set_managed_buffer()` or |
| 3765 | :c:func:`snd_pcm_set_managed_buffer_all()` with | 3575 | :c:func:`snd_pcm_set_managed_buffer_all()` with |
| 3766 | ``SNDRV_DMA_TYPE_DEV_SG`` in the PCM constructor like other PCI | 3576 | ``SNDRV_DMA_TYPE_DEV_SG`` in the PCM constructor like for other PCI |
| 3767 | pre-allocator. You need to pass ``&pci->dev``, where pci is | 3577 | pre-allocations. You need to pass ``&pci->dev``, where pci is |
| 3768 | the struct pci_dev pointer of the chip as | 3578 | the struct pci_dev pointer of the chip as well:: |
| 3769 | well. | ||
| 3770 | |||
| 3771 | :: | ||
| 3772 | 3579 | ||
| 3773 | snd_pcm_set_managed_buffer_all(pcm, SNDRV_DMA_TYPE_DEV_SG, | 3580 | snd_pcm_set_managed_buffer_all(pcm, SNDRV_DMA_TYPE_DEV_SG, |
| 3774 | &pci->dev, size, max); | 3581 | &pci->dev, size, max); |
| 3775 | 3582 | ||
| 3776 | The ``struct snd_sg_buf`` instance is created as | 3583 | The ``struct snd_sg_buf`` instance is created as |
| 3777 | ``substream->dma_private`` in turn. You can cast the pointer like: | 3584 | ``substream->dma_private`` in turn. You can cast the pointer like:: |
| 3778 | |||
| 3779 | :: | ||
| 3780 | 3585 | ||
| 3781 | struct snd_sg_buf *sgbuf = (struct snd_sg_buf *)substream->dma_private; | 3586 | struct snd_sg_buf *sgbuf = (struct snd_sg_buf *)substream->dma_private; |
| 3782 | 3587 | ||
| 3783 | Then in :c:func:`snd_pcm_lib_malloc_pages()` call, the common SG-buffer | 3588 | Then in the :c:func:`snd_pcm_lib_malloc_pages()` call, the common SG-buffer |
| 3784 | handler will allocate the non-contiguous kernel pages of the given size | 3589 | handler will allocate the non-contiguous kernel pages of the given size |
| 3785 | and map them onto the virtually contiguous memory. The virtual pointer | 3590 | and map them as virtually contiguous memory. The virtual pointer |
| 3786 | is addressed in runtime->dma_area. The physical address | 3591 | is addressed via runtime->dma_area. The physical address |
| 3787 | (``runtime->dma_addr``) is set to zero, because the buffer is | 3592 | (``runtime->dma_addr``) is set to zero, because the buffer is |
| 3788 | physically non-contiguous. The physical address table is set up in | 3593 | physically non-contiguous. The physical address table is set up in |
| 3789 | ``sgbuf->table``. You can get the physical address at a certain offset | 3594 | ``sgbuf->table``. You can get the physical address at a certain offset |
| @@ -3796,22 +3601,20 @@ Vmalloc'ed Buffers · 6 unmodified lines | |||
| 3796 | ------------------ | 3601 | ------------------ |
| 3797 | 3602 | ||
| 3798 | It's possible to use a buffer allocated via :c:func:`vmalloc()`, for | 3603 | It's possible to use a buffer allocated via :c:func:`vmalloc()`, for |
| 3799 | example, for an intermediate buffer. In the recent version of kernel, | 3604 | example, for an intermediate buffer. |
| 3800 | you can simply allocate it via standard | 3605 | You can simply allocate it via the standard |
| 3801 | :c:func:`snd_pcm_lib_malloc_pages()` and co after setting up the | 3606 | :c:func:`snd_pcm_lib_malloc_pages()` and co. after setting up the |
| 3802 | buffer preallocation with ``SNDRV_DMA_TYPE_VMALLOC`` type. | 3607 | buffer preallocation with ``SNDRV_DMA_TYPE_VMALLOC`` type:: |
| 3803 | |||
| 3804 | :: | ||
| 3805 | 3608 | ||
| 3806 | snd_pcm_set_managed_buffer_all(pcm, SNDRV_DMA_TYPE_VMALLOC, | 3609 | snd_pcm_set_managed_buffer_all(pcm, SNDRV_DMA_TYPE_VMALLOC, |
| 3807 | NULL, 0, 0); | 3610 | NULL, 0, 0); |
| 3808 | 3611 | ||
| 3809 | The NULL is passed to the device pointer argument, which indicates | 3612 | NULL is passed as the device pointer argument, which indicates |
| 3810 | that the default pages (GFP_KERNEL and GFP_HIGHMEM) will be | 3613 | that default pages (GFP_KERNEL and GFP_HIGHMEM) will be |
| 3811 | allocated. | 3614 | allocated. |
| 3812 | 3615 | ||
| 3813 | Also, note that zero is passed to both the size and the max size | 3616 | Also, note that zero is passed as both the size and the max size |
| 3814 | arguments here. Since each vmalloc call should succeed at any time, | 3617 | argument here. Since each vmalloc call should succeed at any time, |
| 3815 | we don't need to pre-allocate the buffers like other continuous | 3618 | we don't need to pre-allocate the buffers like other continuous |
| 3816 | pages. | 3619 | pages. |
| 3817 | 3620 | ||
| @@ -3823,9 +3626,7 @@ useful for debugging. I recommend you set up proc files if you write a · 5 unmodified lines | |||
| 3823 | driver and want to get a running status or register dumps. The API is | 3626 | driver and want to get a running status or register dumps. The API is |
| 3824 | found in ``<sound/info.h>``. | 3627 | found in ``<sound/info.h>``. |
| 3825 | 3628 | ||
| 3826 | To create a proc file, call :c:func:`snd_card_proc_new()`. | 3629 | To create a proc file, call :c:func:`snd_card_proc_new()`:: |
| 3827 | |||
| 3828 | :: | ||
| 3829 | 3630 | ||
| 3830 | struct snd_info_entry *entry; | 3631 | struct snd_info_entry *entry; |
| 3831 | int err = snd_card_proc_new(card, "my-file", &entry); | 3632 | int err = snd_card_proc_new(card, "my-file", &entry); |
| @@ -3841,28 +3642,22 @@ automatically in the card registration and release functions. · 9 unmodified lines | |||
| 3841 | When the creation is successful, the function stores a new instance in | 3642 | When the creation is successful, the function stores a new instance in |
| 3842 | the pointer given in the third argument. It is initialized as a text | 3643 | the pointer given in the third argument. It is initialized as a text |
| 3843 | proc file for read only. To use this proc file as a read-only text file | 3644 | proc file for read only. To use this proc file as a read-only text file |
| 3844 | as it is, set the read callback with a private data via | 3645 | as-is, set the read callback with private data via |
| 3845 | :c:func:`snd_info_set_text_ops()`. | 3646 | :c:func:`snd_info_set_text_ops()`:: |
| 3846 | |||
| 3847 | :: | ||
| 3848 | 3647 | ||
| 3849 | snd_info_set_text_ops(entry, chip, my_proc_read); | 3648 | snd_info_set_text_ops(entry, chip, my_proc_read); |
| 3850 | 3649 | ||
| 3851 | where the second argument (``chip``) is the private data to be used in | 3650 | where the second argument (``chip``) is the private data to be used in |
| 3852 | the callbacks. The third parameter specifies the read buffer size and | 3651 | the callback. The third parameter specifies the read buffer size and |
| 3853 | the fourth (``my_proc_read``) is the callback function, which is | 3652 | the fourth (``my_proc_read``) is the callback function, which is |
| 3854 | defined like | 3653 | defined like:: |
| 3855 | |||
| 3856 | :: | ||
| 3857 | 3654 | ||
| 3858 | static void my_proc_read(struct snd_info_entry *entry, | 3655 | static void my_proc_read(struct snd_info_entry *entry, |
| 3859 | struct snd_info_buffer *buffer); | 3656 | struct snd_info_buffer *buffer); |
| 3860 | 3657 | ||
| 3861 | In the read callback, use :c:func:`snd_iprintf()` for output | 3658 | In the read callback, use :c:func:`snd_iprintf()` for output |
| 3862 | strings, which works just like normal :c:func:`printf()`. For | 3659 | strings, which works just like normal :c:func:`printf()`. For |
| 3863 | example, | 3660 | example:: |
| 3864 | |||
| 3865 | :: | ||
| 3866 | 3661 | ||
| 3867 | static void my_proc_read(struct snd_info_entry *entry, | 3662 | static void my_proc_read(struct snd_info_entry *entry, |
| 3868 | struct snd_info_buffer *buffer) | 3663 | struct snd_info_buffer *buffer) |
| @@ -3873,28 +3668,22 @@ example, · 4 unmodified lines | |||
| 3873 | snd_iprintf(buffer, "Port = %ld\n", chip->port); | 3668 | snd_iprintf(buffer, "Port = %ld\n", chip->port); |
| 3874 | } | 3669 | } |
| 3875 | 3670 | ||
| 3876 | The file permissions can be changed afterwards. As default, it's set as | 3671 | The file permissions can be changed afterwards. By default, they are |
| 3877 | read only for all users. If you want to add write permission for the | 3672 | read only for all users. If you want to add write permission for the |
| 3878 | user (root as default), do as follows: | 3673 | user (root by default), do as follows:: |
| 3879 | |||
| 3880 | :: | ||
| 3881 | 3674 | ||
| 3882 | entry->mode = S_IFREG | S_IRUGO | S_IWUSR; | 3675 | entry->mode = S_IFREG | S_IRUGO | S_IWUSR; |
| 3883 | 3676 | ||
| 3884 | and set the write buffer size and the callback | 3677 | and set the write buffer size and the callback:: |
| 3885 | |||
| 3886 | :: | ||
| 3887 | 3678 | ||
| 3888 | entry->c.text.write = my_proc_write; | 3679 | entry->c.text.write = my_proc_write; |
| 3889 | 3680 | ||
| 3890 | For the write callback, you can use :c:func:`snd_info_get_line()` | 3681 | In the write callback, you can use :c:func:`snd_info_get_line()` |
| 3891 | to get a text line, and :c:func:`snd_info_get_str()` to retrieve | 3682 | to get a text line, and :c:func:`snd_info_get_str()` to retrieve |
| 3892 | a string from the line. Some examples are found in | 3683 | a string from the line. Some examples are found in |
| 3893 | ``core/oss/mixer_oss.c``, core/oss/and ``pcm_oss.c``. | 3684 | ``core/oss/mixer_oss.c``, core/oss/and ``pcm_oss.c``. |
| 3894 | 3685 | ||
| 3895 | For a raw-data proc-file, set the attributes as follows: | 3686 | For a raw-data proc-file, set the attributes as follows:: |
| 3896 | |||
| 3897 | :: | ||
| 3898 | 3687 | ||
| 3899 | static const struct snd_info_entry_ops my_file_io_ops = { | 3688 | static const struct snd_info_entry_ops my_file_io_ops = { |
| 3900 | .read = my_file_io_read, | 3689 | .read = my_file_io_read, |
| @@ -3906,14 +3695,13 @@ For a raw-data proc-file, set the attributes as follows: · 5 unmodified lines | |||
| 3906 | entry->size = 4096; | 3695 | entry->size = 4096; |
| 3907 | entry->mode = S_IFREG | S_IRUGO; | 3696 | entry->mode = S_IFREG | S_IRUGO; |
| 3908 | 3697 | ||
| 3909 | For the raw data, ``size`` field must be set properly. This specifies | 3698 | For raw data, ``size`` field must be set properly. This specifies |
| 3910 | the maximum size of the proc file access. | 3699 | the maximum size of the proc file access. |
| 3911 | 3700 | ||
| 3912 | The read/write callbacks of raw mode are more direct than the text mode. | 3701 | The read/write callbacks of raw mode are more direct than the text mode. |
| 3913 | You need to use a low-level I/O functions such as | 3702 | You need to use a low-level I/O functions such as |
| 3914 | :c:func:`copy_from_user()` and :c:func:`copy_to_user()` to transfer the data. | 3703 | :c:func:`copy_from_user()` and :c:func:`copy_to_user()` to transfer the |
| 3915 | 3704 | data:: | |
| 3916 | :: | ||
| 3917 | 3705 | ||
| 3918 | static ssize_t my_file_io_read(struct snd_info_entry *entry, | 3706 | static ssize_t my_file_io_read(struct snd_info_entry *entry, |
| 3919 | void *file_private_data, | 3707 | void *file_private_data, |
| @@ -3938,12 +3726,11 @@ Power Management · 18 unmodified lines | |||
| 3938 | If the chip is supposed to work with suspend/resume functions, you need | 3726 | If the chip is supposed to work with suspend/resume functions, you need |
| 3939 | to add power-management code to the driver. The additional code for | 3727 | to add power-management code to the driver. The additional code for |
| 3940 | power-management should be ifdef-ed with ``CONFIG_PM``, or annotated | 3728 | power-management should be ifdef-ed with ``CONFIG_PM``, or annotated |
| 3941 | with __maybe_unused attribute; otherwise the compiler will complain | 3729 | with __maybe_unused attribute; otherwise the compiler will complain. |
| 3942 | you. | ||
| 3943 | 3730 | ||
| 3944 | If the driver *fully* supports suspend/resume that is, the device can be | 3731 | If the driver *fully* supports suspend/resume that is, the device can be |
| 3945 | properly resumed to its state when suspend was called, you can set the | 3732 | properly resumed to its state when suspend was called, you can set the |
| 3946 | ``SNDRV_PCM_INFO_RESUME`` flag in the pcm info field. Usually, this is | 3733 | ``SNDRV_PCM_INFO_RESUME`` flag in the PCM info field. Usually, this is |
| 3947 | possible when the registers of the chip can be safely saved and restored | 3734 | possible when the registers of the chip can be safely saved and restored |
| 3948 | to RAM. If this is set, the trigger callback is called with | 3735 | to RAM. If this is set, the trigger callback is called with |
| 3949 | ``SNDRV_PCM_TRIGGER_RESUME`` after the resume callback completes. | 3736 | ``SNDRV_PCM_TRIGGER_RESUME`` after the resume callback completes. |
| @@ -3953,7 +3740,7 @@ is still possible, it's still worthy to implement suspend/resume · 3 unmodified lines | |||
| 3953 | callbacks. In such a case, applications would reset the status by | 3740 | callbacks. In such a case, applications would reset the status by |
| 3954 | calling :c:func:`snd_pcm_prepare()` and restart the stream | 3741 | calling :c:func:`snd_pcm_prepare()` and restart the stream |
| 3955 | appropriately. Hence, you can define suspend/resume callbacks below but | 3742 | appropriately. Hence, you can define suspend/resume callbacks below but |
| 3956 | don't set ``SNDRV_PCM_INFO_RESUME`` info flag to the PCM. | 3743 | don't set the ``SNDRV_PCM_INFO_RESUME`` info flag to the PCM. |
| 3957 | 3744 | ||
| 3958 | Note that the trigger with SUSPEND can always be called when | 3745 | Note that the trigger with SUSPEND can always be called when |
| 3959 | :c:func:`snd_pcm_suspend_all()` is called, regardless of the | 3746 | :c:func:`snd_pcm_suspend_all()` is called, regardless of the |
| @@ -3963,12 +3750,9 @@ behavior of :c:func:`snd_pcm_resume()`. (Thus, in theory, · 3 unmodified lines | |||
| 3963 | callback when no ``SNDRV_PCM_INFO_RESUME`` flag is set. But, it's better | 3750 | callback when no ``SNDRV_PCM_INFO_RESUME`` flag is set. But, it's better |
| 3964 | to keep it for compatibility reasons.) | 3751 | to keep it for compatibility reasons.) |
| 3965 | 3752 | ||
| 3966 | In the earlier version of ALSA drivers, a common power-management layer | 3753 | The driver needs to define the |
| 3967 | was provided, but it has been removed. The driver needs to define the | ||
| 3968 | suspend/resume hooks according to the bus the device is connected to. In | 3754 | suspend/resume hooks according to the bus the device is connected to. In |
| 3969 | the case of PCI drivers, the callbacks look like below: | 3755 | the case of PCI drivers, the callbacks look like below:: |
| 3970 | |||
| 3971 | :: | ||
| 3972 | 3756 | ||
| 3973 | static int __maybe_unused snd_my_suspend(struct device *dev) | 3757 | static int __maybe_unused snd_my_suspend(struct device *dev) |
| 3974 | { | 3758 | { |
| @@ -3981,7 +3765,7 @@ the case of PCI drivers, the callbacks look like below: · 6 unmodified lines | |||
| 3981 | return 0; | 3765 | return 0; |
| 3982 | } | 3766 | } |
| 3983 | 3767 | ||
| 3984 | The scheme of the real suspend job is as follows. | 3768 | The scheme of the real suspend job is as follows: |
| 3985 | 3769 | ||
| 3986 | 1. Retrieve the card and the chip data. | 3770 | 1. Retrieve the card and the chip data. |
| 3987 | 3771 | ||
| @@ -3995,9 +3779,7 @@ The scheme of the real suspend job is as follows. · 7 unmodified lines | |||
| 3995 | 3779 | ||
| 3996 | 5. Stop the hardware if necessary. | 3780 | 5. Stop the hardware if necessary. |
| 3997 | 3781 | ||
| 3998 | A typical code would be like: | 3782 | Typical code would look like:: |
| 3999 | |||
| 4000 | :: | ||
| 4001 | 3783 | ||
| 4002 | static int __maybe_unused mychip_suspend(struct device *dev) | 3784 | static int __maybe_unused mychip_suspend(struct device *dev) |
| 4003 | { | 3785 | { |
| @@ -4016,7 +3798,7 @@ A typical code would be like: · 12 unmodified lines | |||
| 4016 | } | 3798 | } |
| 4017 | 3799 | ||
| 4018 | 3800 | ||
| 4019 | The scheme of the real resume job is as follows. | 3801 | The scheme of the real resume job is as follows: |
| 4020 | 3802 | ||
| 4021 | 1. Retrieve the card and the chip data. | 3803 | 1. Retrieve the card and the chip data. |
| 4022 | 3804 | ||
| @@ -4024,16 +3806,14 @@ The scheme of the real resume job is as follows. · 1 unmodified line | |||
| 4024 | 3806 | ||
| 4025 | 3. Restore the saved registers if necessary. | 3807 | 3. Restore the saved registers if necessary. |
| 4026 | 3808 | ||
| 4027 | 4. Resume the mixer, e.g. calling :c:func:`snd_ac97_resume()`. | 3809 | 4. Resume the mixer, e.g. by calling :c:func:`snd_ac97_resume()`. |
| 4028 | 3810 | ||
| 4029 | 5. Restart the hardware (if any). | 3811 | 5. Restart the hardware (if any). |
| 4030 | 3812 | ||
| 4031 | 6. Call :c:func:`snd_power_change_state()` with | 3813 | 6. Call :c:func:`snd_power_change_state()` with |
| 4032 | ``SNDRV_CTL_POWER_D0`` to notify the processes. | 3814 | ``SNDRV_CTL_POWER_D0`` to notify the processes. |
| 4033 | 3815 | ||
| 4034 | A typical code would be like: | 3816 | Typical code would look like:: |
| 4035 | |||
| 4036 | :: | ||
| 4037 | 3817 | ||
| 4038 | static int __maybe_unused mychip_resume(struct pci_dev *pci) | 3818 | static int __maybe_unused mychip_resume(struct pci_dev *pci) |
| 4039 | { | 3819 | { |
| @@ -4060,9 +3840,7 @@ been already suspended via its own PM ops calling · 20 unmodified lines | |||
| 4060 | OK, we have all callbacks now. Let's set them up. In the initialization | 3840 | OK, we have all callbacks now. Let's set them up. In the initialization |
| 4061 | of the card, make sure that you can get the chip data from the card | 3841 | of the card, make sure that you can get the chip data from the card |
| 4062 | instance, typically via ``private_data`` field, in case you created the | 3842 | instance, typically via ``private_data`` field, in case you created the |
| 4063 | chip data individually. | 3843 | chip data individually:: |
| 4064 | |||
| 4065 | :: | ||
| 4066 | 3844 | ||
| 4067 | static int snd_mychip_probe(struct pci_dev *pci, | 3845 | static int snd_mychip_probe(struct pci_dev *pci, |
| 4068 | const struct pci_device_id *pci_id) | 3846 | const struct pci_device_id *pci_id) |
| @@ -4082,9 +3860,7 @@ chip data individually. · 13 unmodified lines | |||
| 4082 | } | 3860 | } |
| 4083 | 3861 | ||
| 4084 | When you created the chip data with :c:func:`snd_card_new()`, it's | 3862 | When you created the chip data with :c:func:`snd_card_new()`, it's |
| 4085 | anyway accessible via ``private_data`` field. | 3863 | anyway accessible via ``private_data`` field:: |
| 4086 | |||
| 4087 | :: | ||
| 4088 | 3864 | ||
| 4089 | static int snd_mychip_probe(struct pci_dev *pci, | 3865 | static int snd_mychip_probe(struct pci_dev *pci, |
| 4090 | const struct pci_device_id *pci_id) | 3866 | const struct pci_device_id *pci_id) |
| @@ -4101,14 +3877,12 @@ anyway accessible via ``private_data`` field. · 10 unmodified lines | |||
| 4101 | .... | 3877 | .... |
| 4102 | } | 3878 | } |
| 4103 | 3879 | ||
| 4104 | If you need a space to save the registers, allocate the buffer for it | 3880 | If you need space to save the registers, allocate the buffer for it |
| 4105 | here, too, since it would be fatal if you cannot allocate a memory in | 3881 | here, too, since it would be fatal if you cannot allocate a memory in |
| 4106 | the suspend phase. The allocated buffer should be released in the | 3882 | the suspend phase. The allocated buffer should be released in the |
| 4107 | corresponding destructor. | 3883 | corresponding destructor. |
| 4108 | 3884 | ||
| 4109 | And next, set suspend/resume callbacks to the pci_driver. | 3885 | And next, set suspend/resume callbacks to the pci_driver:: |
| 4110 | |||
| 4111 | :: | ||
| 4112 | 3886 | ||
| 4113 | static SIMPLE_DEV_PM_OPS(snd_my_pm_ops, mychip_suspend, mychip_resume); | 3887 | static SIMPLE_DEV_PM_OPS(snd_my_pm_ops, mychip_suspend, mychip_resume); |
| 4114 | 3888 | ||
| @@ -4128,9 +3902,7 @@ have the ``index``, ``id`` and ``enable`` options. · 13 unmodified lines | |||
| 4128 | 3902 | ||
| 4129 | If the module supports multiple cards (usually up to 8 = ``SNDRV_CARDS`` | 3903 | If the module supports multiple cards (usually up to 8 = ``SNDRV_CARDS`` |
| 4130 | cards), they should be arrays. The default initial values are defined | 3904 | cards), they should be arrays. The default initial values are defined |
| 4131 | already as constants for easier programming: | 3905 | already as constants for easier programming:: |
| 4132 | |||
| 4133 | :: | ||
| 4134 | 3906 | ||
| 4135 | static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; | 3907 | static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; |
| 4136 | static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; | 3908 | static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; |
| @@ -4144,9 +3916,7 @@ The module parameters must be declared with the standard · 7 unmodified lines | |||
| 4144 | ``module_param()``, ``module_param_array()`` and | 3916 | ``module_param()``, ``module_param_array()`` and |
| 4145 | :c:func:`MODULE_PARM_DESC()` macros. | 3917 | :c:func:`MODULE_PARM_DESC()` macros. |
| 4146 | 3918 | ||
| 4147 | The typical coding would be like below: | 3919 | Typical code would look as below:: |
| 4148 | |||
| 4149 | :: | ||
| 4150 | 3920 | ||
| 4151 | #define CARD_NAME "My Chip" | 3921 | #define CARD_NAME "My Chip" |
| 4152 | 3922 | ||
| @@ -4159,9 +3929,7 @@ The typical coding would be like below: · 6 unmodified lines | |||
| 4159 | 3929 | ||
| 4160 | Also, don't forget to define the module description and the license. | 3930 | Also, don't forget to define the module description and the license. |
| 4161 | Especially, the recent modprobe requires to define the | 3931 | Especially, the recent modprobe requires to define the |
| 4162 | module license as GPL, etc., otherwise the system is shown as “tainted”. | 3932 | module license as GPL, etc., otherwise the system is shown as “tainted”:: |
| 4163 | |||
| 4164 | :: | ||
| 4165 | 3933 | ||
| 4166 | MODULE_DESCRIPTION("Sound driver for My Chip"); | 3934 | MODULE_DESCRIPTION("Sound driver for My Chip"); |
| 4167 | MODULE_LICENSE("GPL"); | 3935 | MODULE_LICENSE("GPL"); |
| @@ -4224,32 +3992,36 @@ Driver with A Single Source File · 56 unmodified lines | |||
| 4224 | 3992 | ||
| 4225 | 1. Modify sound/pci/Makefile | 3993 | 1. Modify sound/pci/Makefile |
| 4226 | 3994 | ||
| 4227 | Suppose you have a file xyz.c. Add the following two lines | 3995 | Suppose you have a file xyz.c. Add the following two lines:: |
| 4228 | |||
| 4229 | :: | ||
| 4230 | 3996 | ||
| 4231 | snd-xyz-objs := xyz.o | 3997 | snd-xyz-objs := xyz.o |
| 4232 | obj-$(CONFIG_SND_XYZ) += snd-xyz.o | 3998 | obj-$(CONFIG_SND_XYZ) += snd-xyz.o |
| 4233 | 3999 | ||
| 4234 | 2. Create the Kconfig entry | 4000 | 2. Create the Kconfig entry |
| 4235 | 4001 | ||
| 4236 | Add the new entry of Kconfig for your xyz driver. config SND_XYZ | 4002 | Add the new entry of Kconfig for your xyz driver:: |
| 4237 | tristate "Foobar XYZ" depends on SND select SND_PCM help Say Y here | 4003 | |
| 4238 | to include support for Foobar XYZ soundcard. To compile this driver | 4004 | config SND_XYZ |
| 4239 | as a module, choose M here: the module will be called snd-xyz. the | 4005 | tristate "Foobar XYZ" |
| 4240 | line, select SND_PCM, specifies that the driver xyz supports PCM. In | 4006 | depends on SND |
| 4241 | addition to SND_PCM, the following components are supported for | 4007 | select SND_PCM |
| 4242 | select command: SND_RAWMIDI, SND_TIMER, SND_HWDEP, | 4008 | help |
| 4243 | SND_MPU401_UART, SND_OPL3_LIB, SND_OPL4_LIB, SND_VX_LIB, | 4009 | Say Y here to include support for Foobar XYZ soundcard. |
| 4244 | SND_AC97_CODEC. Add the select command for each supported | 4010 | To compile this driver as a module, choose M here: |
| 4245 | component. | 4011 | the module will be called snd-xyz. |
| 4012 | |||
| 4013 | The line ``select SND_PCM`` specifies that the driver xyz supports PCM. | ||
| 4014 | In addition to SND_PCM, the following components are supported for | ||
| 4015 | select command: SND_RAWMIDI, SND_TIMER, SND_HWDEP, SND_MPU401_UART, | ||
| 4016 | SND_OPL3_LIB, SND_OPL4_LIB, SND_VX_LIB, SND_AC97_CODEC. | ||
| 4017 | Add the select command for each supported component. | ||
| 4246 | 4018 | ||
| 4247 | Note that some selections imply the lowlevel selections. For example, | 4019 | Note that some selections imply the lowlevel selections. For example, |
| 4248 | PCM includes TIMER, MPU401_UART includes RAWMIDI, AC97_CODEC | 4020 | PCM includes TIMER, MPU401_UART includes RAWMIDI, AC97_CODEC |
| 4249 | includes PCM, and OPL3_LIB includes HWDEP. You don't need to give | 4021 | includes PCM, and OPL3_LIB includes HWDEP. You don't need to give |
| 4250 | the lowlevel selections again. | 4022 | the lowlevel selections again. |
| 4251 | 4023 | ||
| 4252 | For the details of Kconfig script, refer to the kbuild documentation. | 4024 | For the details of Kconfig script, refer to the kbuild documentation. |
| 4253 | 4025 | ||
| 4254 | Drivers with Several Source Files | 4026 | Drivers with Several Source Files |
| 4255 | --------------------------------- | 4027 | --------------------------------- |
| @@ -4258,16 +4030,12 @@ Suppose that the driver snd-xyz have several source files. They are · 2 unmodified lines | |||
| 4258 | located in the new subdirectory, sound/pci/xyz. | 4030 | located in the new subdirectory, sound/pci/xyz. |
| 4259 | 4031 | ||
| 4260 | 1. Add a new directory (``sound/pci/xyz``) in ``sound/pci/Makefile`` | 4032 | 1. Add a new directory (``sound/pci/xyz``) in ``sound/pci/Makefile`` |
| 4261 | as below | 4033 | as below:: |
| 4262 | |||
| 4263 | :: | ||
| 4264 | 4034 | ||
| 4265 | obj-$(CONFIG_SND) += sound/pci/xyz/ | 4035 | obj-$(CONFIG_SND) += sound/pci/xyz/ |
| 4266 | 4036 | ||
| 4267 | 4037 | ||
| 4268 | 2. Under the directory ``sound/pci/xyz``, create a Makefile | 4038 | 2. Under the directory ``sound/pci/xyz``, create a Makefile:: |
| 4269 | |||
| 4270 | :: | ||
| 4271 | 4039 | ||
| 4272 | snd-xyz-objs := xyz.o abc.o def.o | 4040 | snd-xyz-objs := xyz.o abc.o def.o |
| 4273 | obj-$(CONFIG_SND_XYZ) += snd-xyz.o | 4041 | obj-$(CONFIG_SND_XYZ) += snd-xyz.o |
| @@ -2075,6 +2075,7 @@ M: Alexander Sverdlin <alexander.sverdlin@gmail.com> · 2074 unmodified lines | |||
| 2075 | L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) | 2075 | L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) |
| 2076 | S: Maintained | 2076 | S: Maintained |
| 2077 | F: Documentation/devicetree/bindings/iio/adc/cirrus,ep9301-adc.yaml | 2077 | F: Documentation/devicetree/bindings/iio/adc/cirrus,ep9301-adc.yaml |
| 2078 | F: Documentation/devicetree/bindings/sound/cirrus,ep9301-* | ||
| 2078 | F: arch/arm/boot/compressed/misc-ep93xx.h | 2079 | F: arch/arm/boot/compressed/misc-ep93xx.h |
| 2079 | F: arch/arm/mach-ep93xx/ | 2080 | F: arch/arm/mach-ep93xx/ |
| 2080 | F: drivers/iio/adc/ep93xx_adc.c | 2081 | F: drivers/iio/adc/ep93xx_adc.c |
| @@ -4922,6 +4923,7 @@ L: patches@opensource.cirrus.com · 2841 unmodified lines | |||
| 4922 | S: Maintained | 4923 | S: Maintained |
| 4923 | F: Documentation/devicetree/bindings/sound/cirrus,cs* | 4924 | F: Documentation/devicetree/bindings/sound/cirrus,cs* |
| 4924 | F: include/dt-bindings/sound/cs* | 4925 | F: include/dt-bindings/sound/cs* |
| 4926 | F: include/sound/cs* | ||
| 4925 | F: sound/pci/hda/cs* | 4927 | F: sound/pci/hda/cs* |
| 4926 | F: sound/pci/hda/hda_cs_dsp_ctl.* | 4928 | F: sound/pci/hda/hda_cs_dsp_ctl.* |
| 4927 | F: sound/soc/codecs/cs* | 4929 | F: sound/soc/codecs/cs* |
| @@ -8282,6 +8284,23 @@ S: Maintained · 3354 unmodified lines | |||
| 8282 | F: drivers/soc/fsl/qe/ | 8284 | F: drivers/soc/fsl/qe/ |
| 8283 | F: include/soc/fsl/qe/ | 8285 | F: include/soc/fsl/qe/ |
| 8284 | 8286 | ||
| 8287 | FREESCALE QUICC ENGINE QMC DRIVER | ||
| 8288 | M: Herve Codina <herve.codina@bootlin.com> | ||
| 8289 | L: linuxppc-dev@lists.ozlabs.org | ||
| 8290 | S: Maintained | ||
| 8291 | F: Documentation/devicetree/bindings/soc/fsl/cpm_qe/fsl,cpm1-scc-qmc.yaml | ||
| 8292 | F: drivers/soc/fsl/qe/qmc.c | ||
| 8293 | F: include/soc/fsl/qe/qmc.h | ||
| 8294 | |||
| 8295 | FREESCALE QUICC ENGINE TSA DRIVER | ||
| 8296 | M: Herve Codina <herve.codina@bootlin.com> | ||
| 8297 | L: linuxppc-dev@lists.ozlabs.org | ||
| 8298 | S: Maintained | ||
| 8299 | F: Documentation/devicetree/bindings/soc/fsl/cpm_qe/fsl,cpm1-tsa.yaml | ||
| 8300 | F: drivers/soc/fsl/qe/tsa.c | ||
| 8301 | F: drivers/soc/fsl/qe/tsa.h | ||
| 8302 | F: include/dt-bindings/soc/cpm1-fsl,tsa.h | ||
| 8303 | |||
| 8285 | FREESCALE QUICC ENGINE UCC ETHERNET DRIVER | 8304 | FREESCALE QUICC ENGINE UCC ETHERNET DRIVER |
| 8286 | M: Li Yang <leoyang.li@nxp.com> | 8305 | M: Li Yang <leoyang.li@nxp.com> |
| 8287 | L: netdev@vger.kernel.org | 8306 | L: netdev@vger.kernel.org |
| @@ -8333,6 +8352,14 @@ F: sound/soc/fsl/fsl* · 45 unmodified lines | |||
| 8333 | F: sound/soc/fsl/imx* | 8352 | F: sound/soc/fsl/imx* |
| 8334 | F: sound/soc/fsl/mpc8610_hpcd.c | 8353 | F: sound/soc/fsl/mpc8610_hpcd.c |
| 8335 | 8354 | ||
| 8355 | FREESCALE SOC SOUND QMC DRIVER | ||
| 8356 | M: Herve Codina <herve.codina@bootlin.com> | ||
| 8357 | L: alsa-devel@alsa-project.org (moderated for non-subscribers) | ||
| 8358 | L: linuxppc-dev@lists.ozlabs.org | ||
| 8359 | S: Maintained | ||
| 8360 | F: Documentation/devicetree/bindings/sound/fsl,qmc-audio.yaml | ||
| 8361 | F: sound/soc/fsl/fsl_qmc_audio.c | ||
| 8362 | |||
| 8336 | FREESCALE USB PERIPHERAL DRIVERS | 8363 | FREESCALE USB PERIPHERAL DRIVERS |
| 8337 | M: Li Yang <leoyang.li@nxp.com> | 8364 | M: Li Yang <leoyang.li@nxp.com> |
| 8338 | L: linux-usb@vger.kernel.org | 8365 | L: linux-usb@vger.kernel.org |
| @@ -13651,9 +13678,13 @@ F: Documentation/devicetree/bindings/serial/atmel,at91-usart.yaml · 5312 unmodified lines | |||
| 13651 | F: drivers/spi/spi-at91-usart.c | 13678 | F: drivers/spi/spi-at91-usart.c |
| 13652 | 13679 | ||
| 13653 | MICROCHIP AUDIO ASOC DRIVERS | 13680 | MICROCHIP AUDIO ASOC DRIVERS |
| 13654 | M: Codrin Ciubotariu <codrin.ciubotariu@microchip.com> | 13681 | M: Claudiu Beznea <claudiu.beznea@microchip.com> |
| 13655 | L: alsa-devel@alsa-project.org (moderated for non-subscribers) | 13682 | L: alsa-devel@alsa-project.org (moderated for non-subscribers) |
| 13656 | S: Supported | 13683 | S: Supported |
| 13684 | F: Documentation/devicetree/bindings/sound/atmel* | ||
| 13685 | F: Documentation/devicetree/bindings/sound/axentia,tse850-pcm5142.txt | ||
| 13686 | F: Documentation/devicetree/bindings/sound/microchip,sama7g5-* | ||
| 13687 | F: Documentation/devicetree/bindings/sound/mikroe,mikroe-proto.txt | ||
| 13657 | F: sound/soc/atmel | 13688 | F: sound/soc/atmel |
| 13658 | 13689 | ||
| 13659 | MICROCHIP CSI2DC DRIVER | 13690 | MICROCHIP CSI2DC DRIVER |
| @@ -13826,9 +13857,10 @@ S: Supported · 166 unmodified lines | |||
| 13826 | F: drivers/spi/spi-atmel.* | 13857 | F: drivers/spi/spi-atmel.* |
| 13827 | 13858 | ||
| 13828 | MICROCHIP SSC DRIVER | 13859 | MICROCHIP SSC DRIVER |
| 13829 | M: Codrin Ciubotariu <codrin.ciubotariu@microchip.com> | 13860 | M: Claudiu Beznea <claudiu.beznea@microchip.com> |
| 13830 | L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) | 13861 | L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) |
| 13831 | S: Supported | 13862 | S: Supported |
| 13863 | F: Documentation/devicetree/bindings/misc/atmel-ssc.txt | ||
| 13832 | F: drivers/misc/atmel-ssc.c | 13864 | F: drivers/misc/atmel-ssc.c |
| 13833 | F: include/linux/atmel-ssc.h | 13865 | F: include/linux/atmel-ssc.h |
| 13834 | 13866 | ||
| @@ -94,7 +94,7 @@ int cpm_command(u32 command, u8 opcode) · 93 unmodified lines | |||
| 94 | int i, ret; | 94 | int i, ret; |
| 95 | unsigned long flags; | 95 | unsigned long flags; |
| 96 | 96 | ||
| 97 | if (command & 0xffffff0f) | 97 | if (command & 0xffffff03) |
| 98 | return -EINVAL; | 98 | return -EINVAL; |
| 99 | 99 | ||
| 100 | spin_lock_irqsave(&cmd_lock, flags); | 100 | spin_lock_irqsave(&cmd_lock, flags); |
| @@ -14,6 +14,7 @@ · 13 unmodified lines | |||
| 14 | #include <linux/delay.h> | 14 | #include <linux/delay.h> |
| 15 | #include <linux/module.h> | 15 | #include <linux/module.h> |
| 16 | #include <linux/moduleparam.h> | 16 | #include <linux/moduleparam.h> |
| 17 | #include <linux/seq_file.h> | ||
| 17 | #include <linux/slab.h> | 18 | #include <linux/slab.h> |
| 18 | #include <linux/vmalloc.h> | 19 | #include <linux/vmalloc.h> |
| 19 | 20 | ||
| @@ -301,6 +302,7 @@ struct cs_dsp_ops { · 281 unmodified lines | |||
| 301 | static const struct cs_dsp_ops cs_dsp_adsp1_ops; | 302 | static const struct cs_dsp_ops cs_dsp_adsp1_ops; |
| 302 | static const struct cs_dsp_ops cs_dsp_adsp2_ops[]; | 303 | static const struct cs_dsp_ops cs_dsp_adsp2_ops[]; |
| 303 | static const struct cs_dsp_ops cs_dsp_halo_ops; | 304 | static const struct cs_dsp_ops cs_dsp_halo_ops; |
| 305 | static const struct cs_dsp_ops cs_dsp_halo_ao_ops; | ||
| 304 | 306 | ||
| 305 | struct cs_dsp_buf { | 307 | struct cs_dsp_buf { |
| 306 | struct list_head list; | 308 | struct list_head list; |
| @@ -456,6 +458,33 @@ static const struct { · 149 unmodified lines | |||
| 456 | }, | 458 | }, |
| 457 | }; | 459 | }; |
| 458 | 460 | ||
| 461 | static int cs_dsp_coeff_base_reg(struct cs_dsp_coeff_ctl *ctl, unsigned int *reg, | ||
| 462 | unsigned int off); | ||
| 463 | |||
| 464 | static int cs_dsp_debugfs_read_controls_show(struct seq_file *s, void *ignored) | ||
| 465 | { | ||
| 466 | struct cs_dsp *dsp = s->private; | ||
| 467 | struct cs_dsp_coeff_ctl *ctl; | ||
| 468 | unsigned int reg; | ||
| 469 | |||
| 470 | list_for_each_entry(ctl, &dsp->ctl_list, list) { | ||
| 471 | cs_dsp_coeff_base_reg(ctl, ®, 0); | ||
| 472 | seq_printf(s, "%22.*s: %#8zx %s:%08x %#8x %s %#8x %#4x %c%c%c%c %s %s\n", | ||
| 473 | ctl->subname_len, ctl->subname, ctl->len, | ||
| 474 | cs_dsp_mem_region_name(ctl->alg_region.type), | ||
| 475 | ctl->offset, reg, ctl->fw_name, ctl->alg_region.alg, ctl->type, | ||
| 476 | ctl->flags & WMFW_CTL_FLAG_VOLATILE ? 'V' : '-', | ||
| 477 | ctl->flags & WMFW_CTL_FLAG_SYS ? 'S' : '-', | ||
| 478 | ctl->flags & WMFW_CTL_FLAG_READABLE ? 'R' : '-', | ||
| 479 | ctl->flags & WMFW_CTL_FLAG_WRITEABLE ? 'W' : '-', | ||
| 480 | ctl->enabled ? "enabled" : "disabled", | ||
| 481 | ctl->set ? "dirty" : "clean"); | ||
| 482 | } | ||
| 483 | |||
| 484 | return 0; | ||
| 485 | } | ||
| 486 | DEFINE_SHOW_ATTRIBUTE(cs_dsp_debugfs_read_controls); | ||
| 487 | |||
| 459 | /** | 488 | /** |
| 460 | * cs_dsp_init_debugfs() - Create and populate DSP representation in debugfs | 489 | * cs_dsp_init_debugfs() - Create and populate DSP representation in debugfs |
| 461 | * @dsp: pointer to DSP structure | 490 | * @dsp: pointer to DSP structure |
| @@ -478,6 +507,9 @@ void cs_dsp_init_debugfs(struct cs_dsp *dsp, struct dentry *debugfs_root) · 16 unmodified lines | |||
| 478 | debugfs_create_file(cs_dsp_debugfs_fops[i].name, 0444, root, | 507 | debugfs_create_file(cs_dsp_debugfs_fops[i].name, 0444, root, |
| 479 | dsp, &cs_dsp_debugfs_fops[i].fops); | 508 | dsp, &cs_dsp_debugfs_fops[i].fops); |
| 480 | 509 | ||
| 510 | debugfs_create_file("controls", 0444, root, dsp, | ||
| 511 | &cs_dsp_debugfs_read_controls_fops); | ||
| 512 | |||
| 481 | dsp->debugfs_root = root; | 513 | dsp->debugfs_root = root; |
| 482 | } | 514 | } |
| 483 | EXPORT_SYMBOL_NS_GPL(cs_dsp_init_debugfs, FW_CS_DSP); | 515 | EXPORT_SYMBOL_NS_GPL(cs_dsp_init_debugfs, FW_CS_DSP); |
| @@ -1300,6 +1332,9 @@ static int cs_dsp_load(struct cs_dsp *dsp, const struct firmware *firmware, · 816 unmodified lines | |||
| 1300 | int regions = 0; | 1332 | int regions = 0; |
| 1301 | int ret, offset, type; | 1333 | int ret, offset, type; |
| 1302 | 1334 | ||
| 1335 | if (!firmware) | ||
| 1336 | return 0; | ||
| 1337 | |||
| 1303 | ret = -EINVAL; | 1338 | ret = -EINVAL; |
| 1304 | 1339 | ||
| 1305 | pos = sizeof(*header) + sizeof(*adsp1_sizes) + sizeof(*footer); | 1340 | pos = sizeof(*header) + sizeof(*adsp1_sizes) + sizeof(*footer); |
| @@ -2821,7 +2856,10 @@ EXPORT_SYMBOL_NS_GPL(cs_dsp_adsp2_init, FW_CS_DSP); · 1515 unmodified lines | |||
| 2821 | */ | 2856 | */ |
| 2822 | int cs_dsp_halo_init(struct cs_dsp *dsp) | 2857 | int cs_dsp_halo_init(struct cs_dsp *dsp) |
| 2823 | { | 2858 | { |
| 2824 | dsp->ops = &cs_dsp_halo_ops; | 2859 | if (dsp->no_core_startstop) |
| 2860 | dsp->ops = &cs_dsp_halo_ao_ops; | ||
| 2861 | else | ||
| 2862 | dsp->ops = &cs_dsp_halo_ops; | ||
| 2825 | 2863 | ||
| 2826 | return cs_dsp_common_init(dsp); | 2864 | return cs_dsp_common_init(dsp); |
| 2827 | } | 2865 | } |
| @@ -3187,6 +3225,14 @@ static const struct cs_dsp_ops cs_dsp_halo_ops = { · 359 unmodified lines | |||
| 3187 | .stop_core = cs_dsp_halo_stop_core, | 3225 | .stop_core = cs_dsp_halo_stop_core, |
| 3188 | }; | 3226 | }; |
| 3189 | 3227 | ||
| 3228 | static const struct cs_dsp_ops cs_dsp_halo_ao_ops = { | ||
| 3229 | .parse_sizes = cs_dsp_adsp2_parse_sizes, | ||
| 3230 | .validate_version = cs_dsp_halo_validate_version, | ||
| 3231 | .setup_algs = cs_dsp_halo_setup_algs, | ||
| 3232 | .region_to_reg = cs_dsp_halo_region_to_reg, | ||
| 3233 | .show_fw_status = cs_dsp_halo_show_fw_status, | ||
| 3234 | }; | ||
| 3235 | |||
| 3190 | /** | 3236 | /** |
| 3191 | * cs_dsp_chunk_write() - Format data to a DSP memory chunk | 3237 | * cs_dsp_chunk_write() - Format data to a DSP memory chunk |
| 3192 | * @ch: Pointer to the chunk structure | 3238 | * @ch: Pointer to the chunk structure |
| @@ -33,6 +33,29 @@ config UCC · 32 unmodified lines | |||
| 33 | bool | 33 | bool |
| 34 | default y if UCC_FAST || UCC_SLOW | 34 | default y if UCC_FAST || UCC_SLOW |
| 35 | 35 | ||
| 36 | config CPM_TSA | ||
| 37 | tristate "CPM TSA support" | ||
| 38 | depends on OF && HAS_IOMEM | ||
| 39 | depends on CPM1 || COMPILE_TEST | ||
| 40 | help | ||
| 41 | Freescale CPM Time Slot Assigner (TSA) | ||
| 42 | controller. | ||
| 43 | |||
| 44 | This option enables support for this | ||
| 45 | controller | ||
| 46 | |||
| 47 | config CPM_QMC | ||
| 48 | tristate "CPM QMC support" | ||
| 49 | depends on OF && HAS_IOMEM | ||
| 50 | depends on CPM1 || (FSL_SOC && COMPILE_TEST) | ||
| 51 | depends on CPM_TSA | ||
| 52 | help | ||
| 53 | Freescale CPM QUICC Multichannel Controller | ||
| 54 | (QMC) | ||
| 55 | |||
| 56 | This option enables support for this | ||
| 57 | controller | ||
| 58 | |||
| 36 | config QE_TDM | 59 | config QE_TDM |
| 37 | bool | 60 | bool |
| 38 | default y if FSL_UCC_HDLC | 61 | default y if FSL_UCC_HDLC |
| @@ -4,6 +4,8 @@ · 3 unmodified lines | |||
| 4 | # | 4 | # |
| 5 | obj-$(CONFIG_QUICC_ENGINE)+= qe.o qe_common.o qe_ic.o qe_io.o | 5 | obj-$(CONFIG_QUICC_ENGINE)+= qe.o qe_common.o qe_ic.o qe_io.o |
| 6 | obj-$(CONFIG_CPM) += qe_common.o | 6 | obj-$(CONFIG_CPM) += qe_common.o |
| 7 | obj-$(CONFIG_CPM_TSA) += tsa.o | ||
| 8 | obj-$(CONFIG_CPM_QMC) += qmc.o | ||
| 7 | obj-$(CONFIG_UCC) += ucc.o | 9 | obj-$(CONFIG_UCC) += ucc.o |
| 8 | obj-$(CONFIG_UCC_SLOW) += ucc_slow.o | 10 | obj-$(CONFIG_UCC_SLOW) += ucc_slow.o |
| 9 | obj-$(CONFIG_UCC_FAST) += ucc_fast.o | 11 | obj-$(CONFIG_UCC_FAST) += ucc_fast.o |
| @@ -0,0 +1,1537 @@ | |||
| 1 | // SPDX-License-Identifier: GPL-2.0 | ||
| 2 | /* | ||
| 3 | * QMC driver | ||
| 4 | * | ||
| 5 | * Copyright 2022 CS GROUP France | ||
| 6 | * | ||
| 7 | * Author: Herve Codina <herve.codina@bootlin.com> | ||
| 8 | */ | ||
| 9 | |||
| 10 | #include <soc/fsl/qe/qmc.h> | ||
| 11 | #include <linux/dma-mapping.h> | ||
| 12 | #include <linux/hdlc.h> | ||
| 13 | #include <linux/interrupt.h> | ||
| 14 | #include <linux/io.h> | ||
| 15 | #include <linux/module.h> | ||
| 16 | #include <linux/of.h> | ||
| 17 | #include <linux/of_platform.h> | ||
| 18 | #include <linux/platform_device.h> | ||
| 19 | #include <linux/slab.h> | ||
| 20 | #include <soc/fsl/cpm.h> | ||
| 21 | #include <sysdev/fsl_soc.h> | ||
| 22 | #include "tsa.h" | ||
| 23 | |||
| 24 | /* SCC general mode register high (32 bits) */ | ||
| 25 | #define SCC_GSMRL 0x00 | ||
| 26 | #define SCC_GSMRL_ENR (1 << 5) | ||
| 27 | #define SCC_GSMRL_ENT (1 << 4) | ||
| 28 | #define SCC_GSMRL_MODE_QMC (0x0A << 0) | ||
| 29 | |||
| 30 | /* SCC general mode register low (32 bits) */ | ||
| 31 | #define SCC_GSMRH 0x04 | ||
| 32 | #define SCC_GSMRH_CTSS (1 << 7) | ||
| 33 | #define SCC_GSMRH_CDS (1 << 8) | ||
| 34 | #define SCC_GSMRH_CTSP (1 << 9) | ||
| 35 | #define SCC_GSMRH_CDP (1 << 10) | ||
| 36 | |||
| 37 | /* SCC event register (16 bits) */ | ||
| 38 | #define SCC_SCCE 0x10 | ||
| 39 | #define SCC_SCCE_IQOV (1 << 3) | ||
| 40 | #define SCC_SCCE_GINT (1 << 2) | ||
| 41 | #define SCC_SCCE_GUN (1 << 1) | ||
| 42 | #define SCC_SCCE_GOV (1 << 0) | ||
| 43 | |||
| 44 | /* SCC mask register (16 bits) */ | ||
| 45 | #define SCC_SCCM 0x14 | ||
| 46 | /* Multichannel base pointer (32 bits) */ | ||
| 47 | #define QMC_GBL_MCBASE 0x00 | ||
| 48 | /* Multichannel controller state (16 bits) */ | ||
| 49 | #define QMC_GBL_QMCSTATE 0x04 | ||
| 50 | /* Maximum receive buffer length (16 bits) */ | ||
| 51 | #define QMC_GBL_MRBLR 0x06 | ||
| 52 | /* Tx time-slot assignment table pointer (16 bits) */ | ||
| 53 | #define QMC_GBL_TX_S_PTR 0x08 | ||
| 54 | /* Rx pointer (16 bits) */ | ||
| 55 | #define QMC_GBL_RXPTR 0x0A | ||
| 56 | /* Global receive frame threshold (16 bits) */ | ||
| 57 | #define QMC_GBL_GRFTHR 0x0C | ||
| 58 | /* Global receive frame count (16 bits) */ | ||
| 59 | #define QMC_GBL_GRFCNT 0x0E | ||
| 60 | /* Multichannel interrupt base address (32 bits) */ | ||
| 61 | #define QMC_GBL_INTBASE 0x10 | ||
| 62 | /* Multichannel interrupt pointer (32 bits) */ | ||
| 63 | #define QMC_GBL_INTPTR 0x14 | ||
| 64 | /* Rx time-slot assignment table pointer (16 bits) */ | ||
| 65 | #define QMC_GBL_RX_S_PTR 0x18 | ||
| 66 | /* Tx pointer (16 bits) */ | ||
| 67 | #define QMC_GBL_TXPTR 0x1A | ||
| 68 | /* CRC constant (32 bits) */ | ||
| 69 | #define QMC_GBL_C_MASK32 0x1C | ||
| 70 | /* Time slot assignment table Rx (32 x 16 bits) */ | ||
| 71 | #define QMC_GBL_TSATRX 0x20 | ||
| 72 | /* Time slot assignment table Tx (32 x 16 bits) */ | ||
| 73 | #define QMC_GBL_TSATTX 0x60 | ||
| 74 | /* CRC constant (16 bits) */ | ||
| 75 | #define QMC_GBL_C_MASK16 0xA0 | ||
| 76 | |||
| 77 | /* TSA entry (16bit entry in TSATRX and TSATTX) */ | ||
| 78 | #define QMC_TSA_VALID (1 << 15) | ||
| 79 | #define QMC_TSA_WRAP (1 << 14) | ||
| 80 | #define QMC_TSA_MASK (0x303F) | ||
| 81 | #define QMC_TSA_CHANNEL(x) ((x) << 6) | ||
| 82 | |||
| 83 | /* Tx buffer descriptor base address (16 bits, offset from MCBASE) */ | ||
| 84 | #define QMC_SPE_TBASE 0x00 | ||
| 85 | |||
| 86 | /* Channel mode register (16 bits) */ | ||
| 87 | #define QMC_SPE_CHAMR 0x02 | ||
| 88 | #define QMC_SPE_CHAMR_MODE_HDLC (1 << 15) | ||
| 89 | #define QMC_SPE_CHAMR_MODE_TRANSP ((0 << 15) | (1 << 13)) | ||
| 90 | #define QMC_SPE_CHAMR_ENT (1 << 12) | ||
| 91 | #define QMC_SPE_CHAMR_POL (1 << 8) | ||
| 92 | #define QMC_SPE_CHAMR_HDLC_IDLM (1 << 13) | ||
| 93 | #define QMC_SPE_CHAMR_HDLC_CRC (1 << 7) | ||
| 94 | #define QMC_SPE_CHAMR_HDLC_NOF (0x0f << 0) | ||
| 95 | #define QMC_SPE_CHAMR_TRANSP_RD (1 << 14) | ||
| 96 | #define QMC_SPE_CHAMR_TRANSP_SYNC (1 << 10) | ||
| 97 | |||
| 98 | /* Tx internal state (32 bits) */ | ||
| 99 | #define QMC_SPE_TSTATE 0x04 | ||
| 100 | /* Tx buffer descriptor pointer (16 bits) */ | ||
| 101 | #define QMC_SPE_TBPTR 0x0C | ||
| 102 | /* Zero-insertion state (32 bits) */ | ||
| 103 | #define QMC_SPE_ZISTATE 0x14 | ||
| 104 | /* Channel’s interrupt mask flags (16 bits) */ | ||
| 105 | #define QMC_SPE_INTMSK 0x1C | ||
| 106 | /* Rx buffer descriptor base address (16 bits, offset from MCBASE) */ | ||
| 107 | #define QMC_SPE_RBASE 0x20 | ||
| 108 | /* HDLC: Maximum frame length register (16 bits) */ | ||
| 109 | #define QMC_SPE_MFLR 0x22 | ||
| 110 | /* TRANSPARENT: Transparent maximum receive length (16 bits) */ | ||
| 111 | #define QMC_SPE_TMRBLR 0x22 | ||
| 112 | /* Rx internal state (32 bits) */ | ||
| 113 | #define QMC_SPE_RSTATE 0x24 | ||
| 114 | /* Rx buffer descriptor pointer (16 bits) */ | ||
| 115 | #define QMC_SPE_RBPTR 0x2C | ||
| 116 | /* Packs 4 bytes to 1 long word before writing to buffer (32 bits) */ | ||
| 117 | #define QMC_SPE_RPACK 0x30 | ||
| 118 | /* Zero deletion state (32 bits) */ | ||
| 119 | #define QMC_SPE_ZDSTATE 0x34 | ||
| 120 | |||
| 121 | /* Transparent synchronization (16 bits) */ | ||
| 122 | #define QMC_SPE_TRNSYNC 0x3C | ||
| 123 | #define QMC_SPE_TRNSYNC_RX(x) ((x) << 8) | ||
| 124 | #define QMC_SPE_TRNSYNC_TX(x) ((x) << 0) | ||
| 125 | |||
| 126 | /* Interrupt related registers bits */ | ||
| 127 | #define QMC_INT_V (1 << 15) | ||
| 128 | #define QMC_INT_W (1 << 14) | ||
| 129 | #define QMC_INT_NID (1 << 13) | ||
| 130 | #define QMC_INT_IDL (1 << 12) | ||
| 131 | #define QMC_INT_GET_CHANNEL(x) (((x) & 0x0FC0) >> 6) | ||
| 132 | #define QMC_INT_MRF (1 << 5) | ||
| 133 | #define QMC_INT_UN (1 << 4) | ||
| 134 | #define QMC_INT_RXF (1 << 3) | ||
| 135 | #define QMC_INT_BSY (1 << 2) | ||
| 136 | #define QMC_INT_TXB (1 << 1) | ||
| 137 | #define QMC_INT_RXB (1 << 0) | ||
| 138 | |||
| 139 | /* BD related registers bits */ | ||
| 140 | #define QMC_BD_RX_E (1 << 15) | ||
| 141 | #define QMC_BD_RX_W (1 << 13) | ||
| 142 | #define QMC_BD_RX_I (1 << 12) | ||
| 143 | #define QMC_BD_RX_L (1 << 11) | ||
| 144 | #define QMC_BD_RX_F (1 << 10) | ||
| 145 | #define QMC_BD_RX_CM (1 << 9) | ||
| 146 | #define QMC_BD_RX_UB (1 << 7) | ||
| 147 | #define QMC_BD_RX_LG (1 << 5) | ||
| 148 | #define QMC_BD_RX_NO (1 << 4) | ||
| 149 | #define QMC_BD_RX_AB (1 << 3) | ||
| 150 | #define QMC_BD_RX_CR (1 << 2) | ||
| 151 | |||
| 152 | #define QMC_BD_TX_R (1 << 15) | ||
| 153 | #define QMC_BD_TX_W (1 << 13) | ||
| 154 | #define QMC_BD_TX_I (1 << 12) | ||
| 155 | #define QMC_BD_TX_L (1 << 11) | ||
| 156 | #define QMC_BD_TX_TC (1 << 10) | ||
| 157 | #define QMC_BD_TX_CM (1 << 9) | ||
| 158 | #define QMC_BD_TX_UB (1 << 7) | ||
| 159 | #define QMC_BD_TX_PAD (0x0f << 0) | ||
| 160 | |||
| 161 | /* Numbers of BDs and interrupt items */ | ||
| 162 | #define QMC_NB_TXBDS 8 | ||
| 163 | #define QMC_NB_RXBDS 8 | ||
| 164 | #define QMC_NB_INTS 128 | ||
| 165 | |||
| 166 | struct qmc_xfer_desc { | ||
| 167 | union { | ||
| 168 | void (*tx_complete)(void *context); | ||
| 169 | void (*rx_complete)(void *context, size_t length); | ||
| 170 | }; | ||
| 171 | void *context; | ||
| 172 | }; | ||
| 173 | |||
| 174 | struct qmc_chan { | ||
| 175 | struct list_head list; | ||
| 176 | unsigned int id; | ||
| 177 | struct qmc *qmc; | ||
| 178 | void *__iomem s_param; | ||
| 179 | enum qmc_mode mode; | ||
| 180 | u64 tx_ts_mask; | ||
| 181 | u64 rx_ts_mask; | ||
| 182 | bool is_reverse_data; | ||
| 183 | |||
| 184 | spinlock_t tx_lock; | ||
| 185 | cbd_t __iomem *txbds; | ||
| 186 | cbd_t __iomem *txbd_free; | ||
| 187 | cbd_t __iomem *txbd_done; | ||
| 188 | struct qmc_xfer_desc tx_desc[QMC_NB_TXBDS]; | ||
| 189 | u64 nb_tx_underrun; | ||
| 190 | bool is_tx_stopped; | ||
| 191 | |||
| 192 | spinlock_t rx_lock; | ||
| 193 | cbd_t __iomem *rxbds; | ||
| 194 | cbd_t __iomem *rxbd_free; | ||
| 195 | cbd_t __iomem *rxbd_done; | ||
| 196 | struct qmc_xfer_desc rx_desc[QMC_NB_RXBDS]; | ||
| 197 | u64 nb_rx_busy; | ||
| 198 | int rx_pending; | ||
| 199 | bool is_rx_halted; | ||
| 200 | bool is_rx_stopped; | ||
| 201 | }; | ||
| 202 | |||
| 203 | struct qmc { | ||
| 204 | struct device *dev; | ||
| 205 | struct tsa_serial *tsa_serial; | ||
| 206 | void *__iomem scc_regs; | ||
| 207 | void *__iomem scc_pram; | ||
| 208 | void *__iomem dpram; | ||
| 209 | u16 scc_pram_offset; | ||
| 210 | cbd_t __iomem *bd_table; | ||
| 211 | dma_addr_t bd_dma_addr; | ||
| 212 | size_t bd_size; | ||
| 213 | u16 __iomem *int_table; | ||
| 214 | u16 __iomem *int_curr; | ||
| 215 | dma_addr_t int_dma_addr; | ||
| 216 | size_t int_size; | ||
| 217 | struct list_head chan_head; | ||
| 218 | struct qmc_chan *chans[64]; | ||
| 219 | }; | ||
| 220 | |||
| 221 | static inline void qmc_write16(void *__iomem addr, u16 val) | ||
| 222 | { | ||
| 223 | iowrite16be(val, addr); | ||
| 224 | } | ||
| 225 | |||
| 226 | static inline u16 qmc_read16(void *__iomem addr) | ||
| 227 | { | ||
| 228 | return ioread16be(addr); | ||
| 229 | } | ||
| 230 | |||
| 231 | static inline void qmc_setbits16(void *__iomem addr, u16 set) | ||
| 232 | { | ||
| 233 | qmc_write16(addr, qmc_read16(addr) | set); | ||
| 234 | } | ||
| 235 | |||
| 236 | static inline void qmc_clrbits16(void *__iomem addr, u16 clr) | ||
| 237 | { | ||
| 238 | qmc_write16(addr, qmc_read16(addr) & ~clr); | ||
| 239 | } | ||
| 240 | |||
| 241 | static inline void qmc_write32(void *__iomem addr, u32 val) | ||
| 242 | { | ||
| 243 | iowrite32be(val, addr); | ||
| 244 | } | ||
| 245 | |||
| 246 | static inline u32 qmc_read32(void *__iomem addr) | ||
| 247 | { | ||
| 248 | return ioread32be(addr); | ||
| 249 | } | ||
| 250 | |||
| 251 | static inline void qmc_setbits32(void *__iomem addr, u32 set) | ||
| 252 | { | ||
| 253 | qmc_write32(addr, qmc_read32(addr) | set); | ||
| 254 | } | ||
| 255 | |||
| 256 | |||
| 257 | int qmc_chan_get_info(struct qmc_chan *chan, struct qmc_chan_info *info) | ||
| 258 | { | ||
| 259 | struct tsa_serial_info tsa_info; | ||
| 260 | int ret; | ||
| 261 | |||
| 262 | /* Retrieve info from the TSA related serial */ | ||
| 263 | ret = tsa_serial_get_info(chan->qmc->tsa_serial, &tsa_info); | ||
| 264 | if (ret) | ||
| 265 | return ret; | ||
| 266 | |||
| 267 | info->mode = chan->mode; | ||
| 268 | info->rx_fs_rate = tsa_info.rx_fs_rate; | ||
| 269 | info->rx_bit_rate = tsa_info.rx_bit_rate; | ||
| 270 | info->nb_tx_ts = hweight64(chan->tx_ts_mask); | ||
| 271 | info->tx_fs_rate = tsa_info.tx_fs_rate; | ||
| 272 | info->tx_bit_rate = tsa_info.tx_bit_rate; | ||
| 273 | info->nb_rx_ts = hweight64(chan->rx_ts_mask); | ||
| 274 | |||
| 275 | return 0; | ||
| 276 | } | ||
| 277 | EXPORT_SYMBOL(qmc_chan_get_info); | ||
| 278 | |||
| 279 | int qmc_chan_set_param(struct qmc_chan *chan, const struct qmc_chan_param *param) | ||
| 280 | { | ||
| 281 | if (param->mode != chan->mode) | ||
| 282 | return -EINVAL; | ||
| 283 | |||
| 284 | switch (param->mode) { | ||
| 285 | case QMC_HDLC: | ||
| 286 | if ((param->hdlc.max_rx_buf_size % 4) || | ||
| 287 | (param->hdlc.max_rx_buf_size < 8)) | ||
| 288 | return -EINVAL; | ||
| 289 | |||
| 290 | qmc_write16(chan->qmc->scc_pram + QMC_GBL_MRBLR, | ||
| 291 | param->hdlc.max_rx_buf_size - 8); | ||
| 292 | qmc_write16(chan->s_param + QMC_SPE_MFLR, | ||
| 293 | param->hdlc.max_rx_frame_size); | ||
| 294 | if (param->hdlc.is_crc32) { | ||
| 295 | qmc_setbits16(chan->s_param + QMC_SPE_CHAMR, | ||
| 296 | QMC_SPE_CHAMR_HDLC_CRC); | ||
| 297 | } else { | ||
| 298 | qmc_clrbits16(chan->s_param + QMC_SPE_CHAMR, | ||
| 299 | QMC_SPE_CHAMR_HDLC_CRC); | ||
| 300 | } | ||
| 301 | break; | ||
| 302 | |||
| 303 | case QMC_TRANSPARENT: | ||
| 304 | qmc_write16(chan->s_param + QMC_SPE_TMRBLR, | ||
| 305 | param->transp.max_rx_buf_size); | ||
| 306 | break; | ||
| 307 | |||
| 308 | default: | ||
| 309 | return -EINVAL; | ||
| 310 | } | ||
| 311 | |||
| 312 | return 0; | ||
| 313 | } | ||
| 314 | EXPORT_SYMBOL(qmc_chan_set_param); | ||
| 315 | |||
| 316 | int qmc_chan_write_submit(struct qmc_chan *chan, dma_addr_t addr, size_t length, | ||
| 317 | void (*complete)(void *context), void *context) | ||
| 318 | { | ||
| 319 | struct qmc_xfer_desc *xfer_desc; | ||
| 320 | unsigned long flags; | ||
| 321 | cbd_t *__iomem bd; | ||
| 322 | u16 ctrl; | ||
| 323 | int ret; | ||
| 324 | |||
| 325 | /* | ||
| 326 | * R bit UB bit | ||
| 327 | * 0 0 : The BD is free | ||
| 328 | * 1 1 : The BD is in used, waiting for transfer | ||
| 329 | * 0 1 : The BD is in used, waiting for completion | ||
| 330 | * 1 0 : Should not append | ||
| 331 | */ | ||
| 332 | |||
| 333 | spin_lock_irqsave(&chan->tx_lock, flags); | ||
| 334 | bd = chan->txbd_free; | ||
| 335 | |||
| 336 | ctrl = qmc_read16(&bd->cbd_sc); | ||
| 337 | if (ctrl & (QMC_BD_TX_R | QMC_BD_TX_UB)) { | ||
| 338 | /* We are full ... */ | ||
| 339 | ret = -EBUSY; | ||
| 340 | goto end; | ||
| 341 | } | ||
| 342 | |||
| 343 | qmc_write16(&bd->cbd_datlen, length); | ||
| 344 | qmc_write32(&bd->cbd_bufaddr, addr); | ||
| 345 | |||
| 346 | xfer_desc = &chan->tx_desc[bd - chan->txbds]; | ||
| 347 | xfer_desc->tx_complete = complete; | ||
| 348 | xfer_desc->context = context; | ||
| 349 | |||
| 350 | /* Activate the descriptor */ | ||
| 351 | ctrl |= (QMC_BD_TX_R | QMC_BD_TX_UB); | ||
| 352 | wmb(); /* Be sure to flush the descriptor before control update */ | ||
| 353 | qmc_write16(&bd->cbd_sc, ctrl); | ||
| 354 | |||
| 355 | if (!chan->is_tx_stopped) | ||
| 356 | qmc_setbits16(chan->s_param + QMC_SPE_CHAMR, QMC_SPE_CHAMR_POL); | ||
| 357 | |||
| 358 | if (ctrl & QMC_BD_TX_W) | ||
| 359 | chan->txbd_free = chan->txbds; | ||
| 360 | else | ||
| 361 | chan->txbd_free++; | ||
| 362 | |||
| 363 | ret = 0; | ||
| 364 | |||
| 365 | end: | ||
| 366 | spin_unlock_irqrestore(&chan->tx_lock, flags); | ||
| 367 | return ret; | ||
| 368 | } | ||
| 369 | EXPORT_SYMBOL(qmc_chan_write_submit); | ||
| 370 | |||
| 371 | static void qmc_chan_write_done(struct qmc_chan *chan) | ||
| 372 | { | ||
| 373 | struct qmc_xfer_desc *xfer_desc; | ||
| 374 | void (*complete)(void *context); | ||
| 375 | unsigned long flags; | ||
| 376 | void *context; | ||
| 377 | cbd_t *__iomem bd; | ||
| 378 | u16 ctrl; | ||
| 379 | |||
| 380 | /* | ||
| 381 | * R bit UB bit | ||
| 382 | * 0 0 : The BD is free | ||
| 383 | * 1 1 : The BD is in used, waiting for transfer | ||
| 384 | * 0 1 : The BD is in used, waiting for completion | ||
| 385 | * 1 0 : Should not append | ||
| 386 | */ | ||
| 387 | |||
| 388 | spin_lock_irqsave(&chan->tx_lock, flags); | ||
| 389 | bd = chan->txbd_done; | ||
| 390 | |||
| 391 | ctrl = qmc_read16(&bd->cbd_sc); | ||
| 392 | while (!(ctrl & QMC_BD_TX_R)) { | ||
| 393 | if (!(ctrl & QMC_BD_TX_UB)) | ||
| 394 | goto end; | ||
| 395 | |||
| 396 | xfer_desc = &chan->tx_desc[bd - chan->txbds]; | ||
| 397 | complete = xfer_desc->tx_complete; | ||
| 398 | context = xfer_desc->context; | ||
| 399 | xfer_desc->tx_complete = NULL; | ||
| 400 | xfer_desc->context = NULL; | ||
| 401 | |||
| 402 | qmc_write16(&bd->cbd_sc, ctrl & ~QMC_BD_TX_UB); | ||
| 403 | |||
| 404 | if (ctrl & QMC_BD_TX_W) | ||
| 405 | chan->txbd_done = chan->txbds; | ||
| 406 | else | ||
| 407 | chan->txbd_done++; | ||
| 408 | |||
| 409 | if (complete) { | ||
| 410 | spin_unlock_irqrestore(&chan->tx_lock, flags); | ||
| 411 | complete(context); | ||
| 412 | spin_lock_irqsave(&chan->tx_lock, flags); | ||
| 413 | } | ||
| 414 | |||
| 415 | bd = chan->txbd_done; | ||
| 416 | ctrl = qmc_read16(&bd->cbd_sc); | ||
| 417 | } | ||
| 418 | |||
| 419 | end: | ||
| 420 | spin_unlock_irqrestore(&chan->tx_lock, flags); | ||
| 421 | } | ||
| 422 | |||
| 423 | int qmc_chan_read_submit(struct qmc_chan *chan, dma_addr_t addr, size_t length, | ||
| 424 | void (*complete)(void *context, size_t length), void *context) | ||
| 425 | { | ||
| 426 | struct qmc_xfer_desc *xfer_desc; | ||
| 427 | unsigned long flags; | ||
| 428 | cbd_t *__iomem bd; | ||
| 429 | u16 ctrl; | ||
| 430 | int ret; | ||
| 431 | |||
| 432 | /* | ||
| 433 | * E bit UB bit | ||
| 434 | * 0 0 : The BD is free | ||
| 435 | * 1 1 : The BD is in used, waiting for transfer | ||
| 436 | * 0 1 : The BD is in used, waiting for completion | ||
| 437 | * 1 0 : Should not append | ||
| 438 | */ | ||
| 439 | |||
| 440 | spin_lock_irqsave(&chan->rx_lock, flags); | ||
| 441 | bd = chan->rxbd_free; | ||
| 442 | |||
| 443 | ctrl = qmc_read16(&bd->cbd_sc); | ||
| 444 | if (ctrl & (QMC_BD_RX_E | QMC_BD_RX_UB)) { | ||
| 445 | /* We are full ... */ | ||
| 446 | ret = -EBUSY; | ||
| 447 | goto end; | ||
| 448 | } | ||
| 449 | |||
| 450 | qmc_write16(&bd->cbd_datlen, 0); /* data length is updated by the QMC */ | ||
| 451 | qmc_write32(&bd->cbd_bufaddr, addr); | ||
| 452 | |||
| 453 | xfer_desc = &chan->rx_desc[bd - chan->rxbds]; | ||
| 454 | xfer_desc->rx_complete = complete; | ||
| 455 | xfer_desc->context = context; | ||
| 456 | |||
| 457 | /* Activate the descriptor */ | ||
| 458 | ctrl |= (QMC_BD_RX_E | QMC_BD_RX_UB); | ||
| 459 | wmb(); /* Be sure to flush data before descriptor activation */ | ||
| 460 | qmc_write16(&bd->cbd_sc, ctrl); | ||
| 461 | |||
| 462 | /* Restart receiver if needed */ | ||
| 463 | if (chan->is_rx_halted && !chan->is_rx_stopped) { | ||
| 464 | /* Restart receiver */ | ||
| 465 | if (chan->mode == QMC_TRANSPARENT) | ||
| 466 | qmc_write32(chan->s_param + QMC_SPE_ZDSTATE, 0x18000080); | ||
| 467 | else | ||
| 468 | qmc_write32(chan->s_param + QMC_SPE_ZDSTATE, 0x00000080); | ||
| 469 | qmc_write32(chan->s_param + QMC_SPE_RSTATE, 0x31000000); | ||
| 470 | chan->is_rx_halted = false; | ||
| 471 | } | ||
| 472 | chan->rx_pending++; | ||
| 473 | |||
| 474 | if (ctrl & QMC_BD_RX_W) | ||
| 475 | chan->rxbd_free = chan->rxbds; | ||
| 476 | else | ||
| 477 | chan->rxbd_free++; | ||
| 478 | |||
| 479 | ret = 0; | ||
| 480 | end: | ||
| 481 | spin_unlock_irqrestore(&chan->rx_lock, flags); | ||
| 482 | return ret; | ||
| 483 | } | ||
| 484 | EXPORT_SYMBOL(qmc_chan_read_submit); | ||
| 485 | |||
| 486 | static void qmc_chan_read_done(struct qmc_chan *chan) | ||
| 487 | { | ||
| 488 | void (*complete)(void *context, size_t size); | ||
| 489 | struct qmc_xfer_desc *xfer_desc; | ||
| 490 | unsigned long flags; | ||
| 491 | cbd_t *__iomem bd; | ||
| 492 | void *context; | ||
| 493 | u16 datalen; | ||
| 494 | u16 ctrl; | ||
| 495 | |||
| 496 | /* | ||
| 497 | * E bit UB bit | ||
| 498 | * 0 0 : The BD is free | ||
| 499 | * 1 1 : The BD is in used, waiting for transfer | ||
| 500 | * 0 1 : The BD is in used, waiting for completion | ||
| 501 | * 1 0 : Should not append | ||
| 502 | */ | ||
| 503 | |||
| 504 | spin_lock_irqsave(&chan->rx_lock, flags); | ||
| 505 | bd = chan->rxbd_done; | ||
| 506 | |||
| 507 | ctrl = qmc_read16(&bd->cbd_sc); | ||
| 508 | while (!(ctrl & QMC_BD_RX_E)) { | ||
| 509 | if (!(ctrl & QMC_BD_RX_UB)) | ||
| 510 | goto end; | ||
| 511 | |||
| 512 | xfer_desc = &chan->rx_desc[bd - chan->rxbds]; | ||
| 513 | complete = xfer_desc->rx_complete; | ||
| 514 | context = xfer_desc->context; | ||
| 515 | xfer_desc->rx_complete = NULL; | ||
| 516 | xfer_desc->context = NULL; | ||
| 517 | |||
| 518 | datalen = qmc_read16(&bd->cbd_datlen); | ||
| 519 | qmc_write16(&bd->cbd_sc, ctrl & ~QMC_BD_RX_UB); | ||
| 520 | |||
| 521 | if (ctrl & QMC_BD_RX_W) | ||
| 522 | chan->rxbd_done = chan->rxbds; | ||
| 523 | else | ||
| 524 | chan->rxbd_done++; | ||
| 525 | |||
| 526 | chan->rx_pending--; | ||
| 527 | |||
| 528 | if (complete) { | ||
| 529 | spin_unlock_irqrestore(&chan->rx_lock, flags); | ||
| 530 | complete(context, datalen); | ||
| 531 | spin_lock_irqsave(&chan->rx_lock, flags); | ||
| 532 | } | ||
| 533 | |||
| 534 | bd = chan->rxbd_done; | ||
| 535 | ctrl = qmc_read16(&bd->cbd_sc); | ||
| 536 | } | ||
| 537 | |||
| 538 | end: | ||
| 539 | spin_unlock_irqrestore(&chan->rx_lock, flags); | ||
| 540 | } | ||
| 541 | |||
| 542 | static int qmc_chan_command(struct qmc_chan *chan, u8 qmc_opcode) | ||
| 543 | { | ||
| 544 | return cpm_command(chan->id << 2, (qmc_opcode << 4) | 0x0E); | ||
| 545 | } | ||
| 546 | |||
| 547 | static int qmc_chan_stop_rx(struct qmc_chan *chan) | ||
| 548 | { | ||
| 549 | unsigned long flags; | ||
| 550 | int ret; | ||
| 551 | |||
| 552 | spin_lock_irqsave(&chan->rx_lock, flags); | ||
| 553 | |||
| 554 | /* Send STOP RECEIVE command */ | ||
| 555 | ret = qmc_chan_command(chan, 0x0); | ||
| 556 | if (ret) { | ||
| 557 | dev_err(chan->qmc->dev, "chan %u: Send STOP RECEIVE failed (%d)\n", | ||
| 558 | chan->id, ret); | ||
| 559 | goto end; | ||
| 560 | } | ||
| 561 | |||
| 562 | chan->is_rx_stopped = true; | ||
| 563 | |||
| 564 | end: | ||
| 565 | spin_unlock_irqrestore(&chan->rx_lock, flags); | ||
| 566 | return ret; | ||
| 567 | } | ||
| 568 | |||
| 569 | static int qmc_chan_stop_tx(struct qmc_chan *chan) | ||
| 570 | { | ||
| 571 | unsigned long flags; | ||
| 572 | int ret; | ||
| 573 | |||
| 574 | spin_lock_irqsave(&chan->tx_lock, flags); | ||
| 575 | |||
| 576 | /* Send STOP TRANSMIT command */ | ||
| 577 | ret = qmc_chan_command(chan, 0x1); | ||
| 578 | if (ret) { | ||
| 579 | dev_err(chan->qmc->dev, "chan %u: Send STOP TRANSMIT failed (%d)\n", | ||
| 580 | chan->id, ret); | ||
| 581 | goto end; | ||
| 582 | } | ||
| 583 | |||
| 584 | chan->is_tx_stopped = true; | ||
| 585 | |||
| 586 | end: | ||
| 587 | spin_unlock_irqrestore(&chan->tx_lock, flags); | ||
| 588 | return ret; | ||
| 589 | } | ||
| 590 | |||
| 591 | int qmc_chan_stop(struct qmc_chan *chan, int direction) | ||
| 592 | { | ||
| 593 | int ret; | ||
| 594 | |||
| 595 | if (direction & QMC_CHAN_READ) { | ||
| 596 | ret = qmc_chan_stop_rx(chan); | ||
| 597 | if (ret) | ||
| 598 | return ret; | ||
| 599 | } | ||
| 600 | |||
| 601 | if (direction & QMC_CHAN_WRITE) { | ||
| 602 | ret = qmc_chan_stop_tx(chan); | ||
| 603 | if (ret) | ||
| 604 | return ret; | ||
| 605 | } | ||
| 606 | |||
| 607 | return 0; | ||
| 608 | } | ||
| 609 | EXPORT_SYMBOL(qmc_chan_stop); | ||
| 610 | |||
| 611 | static void qmc_chan_start_rx(struct qmc_chan *chan) | ||
| 612 | { | ||
| 613 | unsigned long flags; | ||
| 614 | |||
| 615 | spin_lock_irqsave(&chan->rx_lock, flags); | ||
| 616 | |||
| 617 | /* Restart the receiver */ | ||
| 618 | if (chan->mode == QMC_TRANSPARENT) | ||
| 619 | qmc_write32(chan->s_param + QMC_SPE_ZDSTATE, 0x18000080); | ||
| 620 | else | ||
| 621 | qmc_write32(chan->s_param + QMC_SPE_ZDSTATE, 0x00000080); | ||
| 622 | qmc_write32(chan->s_param + QMC_SPE_RSTATE, 0x31000000); | ||
| 623 | chan->is_rx_halted = false; | ||
| 624 | |||
| 625 | chan->is_rx_stopped = false; | ||
| 626 | |||
| 627 | spin_unlock_irqrestore(&chan->rx_lock, flags); | ||
| 628 | } | ||
| 629 | |||
| 630 | static void qmc_chan_start_tx(struct qmc_chan *chan) | ||
| 631 | { | ||
| 632 | unsigned long flags; | ||
| 633 | |||
| 634 | spin_lock_irqsave(&chan->tx_lock, flags); | ||
| 635 | |||
| 636 | /* | ||
| 637 | * Enable channel transmitter as it could be disabled if | ||
| 638 | * qmc_chan_reset() was called. | ||
| 639 | */ | ||
| 640 | qmc_setbits16(chan->s_param + QMC_SPE_CHAMR, QMC_SPE_CHAMR_ENT); | ||
| 641 | |||
| 642 | /* Set the POL bit in the channel mode register */ | ||
| 643 | qmc_setbits16(chan->s_param + QMC_SPE_CHAMR, QMC_SPE_CHAMR_POL); | ||
| 644 | |||
| 645 | chan->is_tx_stopped = false; | ||
| 646 | |||
| 647 | spin_unlock_irqrestore(&chan->tx_lock, flags); | ||
| 648 | } | ||
| 649 | |||
| 650 | int qmc_chan_start(struct qmc_chan *chan, int direction) | ||
| 651 | { | ||
| 652 | if (direction & QMC_CHAN_READ) | ||
| 653 | qmc_chan_start_rx(chan); | ||
| 654 | |||
| 655 | if (direction & QMC_CHAN_WRITE) | ||
| 656 | qmc_chan_start_tx(chan); | ||
| 657 | |||
| 658 | return 0; | ||
| 659 | } | ||
| 660 | EXPORT_SYMBOL(qmc_chan_start); | ||
| 661 | |||
| 662 | static void qmc_chan_reset_rx(struct qmc_chan *chan) | ||
| 663 | { | ||
| 664 | struct qmc_xfer_desc *xfer_desc; | ||
| 665 | unsigned long flags; | ||
| 666 | cbd_t *__iomem bd; | ||
| 667 | u16 ctrl; | ||
| 668 | |||
| 669 | spin_lock_irqsave(&chan->rx_lock, flags); | ||
| 670 | bd = chan->rxbds; | ||
| 671 | do { | ||
| 672 | ctrl = qmc_read16(&bd->cbd_sc); | ||
| 673 | qmc_write16(&bd->cbd_sc, ctrl & ~(QMC_BD_RX_UB | QMC_BD_RX_E)); | ||
| 674 | |||
| 675 | xfer_desc = &chan->rx_desc[bd - chan->rxbds]; | ||
| 676 | xfer_desc->rx_complete = NULL; | ||
| 677 | xfer_desc->context = NULL; | ||
| 678 | |||
| 679 | bd++; | ||
| 680 | } while (!(ctrl & QMC_BD_RX_W)); | ||
| 681 | |||
| 682 | chan->rxbd_free = chan->rxbds; | ||
| 683 | chan->rxbd_done = chan->rxbds; | ||
| 684 | qmc_write16(chan->s_param + QMC_SPE_RBPTR, | ||
| 685 | qmc_read16(chan->s_param + QMC_SPE_RBASE)); | ||
| 686 | |||
| 687 | chan->rx_pending = 0; | ||
| 688 | chan->is_rx_stopped = false; | ||
| 689 | |||
| 690 | spin_unlock_irqrestore(&chan->rx_lock, flags); | ||
| 691 | } | ||
| 692 | |||
| 693 | static void qmc_chan_reset_tx(struct qmc_chan *chan) | ||
| 694 | { | ||
| 695 | struct qmc_xfer_desc *xfer_desc; | ||
| 696 | unsigned long flags; | ||
| 697 | cbd_t *__iomem bd; | ||
| 698 | u16 ctrl; | ||
| 699 | |||
| 700 | spin_lock_irqsave(&chan->tx_lock, flags); | ||
| 701 | |||
| 702 | /* Disable transmitter. It will be re-enable on qmc_chan_start() */ | ||
| 703 | qmc_clrbits16(chan->s_param + QMC_SPE_CHAMR, QMC_SPE_CHAMR_ENT); | ||
| 704 | |||
| 705 | bd = chan->txbds; | ||
| 706 | do { | ||
| 707 | ctrl = qmc_read16(&bd->cbd_sc); | ||
| 708 | qmc_write16(&bd->cbd_sc, ctrl & ~(QMC_BD_TX_UB | QMC_BD_TX_R)); | ||
| 709 | |||
| 710 | xfer_desc = &chan->tx_desc[bd - chan->txbds]; | ||
| 711 | xfer_desc->tx_complete = NULL; | ||
| 712 | xfer_desc->context = NULL; | ||
| 713 | |||
| 714 | bd++; | ||
| 715 | } while (!(ctrl & QMC_BD_TX_W)); | ||
| 716 | |||
| 717 | chan->txbd_free = chan->txbds; | ||
| 718 | chan->txbd_done = chan->txbds; | ||
| 719 | qmc_write16(chan->s_param + QMC_SPE_TBPTR, | ||
| 720 | qmc_read16(chan->s_param + QMC_SPE_TBASE)); | ||
| 721 | |||
| 722 | /* Reset TSTATE and ZISTATE to their initial value */ | ||
| 723 | qmc_write32(chan->s_param + QMC_SPE_TSTATE, 0x30000000); | ||
| 724 | qmc_write32(chan->s_param + QMC_SPE_ZISTATE, 0x00000100); | ||
| 725 | |||
| 726 | spin_unlock_irqrestore(&chan->tx_lock, flags); | ||
| 727 | } | ||
| 728 | |||
| 729 | int qmc_chan_reset(struct qmc_chan *chan, int direction) | ||
| 730 | { | ||
| 731 | if (direction & QMC_CHAN_READ) | ||
| 732 | qmc_chan_reset_rx(chan); | ||
| 733 | |||
| 734 | if (direction & QMC_CHAN_WRITE) | ||
| 735 | qmc_chan_reset_tx(chan); | ||
| 736 | |||
| 737 | return 0; | ||
| 738 | } | ||
| 739 | EXPORT_SYMBOL(qmc_chan_reset); | ||
| 740 | |||
| 741 | static int qmc_check_chans(struct qmc *qmc) | ||
| 742 | { | ||
| 743 | struct tsa_serial_info info; | ||
| 744 | bool is_one_table = false; | ||
| 745 | struct qmc_chan *chan; | ||
| 746 | u64 tx_ts_mask = 0; | ||
| 747 | u64 rx_ts_mask = 0; | ||
| 748 | u64 tx_ts_assigned_mask; | ||
| 749 | u64 rx_ts_assigned_mask; | ||
| 750 | int ret; | ||
| 751 | |||
| 752 | /* Retrieve info from the TSA related serial */ | ||
| 753 | ret = tsa_serial_get_info(qmc->tsa_serial, &info); | ||
| 754 | if (ret) | ||
| 755 | return ret; | ||
| 756 | |||
| 757 | if ((info.nb_tx_ts > 64) || (info.nb_rx_ts > 64)) { | ||
| 758 | dev_err(qmc->dev, "Number of TSA Tx/Rx TS assigned not supported\n"); | ||
| 759 | return -EINVAL; | ||
| 760 | } | ||
| 761 | |||
| 762 | /* | ||
| 763 | * If more than 32 TS are assigned to this serial, one common table is | ||
| 764 | * used for Tx and Rx and so masks must be equal for all channels. | ||
| 765 | */ | ||
| 766 | if ((info.nb_tx_ts > 32) || (info.nb_rx_ts > 32)) { | ||
| 767 | if (info.nb_tx_ts != info.nb_rx_ts) { | ||
| 768 | dev_err(qmc->dev, "Number of TSA Tx/Rx TS assigned are not equal\n"); | ||
| 769 | return -EINVAL; | ||
| 770 | } | ||
| 771 | is_one_table = true; | ||
| 772 | } | ||
| 773 | |||
| 774 | tx_ts_assigned_mask = info.nb_tx_ts == 64 ? U64_MAX : (((u64)1) << info.nb_tx_ts) - 1; | ||
| 775 | rx_ts_assigned_mask = info.nb_rx_ts == 64 ? U64_MAX : (((u64)1) << info.nb_rx_ts) - 1; | ||
| 776 | |||
| 777 | list_for_each_entry(chan, &qmc->chan_head, list) { | ||
| 778 | if (chan->tx_ts_mask > tx_ts_assigned_mask) { | ||
| 779 | dev_err(qmc->dev, "chan %u uses TSA unassigned Tx TS\n", chan->id); | ||
| 780 | return -EINVAL; | ||
| 781 | } | ||
| 782 | if (tx_ts_mask & chan->tx_ts_mask) { | ||
| 783 | dev_err(qmc->dev, "chan %u uses an already used Tx TS\n", chan->id); | ||
| 784 | return -EINVAL; | ||
| 785 | } | ||
| 786 | |||
| 787 | if (chan->rx_ts_mask > rx_ts_assigned_mask) { | ||
| 788 | dev_err(qmc->dev, "chan %u uses TSA unassigned Rx TS\n", chan->id); | ||
| 789 | return -EINVAL; | ||
| 790 | } | ||
| 791 | if (rx_ts_mask & chan->rx_ts_mask) { | ||
| 792 | dev_err(qmc->dev, "chan %u uses an already used Rx TS\n", chan->id); | ||
| 793 | return -EINVAL; | ||
| 794 | } | ||
| 795 | |||
| 796 | if (is_one_table && (chan->tx_ts_mask != chan->rx_ts_mask)) { | ||
| 797 | dev_err(qmc->dev, "chan %u uses different Rx and Tx TS\n", chan->id); | ||
| 798 | return -EINVAL; | ||
| 799 | } | ||
| 800 | |||
| 801 | tx_ts_mask |= chan->tx_ts_mask; | ||
| 802 | rx_ts_mask |= chan->rx_ts_mask; | ||
| 803 | } | ||
| 804 | |||
| 805 | return 0; | ||
| 806 | } | ||
| 807 | |||
| 808 | static unsigned int qmc_nb_chans(struct qmc *qmc) | ||
| 809 | { | ||
| 810 | unsigned int count = 0; | ||
| 811 | struct qmc_chan *chan; | ||
| 812 | |||
| 813 | list_for_each_entry(chan, &qmc->chan_head, list) | ||
| 814 | count++; | ||
| 815 | |||
| 816 | return count; | ||
| 817 | } | ||
| 818 | |||
| 819 | static int qmc_of_parse_chans(struct qmc *qmc, struct device_node *np) | ||
| 820 | { | ||
| 821 | struct device_node *chan_np; | ||
| 822 | struct qmc_chan *chan; | ||
| 823 | const char *mode; | ||
| 824 | u32 chan_id; | ||
| 825 | u64 ts_mask; | ||
| 826 | int ret; | ||
| 827 | |||
| 828 | for_each_available_child_of_node(np, chan_np) { | ||
| 829 | ret = of_property_read_u32(chan_np, "reg", &chan_id); | ||
| 830 | if (ret) { | ||
| 831 | dev_err(qmc->dev, "%pOF: failed to read reg\n", chan_np); | ||
| 832 | of_node_put(chan_np); | ||
| 833 | return ret; | ||
| 834 | } | ||
| 835 | if (chan_id > 63) { | ||
| 836 | dev_err(qmc->dev, "%pOF: Invalid chan_id\n", chan_np); | ||
| 837 | of_node_put(chan_np); | ||
| 838 | return -EINVAL; | ||
| 839 | } | ||
| 840 | |||
| 841 | chan = devm_kzalloc(qmc->dev, sizeof(*chan), GFP_KERNEL); | ||
| 842 | if (!chan) { | ||
| 843 | of_node_put(chan_np); | ||
| 844 | return -ENOMEM; | ||
| 845 | } | ||
| 846 | |||
| 847 | chan->id = chan_id; | ||
| 848 | spin_lock_init(&chan->rx_lock); | ||
| 849 | spin_lock_init(&chan->tx_lock); | ||
| 850 | |||
| 851 | ret = of_property_read_u64(chan_np, "fsl,tx-ts-mask", &ts_mask); | ||
| 852 | if (ret) { | ||
| 853 | dev_err(qmc->dev, "%pOF: failed to read fsl,tx-ts-mask\n", | ||
| 854 | chan_np); | ||
| 855 | of_node_put(chan_np); | ||
| 856 | return ret; | ||
| 857 | } | ||
| 858 | chan->tx_ts_mask = ts_mask; | ||
| 859 | |||
| 860 | ret = of_property_read_u64(chan_np, "fsl,rx-ts-mask", &ts_mask); | ||
| 861 | if (ret) { | ||
| 862 | dev_err(qmc->dev, "%pOF: failed to read fsl,rx-ts-mask\n", | ||
| 863 | chan_np); | ||
| 864 | of_node_put(chan_np); | ||
| 865 | return ret; | ||
| 866 | } | ||
| 867 | chan->rx_ts_mask = ts_mask; | ||
| 868 | |||
| 869 | mode = "transparent"; | ||
| 870 | ret = of_property_read_string(chan_np, "fsl,operational-mode", &mode); | ||
| 871 | if (ret && ret != -EINVAL) { | ||
| 872 | dev_err(qmc->dev, "%pOF: failed to read fsl,operational-mode\n", | ||
| 873 | chan_np); | ||
| 874 | of_node_put(chan_np); | ||
| 875 | return ret; | ||
| 876 | } | ||
| 877 | if (!strcmp(mode, "transparent")) { | ||
| 878 | chan->mode = QMC_TRANSPARENT; | ||
| 879 | } else if (!strcmp(mode, "hdlc")) { | ||
| 880 | chan->mode = QMC_HDLC; | ||
| 881 | } else { | ||
| 882 | dev_err(qmc->dev, "%pOF: Invalid fsl,operational-mode (%s)\n", | ||
| 883 | chan_np, mode); | ||
| 884 | of_node_put(chan_np); | ||
| 885 | return -EINVAL; | ||
| 886 | } | ||
| 887 | |||
| 888 | chan->is_reverse_data = of_property_read_bool(chan_np, | ||
| 889 | "fsl,reverse-data"); | ||
| 890 | |||
| 891 | list_add_tail(&chan->list, &qmc->chan_head); | ||
| 892 | qmc->chans[chan->id] = chan; | ||
| 893 | } | ||
| 894 | |||
| 895 | return qmc_check_chans(qmc); | ||
| 896 | } | ||
| 897 | |||
| 898 | static int qmc_setup_tsa_64rxtx(struct qmc *qmc, const struct tsa_serial_info *info) | ||
| 899 | { | ||
| 900 | struct qmc_chan *chan; | ||
| 901 | unsigned int i; | ||
| 902 | u16 val; | ||
| 903 | |||
| 904 | /* | ||
| 905 | * Use a common Tx/Rx 64 entries table. | ||
| 906 | * Everything was previously checked, Tx and Rx related stuffs are | ||
| 907 | * identical -> Used Rx related stuff to build the table | ||
| 908 | */ | ||
| 909 | |||
| 910 | /* Invalidate all entries */ | ||
| 911 | for (i = 0; i < 64; i++) | ||
| 912 | qmc_write16(qmc->scc_pram + QMC_GBL_TSATRX + (i * 2), 0x0000); | ||
| 913 | |||
| 914 | /* Set entries based on Rx stuff*/ | ||
| 915 | list_for_each_entry(chan, &qmc->chan_head, list) { | ||
| 916 | for (i = 0; i < info->nb_rx_ts; i++) { | ||
| 917 | if (!(chan->rx_ts_mask & (((u64)1) << i))) | ||
| 918 | continue; | ||
| 919 | |||
| 920 | val = QMC_TSA_VALID | QMC_TSA_MASK | | ||
| 921 | QMC_TSA_CHANNEL(chan->id); | ||
| 922 | qmc_write16(qmc->scc_pram + QMC_GBL_TSATRX + (i * 2), val); | ||
| 923 | } | ||
| 924 | } | ||
| 925 | |||
| 926 | /* Set Wrap bit on last entry */ | ||
| 927 | qmc_setbits16(qmc->scc_pram + QMC_GBL_TSATRX + ((info->nb_rx_ts - 1) * 2), | ||
| 928 | QMC_TSA_WRAP); | ||
| 929 | |||
| 930 | /* Init pointers to the table */ | ||
| 931 | val = qmc->scc_pram_offset + QMC_GBL_TSATRX; | ||
| 932 | qmc_write16(qmc->scc_pram + QMC_GBL_RX_S_PTR, val); | ||
| 933 | qmc_write16(qmc->scc_pram + QMC_GBL_RXPTR, val); | ||
| 934 | qmc_write16(qmc->scc_pram + QMC_GBL_TX_S_PTR, val); | ||
| 935 | qmc_write16(qmc->scc_pram + QMC_GBL_TXPTR, val); | ||
| 936 | |||
| 937 | return 0; | ||
| 938 | } | ||
| 939 | |||
| 940 | static int qmc_setup_tsa_32rx_32tx(struct qmc *qmc, const struct tsa_serial_info *info) | ||
| 941 | { | ||
| 942 | struct qmc_chan *chan; | ||
| 943 | unsigned int i; | ||
| 944 | u16 val; | ||
| 945 | |||
| 946 | /* | ||
| 947 | * Use a Tx 32 entries table and a Rx 32 entries table. | ||
| 948 | * Everything was previously checked. | ||
| 949 | */ | ||
| 950 | |||
| 951 | /* Invalidate all entries */ | ||
| 952 | for (i = 0; i < 32; i++) { | ||
| 953 | qmc_write16(qmc->scc_pram + QMC_GBL_TSATRX + (i * 2), 0x0000); | ||
| 954 | qmc_write16(qmc->scc_pram + QMC_GBL_TSATTX + (i * 2), 0x0000); | ||
| 955 | } | ||
| 956 | |||
| 957 | /* Set entries based on Rx and Tx stuff*/ | ||
| 958 | list_for_each_entry(chan, &qmc->chan_head, list) { | ||
| 959 | /* Rx part */ | ||
| 960 | for (i = 0; i < info->nb_rx_ts; i++) { | ||
| 961 | if (!(chan->rx_ts_mask & (((u64)1) << i))) | ||
| 962 | continue; | ||
| 963 | |||
| 964 | val = QMC_TSA_VALID | QMC_TSA_MASK | | ||
| 965 | QMC_TSA_CHANNEL(chan->id); | ||
| 966 | qmc_write16(qmc->scc_pram + QMC_GBL_TSATRX + (i * 2), val); | ||
| 967 | } | ||
| 968 | /* Tx part */ | ||
| 969 | for (i = 0; i < info->nb_tx_ts; i++) { | ||
| 970 | if (!(chan->tx_ts_mask & (((u64)1) << i))) | ||
| 971 | continue; | ||
| 972 | |||
| 973 | val = QMC_TSA_VALID | QMC_TSA_MASK | | ||
| 974 | QMC_TSA_CHANNEL(chan->id); | ||
| 975 | qmc_write16(qmc->scc_pram + QMC_GBL_TSATTX + (i * 2), val); | ||
| 976 | } | ||
| 977 | } | ||
| 978 | |||
| 979 | /* Set Wrap bit on last entries */ | ||
| 980 | qmc_setbits16(qmc->scc_pram + QMC_GBL_TSATRX + ((info->nb_rx_ts - 1) * 2), | ||
| 981 | QMC_TSA_WRAP); | ||
| 982 | qmc_setbits16(qmc->scc_pram + QMC_GBL_TSATTX + ((info->nb_tx_ts - 1) * 2), | ||
| 983 | QMC_TSA_WRAP); | ||
| 984 | |||
| 985 | /* Init Rx pointers ...*/ | ||
| 986 | val = qmc->scc_pram_offset + QMC_GBL_TSATRX; | ||
| 987 | qmc_write16(qmc->scc_pram + QMC_GBL_RX_S_PTR, val); | ||
| 988 | qmc_write16(qmc->scc_pram + QMC_GBL_RXPTR, val); | ||
| 989 | |||
| 990 | /* ... and Tx pointers */ | ||
| 991 | val = qmc->scc_pram_offset + QMC_GBL_TSATTX; | ||
| 992 | qmc_write16(qmc->scc_pram + QMC_GBL_TX_S_PTR, val); | ||
| 993 | qmc_write16(qmc->scc_pram + QMC_GBL_TXPTR, val); | ||
| 994 | |||
| 995 | return 0; | ||
| 996 | } | ||
| 997 | |||
| 998 | static int qmc_setup_tsa(struct qmc *qmc) | ||
| 999 | { | ||
| 1000 | struct tsa_serial_info info; | ||
| 1001 | int ret; | ||
| 1002 | |||
| 1003 | /* Retrieve info from the TSA related serial */ | ||
| 1004 | ret = tsa_serial_get_info(qmc->tsa_serial, &info); | ||
| 1005 | if (ret) | ||
| 1006 | return ret; | ||
| 1007 | |||
| 1008 | /* | ||
| 1009 | * Setup one common 64 entries table or two 32 entries (one for Tx and | ||
| 1010 | * one for Tx) according to assigned TS numbers. | ||
| 1011 | */ | ||
| 1012 | return ((info.nb_tx_ts > 32) || (info.nb_rx_ts > 32)) ? | ||
| 1013 | qmc_setup_tsa_64rxtx(qmc, &info) : | ||
| 1014 | qmc_setup_tsa_32rx_32tx(qmc, &info); | ||
| 1015 | } | ||
| 1016 | |||
| 1017 | static int qmc_setup_chan_trnsync(struct qmc *qmc, struct qmc_chan *chan) | ||
| 1018 | { | ||
| 1019 | struct tsa_serial_info info; | ||
| 1020 | u16 first_rx, last_tx; | ||
| 1021 | u16 trnsync; | ||
| 1022 | int ret; | ||
| 1023 | |||
| 1024 | /* Retrieve info from the TSA related serial */ | ||
| 1025 | ret = tsa_serial_get_info(chan->qmc->tsa_serial, &info); | ||
| 1026 | if (ret) | ||
| 1027 | return ret; | ||
| 1028 | |||
| 1029 | /* Find the first Rx TS allocated to the channel */ | ||
| 1030 | first_rx = chan->rx_ts_mask ? __ffs64(chan->rx_ts_mask) + 1 : 0; | ||
| 1031 | |||
| 1032 | /* Find the last Tx TS allocated to the channel */ | ||
| 1033 | last_tx = fls64(chan->tx_ts_mask); | ||
| 1034 | |||
| 1035 | trnsync = 0; | ||
| 1036 | if (info.nb_rx_ts) | ||
| 1037 | trnsync |= QMC_SPE_TRNSYNC_RX((first_rx % info.nb_rx_ts) * 2); | ||
| 1038 | if (info.nb_tx_ts) | ||
| 1039 | trnsync |= QMC_SPE_TRNSYNC_TX((last_tx % info.nb_tx_ts) * 2); | ||
| 1040 | |||
| 1041 | qmc_write16(chan->s_param + QMC_SPE_TRNSYNC, trnsync); | ||
| 1042 | |||
| 1043 | dev_dbg(qmc->dev, "chan %u: trnsync=0x%04x, rx %u/%u 0x%llx, tx %u/%u 0x%llx\n", | ||
| 1044 | chan->id, trnsync, | ||
| 1045 | first_rx, info.nb_rx_ts, chan->rx_ts_mask, | ||
| 1046 | last_tx, info.nb_tx_ts, chan->tx_ts_mask); | ||
| 1047 | |||
| 1048 | return 0; | ||
| 1049 | } | ||
| 1050 | |||
| 1051 | static int qmc_setup_chan(struct qmc *qmc, struct qmc_chan *chan) | ||
| 1052 | { | ||
| 1053 | unsigned int i; | ||
| 1054 | cbd_t __iomem *bd; | ||
| 1055 | int ret; | ||
| 1056 | u16 val; | ||
| 1057 | |||
| 1058 | chan->qmc = qmc; | ||
| 1059 | |||
| 1060 | /* Set channel specific parameter base address */ | ||
| 1061 | chan->s_param = qmc->dpram + (chan->id * 64); | ||
| 1062 | /* 16 bd per channel (8 rx and 8 tx) */ | ||
| 1063 | chan->txbds = qmc->bd_table + (chan->id * (QMC_NB_TXBDS + QMC_NB_RXBDS)); | ||
| 1064 | chan->rxbds = qmc->bd_table + (chan->id * (QMC_NB_TXBDS + QMC_NB_RXBDS)) + QMC_NB_TXBDS; | ||
| 1065 | |||
| 1066 | chan->txbd_free = chan->txbds; | ||
| 1067 | chan->txbd_done = chan->txbds; | ||
| 1068 | chan->rxbd_free = chan->rxbds; | ||
| 1069 | chan->rxbd_done = chan->rxbds; | ||
| 1070 | |||
| 1071 | /* TBASE and TBPTR*/ | ||
| 1072 | val = chan->id * (QMC_NB_TXBDS + QMC_NB_RXBDS) * sizeof(cbd_t); | ||
| 1073 | qmc_write16(chan->s_param + QMC_SPE_TBASE, val); | ||
| 1074 | qmc_write16(chan->s_param + QMC_SPE_TBPTR, val); | ||
| 1075 | |||
| 1076 | /* RBASE and RBPTR*/ | ||
| 1077 | val = ((chan->id * (QMC_NB_TXBDS + QMC_NB_RXBDS)) + QMC_NB_TXBDS) * sizeof(cbd_t); | ||
| 1078 | qmc_write16(chan->s_param + QMC_SPE_RBASE, val); | ||
| 1079 | qmc_write16(chan->s_param + QMC_SPE_RBPTR, val); | ||
| 1080 | qmc_write32(chan->s_param + QMC_SPE_TSTATE, 0x30000000); | ||
| 1081 | qmc_write32(chan->s_param + QMC_SPE_RSTATE, 0x31000000); | ||
| 1082 | qmc_write32(chan->s_param + QMC_SPE_ZISTATE, 0x00000100); | ||
| 1083 | if (chan->mode == QMC_TRANSPARENT) { | ||
| 1084 | qmc_write32(chan->s_param + QMC_SPE_ZDSTATE, 0x18000080); | ||
| 1085 | qmc_write16(chan->s_param + QMC_SPE_TMRBLR, 60); | ||
| 1086 | val = QMC_SPE_CHAMR_MODE_TRANSP | QMC_SPE_CHAMR_TRANSP_SYNC; | ||
| 1087 | if (chan->is_reverse_data) | ||
| 1088 | val |= QMC_SPE_CHAMR_TRANSP_RD; | ||
| 1089 | qmc_write16(chan->s_param + QMC_SPE_CHAMR, val); | ||
| 1090 | ret = qmc_setup_chan_trnsync(qmc, chan); | ||
| 1091 | if (ret) | ||
| 1092 | return ret; | ||
| 1093 | } else { | ||
| 1094 | qmc_write32(chan->s_param + QMC_SPE_ZDSTATE, 0x00000080); | ||
| 1095 | qmc_write16(chan->s_param + QMC_SPE_MFLR, 60); | ||
| 1096 | qmc_write16(chan->s_param + QMC_SPE_CHAMR, | ||
| 1097 | QMC_SPE_CHAMR_MODE_HDLC | QMC_SPE_CHAMR_HDLC_IDLM); | ||
| 1098 | } | ||
| 1099 | |||
| 1100 | /* Do not enable interrupts now. They will be enabled later */ | ||
| 1101 | qmc_write16(chan->s_param + QMC_SPE_INTMSK, 0x0000); | ||
| 1102 | |||
| 1103 | /* Init Rx BDs and set Wrap bit on last descriptor */ | ||
| 1104 | BUILD_BUG_ON(QMC_NB_RXBDS == 0); | ||
| 1105 | val = QMC_BD_RX_I; | ||
| 1106 | for (i = 0; i < QMC_NB_RXBDS; i++) { | ||
| 1107 | bd = chan->rxbds + i; | ||
| 1108 | qmc_write16(&bd->cbd_sc, val); | ||
| 1109 | } | ||
| 1110 | bd = chan->rxbds + QMC_NB_RXBDS - 1; | ||
| 1111 | qmc_write16(&bd->cbd_sc, val | QMC_BD_RX_W); | ||
| 1112 | |||
| 1113 | /* Init Tx BDs and set Wrap bit on last descriptor */ | ||
| 1114 | BUILD_BUG_ON(QMC_NB_TXBDS == 0); | ||
| 1115 | val = QMC_BD_TX_I; | ||
| 1116 | if (chan->mode == QMC_HDLC) | ||
| 1117 | val |= QMC_BD_TX_L | QMC_BD_TX_TC; | ||
| 1118 | for (i = 0; i < QMC_NB_TXBDS; i++) { | ||
| 1119 | bd = chan->txbds + i; | ||
| 1120 | qmc_write16(&bd->cbd_sc, val); | ||
| 1121 | } | ||
| 1122 | bd = chan->txbds + QMC_NB_TXBDS - 1; | ||
| 1123 | qmc_write16(&bd->cbd_sc, val | QMC_BD_TX_W); | ||
| 1124 | |||
| 1125 | return 0; | ||
| 1126 | } | ||
| 1127 | |||
| 1128 | static int qmc_setup_chans(struct qmc *qmc) | ||
| 1129 | { | ||
| 1130 | struct qmc_chan *chan; | ||
| 1131 | int ret; | ||
| 1132 | |||
| 1133 | list_for_each_entry(chan, &qmc->chan_head, list) { | ||
| 1134 | ret = qmc_setup_chan(qmc, chan); | ||
| 1135 | if (ret) | ||
| 1136 | return ret; | ||
| 1137 | } | ||
| 1138 | |||
| 1139 | return 0; | ||
| 1140 | } | ||
| 1141 | |||
| 1142 | static int qmc_finalize_chans(struct qmc *qmc) | ||
| 1143 | { | ||
| 1144 | struct qmc_chan *chan; | ||
| 1145 | int ret; | ||
| 1146 | |||
| 1147 | list_for_each_entry(chan, &qmc->chan_head, list) { | ||
| 1148 | /* Unmask channel interrupts */ | ||
| 1149 | if (chan->mode == QMC_HDLC) { | ||
| 1150 | qmc_write16(chan->s_param + QMC_SPE_INTMSK, | ||
| 1151 | QMC_INT_NID | QMC_INT_IDL | QMC_INT_MRF | | ||
| 1152 | QMC_INT_UN | QMC_INT_RXF | QMC_INT_BSY | | ||
| 1153 | QMC_INT_TXB | QMC_INT_RXB); | ||
| 1154 | } else { | ||
| 1155 | qmc_write16(chan->s_param + QMC_SPE_INTMSK, | ||
| 1156 | QMC_INT_UN | QMC_INT_BSY | | ||
| 1157 | QMC_INT_TXB | QMC_INT_RXB); | ||
| 1158 | } | ||
| 1159 | |||
| 1160 | /* Forced stop the channel */ | ||
| 1161 | ret = qmc_chan_stop(chan, QMC_CHAN_ALL); | ||
| 1162 | if (ret) | ||
| 1163 | return ret; | ||
| 1164 | } | ||
| 1165 | |||
| 1166 | return 0; | ||
| 1167 | } | ||
| 1168 | |||
| 1169 | static int qmc_setup_ints(struct qmc *qmc) | ||
| 1170 | { | ||
| 1171 | unsigned int i; | ||
| 1172 | u16 __iomem *last; | ||
| 1173 | |||
| 1174 | /* Raz all entries */ | ||
| 1175 | for (i = 0; i < (qmc->int_size / sizeof(u16)); i++) | ||
| 1176 | qmc_write16(qmc->int_table + i, 0x0000); | ||
| 1177 | |||
| 1178 | /* Set Wrap bit on last entry */ | ||
| 1179 | if (qmc->int_size >= sizeof(u16)) { | ||
| 1180 | last = qmc->int_table + (qmc->int_size / sizeof(u16)) - 1; | ||
| 1181 | qmc_write16(last, QMC_INT_W); | ||
| 1182 | } | ||
| 1183 | |||
| 1184 | return 0; | ||
| 1185 | } | ||
| 1186 | |||
| 1187 | static void qmc_irq_gint(struct qmc *qmc) | ||
| 1188 | { | ||
| 1189 | struct qmc_chan *chan; | ||
| 1190 | unsigned int chan_id; | ||
| 1191 | unsigned long flags; | ||
| 1192 | u16 int_entry; | ||
| 1193 | |||
| 1194 | int_entry = qmc_read16(qmc->int_curr); | ||
| 1195 | while (int_entry & QMC_INT_V) { | ||
| 1196 | /* Clear all but the Wrap bit */ | ||
| 1197 | qmc_write16(qmc->int_curr, int_entry & QMC_INT_W); | ||
| 1198 | |||
| 1199 | chan_id = QMC_INT_GET_CHANNEL(int_entry); | ||
| 1200 | chan = qmc->chans[chan_id]; | ||
| 1201 | if (!chan) { | ||
| 1202 | dev_err(qmc->dev, "interrupt on invalid chan %u\n", chan_id); | ||
| 1203 | goto int_next; | ||
| 1204 | } | ||
| 1205 | |||
| 1206 | if (int_entry & QMC_INT_TXB) | ||
| 1207 | qmc_chan_write_done(chan); | ||
| 1208 | |||
| 1209 | if (int_entry & QMC_INT_UN) { | ||
| 1210 | dev_info(qmc->dev, "intr chan %u, 0x%04x (UN)\n", chan_id, | ||
| 1211 | int_entry); | ||
| 1212 | chan->nb_tx_underrun++; | ||
| 1213 | } | ||
| 1214 | |||
| 1215 | if (int_entry & QMC_INT_BSY) { | ||
| 1216 | dev_info(qmc->dev, "intr chan %u, 0x%04x (BSY)\n", chan_id, | ||
| 1217 | int_entry); | ||
| 1218 | chan->nb_rx_busy++; | ||
| 1219 | /* Restart the receiver if needed */ | ||
| 1220 | spin_lock_irqsave(&chan->rx_lock, flags); | ||
| 1221 | if (chan->rx_pending && !chan->is_rx_stopped) { | ||
| 1222 | if (chan->mode == QMC_TRANSPARENT) | ||
| 1223 | qmc_write32(chan->s_param + QMC_SPE_ZDSTATE, 0x18000080); | ||
| 1224 | else | ||
| 1225 | qmc_write32(chan->s_param + QMC_SPE_ZDSTATE, 0x00000080); | ||
| 1226 | qmc_write32(chan->s_param + QMC_SPE_RSTATE, 0x31000000); | ||
| 1227 | chan->is_rx_halted = false; | ||
| 1228 | } else { | ||
| 1229 | chan->is_rx_halted = true; | ||
| 1230 | } | ||
| 1231 | spin_unlock_irqrestore(&chan->rx_lock, flags); | ||
| 1232 | } | ||
| 1233 | |||
| 1234 | if (int_entry & QMC_INT_RXB) | ||
| 1235 | qmc_chan_read_done(chan); | ||
| 1236 | |||
| 1237 | int_next: | ||
| 1238 | if (int_entry & QMC_INT_W) | ||
| 1239 | qmc->int_curr = qmc->int_table; | ||
| 1240 | else | ||
| 1241 | qmc->int_curr++; | ||
| 1242 | int_entry = qmc_read16(qmc->int_curr); | ||
| 1243 | } | ||
| 1244 | } | ||
| 1245 | |||
| 1246 | static irqreturn_t qmc_irq_handler(int irq, void *priv) | ||
| 1247 | { | ||
| 1248 | struct qmc *qmc = (struct qmc *)priv; | ||
| 1249 | u16 scce; | ||
| 1250 | |||
| 1251 | scce = qmc_read16(qmc->scc_regs + SCC_SCCE); | ||
| 1252 | qmc_write16(qmc->scc_regs + SCC_SCCE, scce); | ||
| 1253 | |||
| 1254 | if (unlikely(scce & SCC_SCCE_IQOV)) | ||
| 1255 | dev_info(qmc->dev, "IRQ queue overflow\n"); | ||
| 1256 | |||
| 1257 | if (unlikely(scce & SCC_SCCE_GUN)) | ||
| 1258 | dev_err(qmc->dev, "Global transmitter underrun\n"); | ||
| 1259 | |||
| 1260 | if (unlikely(scce & SCC_SCCE_GOV)) | ||
| 1261 | dev_err(qmc->dev, "Global receiver overrun\n"); | ||
| 1262 | |||
| 1263 | /* normal interrupt */ | ||
| 1264 | if (likely(scce & SCC_SCCE_GINT)) | ||
| 1265 | qmc_irq_gint(qmc); | ||
| 1266 | |||
| 1267 | return IRQ_HANDLED; | ||
| 1268 | } | ||
| 1269 | |||
| 1270 | static int qmc_probe(struct platform_device *pdev) | ||
| 1271 | { | ||
| 1272 | struct device_node *np = pdev->dev.of_node; | ||
| 1273 | unsigned int nb_chans; | ||
| 1274 | struct resource *res; | ||
| 1275 | struct qmc *qmc; | ||
| 1276 | int irq; | ||
| 1277 | int ret; | ||
| 1278 | |||
| 1279 | qmc = devm_kzalloc(&pdev->dev, sizeof(*qmc), GFP_KERNEL); | ||
| 1280 | if (!qmc) | ||
| 1281 | return -ENOMEM; | ||
| 1282 | |||
| 1283 | qmc->dev = &pdev->dev; | ||
| 1284 | INIT_LIST_HEAD(&qmc->chan_head); | ||
| 1285 | |||
| 1286 | qmc->scc_regs = devm_platform_ioremap_resource_byname(pdev, "scc_regs"); | ||
| 1287 | if (IS_ERR(qmc->scc_regs)) | ||
| 1288 | return PTR_ERR(qmc->scc_regs); | ||
| 1289 | |||
| 1290 | |||
| 1291 | res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "scc_pram"); | ||
| 1292 | if (!res) | ||
| 1293 | return -EINVAL; | ||
| 1294 | qmc->scc_pram_offset = res->start - get_immrbase(); | ||
| 1295 | qmc->scc_pram = devm_ioremap_resource(qmc->dev, res); | ||
| 1296 | if (IS_ERR(qmc->scc_pram)) | ||
| 1297 | return PTR_ERR(qmc->scc_pram); | ||
| 1298 | |||
| 1299 | qmc->dpram = devm_platform_ioremap_resource_byname(pdev, "dpram"); | ||
| 1300 | if (IS_ERR(qmc->dpram)) | ||
| 1301 | return PTR_ERR(qmc->dpram); | ||
| 1302 | |||
| 1303 | qmc->tsa_serial = devm_tsa_serial_get_byphandle(qmc->dev, np, "fsl,tsa-serial"); | ||
| 1304 | if (IS_ERR(qmc->tsa_serial)) { | ||
| 1305 | return dev_err_probe(qmc->dev, PTR_ERR(qmc->tsa_serial), | ||
| 1306 | "Failed to get TSA serial\n"); | ||
| 1307 | } | ||
| 1308 | |||
| 1309 | /* Connect the serial (SCC) to TSA */ | ||
| 1310 | ret = tsa_serial_connect(qmc->tsa_serial); | ||
| 1311 | if (ret) { | ||
| 1312 | dev_err(qmc->dev, "Failed to connect TSA serial\n"); | ||
| 1313 | return ret; | ||
| 1314 | } | ||
| 1315 | |||
| 1316 | /* Parse channels informationss */ | ||
| 1317 | ret = qmc_of_parse_chans(qmc, np); | ||
| 1318 | if (ret) | ||
| 1319 | goto err_tsa_serial_disconnect; | ||
| 1320 | |||
| 1321 | nb_chans = qmc_nb_chans(qmc); | ||
| 1322 | |||
| 1323 | /* Init GMSR_H and GMSR_L registers */ | ||
| 1324 | qmc_write32(qmc->scc_regs + SCC_GSMRH, | ||
| 1325 | SCC_GSMRH_CDS | SCC_GSMRH_CTSS | SCC_GSMRH_CDP | SCC_GSMRH_CTSP); | ||
| 1326 | |||
| 1327 | /* enable QMC mode */ | ||
| 1328 | qmc_write32(qmc->scc_regs + SCC_GSMRL, SCC_GSMRL_MODE_QMC); | ||
| 1329 | |||
| 1330 | /* | ||
| 1331 | * Allocate the buffer descriptor table | ||
| 1332 | * 8 rx and 8 tx descriptors per channel | ||
| 1333 | */ | ||
| 1334 | qmc->bd_size = (nb_chans * (QMC_NB_TXBDS + QMC_NB_RXBDS)) * sizeof(cbd_t); | ||
| 1335 | qmc->bd_table = dmam_alloc_coherent(qmc->dev, qmc->bd_size, | ||
| 1336 | &qmc->bd_dma_addr, GFP_KERNEL); | ||
| 1337 | if (!qmc->bd_table) { | ||
| 1338 | dev_err(qmc->dev, "Failed to allocate bd table\n"); | ||
| 1339 | ret = -ENOMEM; | ||
| 1340 | goto err_tsa_serial_disconnect; | ||
| 1341 | } | ||
| 1342 | memset(qmc->bd_table, 0, qmc->bd_size); | ||
| 1343 | |||
| 1344 | qmc_write32(qmc->scc_pram + QMC_GBL_MCBASE, qmc->bd_dma_addr); | ||
| 1345 | |||
| 1346 | /* Allocate the interrupt table */ | ||
| 1347 | qmc->int_size = QMC_NB_INTS * sizeof(u16); | ||
| 1348 | qmc->int_table = dmam_alloc_coherent(qmc->dev, qmc->int_size, | ||
| 1349 | &qmc->int_dma_addr, GFP_KERNEL); | ||
| 1350 | if (!qmc->int_table) { | ||
| 1351 | dev_err(qmc->dev, "Failed to allocate interrupt table\n"); | ||
| 1352 | ret = -ENOMEM; | ||
| 1353 | goto err_tsa_serial_disconnect; | ||
| 1354 | } | ||
| 1355 | memset(qmc->int_table, 0, qmc->int_size); | ||
| 1356 | |||
| 1357 | qmc->int_curr = qmc->int_table; | ||
| 1358 | qmc_write32(qmc->scc_pram + QMC_GBL_INTBASE, qmc->int_dma_addr); | ||
| 1359 | qmc_write32(qmc->scc_pram + QMC_GBL_INTPTR, qmc->int_dma_addr); | ||
| 1360 | |||
| 1361 | /* Set MRBLR (valid for HDLC only) max MRU + max CRC */ | ||
| 1362 | qmc_write16(qmc->scc_pram + QMC_GBL_MRBLR, HDLC_MAX_MRU + 4); | ||
| 1363 | |||
| 1364 | qmc_write16(qmc->scc_pram + QMC_GBL_GRFTHR, 1); | ||
| 1365 | qmc_write16(qmc->scc_pram + QMC_GBL_GRFCNT, 1); | ||
| 1366 | |||
| 1367 | qmc_write32(qmc->scc_pram + QMC_GBL_C_MASK32, 0xDEBB20E3); | ||
| 1368 | qmc_write16(qmc->scc_pram + QMC_GBL_C_MASK16, 0xF0B8); | ||
| 1369 | |||
| 1370 | ret = qmc_setup_tsa(qmc); | ||
| 1371 | if (ret) | ||
| 1372 | goto err_tsa_serial_disconnect; | ||
| 1373 | |||
| 1374 | qmc_write16(qmc->scc_pram + QMC_GBL_QMCSTATE, 0x8000); | ||
| 1375 | |||
| 1376 | ret = qmc_setup_chans(qmc); | ||
| 1377 | if (ret) | ||
| 1378 | goto err_tsa_serial_disconnect; | ||
| 1379 | |||
| 1380 | /* Init interrupts table */ | ||
| 1381 | ret = qmc_setup_ints(qmc); | ||
| 1382 | if (ret) | ||
| 1383 | goto err_tsa_serial_disconnect; | ||
| 1384 | |||
| 1385 | /* Disable and clear interrupts, set the irq handler */ | ||
| 1386 | qmc_write16(qmc->scc_regs + SCC_SCCM, 0x0000); | ||
| 1387 | qmc_write16(qmc->scc_regs + SCC_SCCE, 0x000F); | ||
| 1388 | irq = platform_get_irq(pdev, 0); | ||
| 1389 | if (irq < 0) | ||
| 1390 | goto err_tsa_serial_disconnect; | ||
| 1391 | ret = devm_request_irq(qmc->dev, irq, qmc_irq_handler, 0, "qmc", qmc); | ||
| 1392 | if (ret < 0) | ||
| 1393 | goto err_tsa_serial_disconnect; | ||
| 1394 | |||
| 1395 | /* Enable interrupts */ | ||
| 1396 | qmc_write16(qmc->scc_regs + SCC_SCCM, | ||
| 1397 | SCC_SCCE_IQOV | SCC_SCCE_GINT | SCC_SCCE_GUN | SCC_SCCE_GOV); | ||
| 1398 | |||
| 1399 | ret = qmc_finalize_chans(qmc); | ||
| 1400 | if (ret < 0) | ||
| 1401 | goto err_disable_intr; | ||
| 1402 | |||
| 1403 | /* Enable transmiter and receiver */ | ||
| 1404 | qmc_setbits32(qmc->scc_regs + SCC_GSMRL, SCC_GSMRL_ENR | SCC_GSMRL_ENT); | ||
| 1405 | |||
| 1406 | platform_set_drvdata(pdev, qmc); | ||
| 1407 | |||
| 1408 | return 0; | ||
| 1409 | |||
| 1410 | err_disable_intr: | ||
| 1411 | qmc_write16(qmc->scc_regs + SCC_SCCM, 0); | ||
| 1412 | |||
| 1413 | err_tsa_serial_disconnect: | ||
| 1414 | tsa_serial_disconnect(qmc->tsa_serial); | ||
| 1415 | return ret; | ||
| 1416 | } | ||
| 1417 | |||
| 1418 | static int qmc_remove(struct platform_device *pdev) | ||
| 1419 | { | ||
| 1420 | struct qmc *qmc = platform_get_drvdata(pdev); | ||
| 1421 | |||
| 1422 | /* Disable transmiter and receiver */ | ||
| 1423 | qmc_setbits32(qmc->scc_regs + SCC_GSMRL, 0); | ||
| 1424 | |||
| 1425 | /* Disable interrupts */ | ||
| 1426 | qmc_write16(qmc->scc_regs + SCC_SCCM, 0); | ||
| 1427 | |||
| 1428 | /* Disconnect the serial from TSA */ | ||
| 1429 | tsa_serial_disconnect(qmc->tsa_serial); | ||
| 1430 | |||
| 1431 | return 0; | ||
| 1432 | } | ||
| 1433 | |||
| 1434 | static const struct of_device_id qmc_id_table[] = { | ||
| 1435 | { .compatible = "fsl,cpm1-scc-qmc" }, | ||
| 1436 | {} /* sentinel */ | ||
| 1437 | }; | ||
| 1438 | MODULE_DEVICE_TABLE(of, qmc_id_table); | ||
| 1439 | |||
| 1440 | static struct platform_driver qmc_driver = { | ||
| 1441 | .driver = { | ||
| 1442 | .name = "fsl-qmc", | ||
| 1443 | .of_match_table = of_match_ptr(qmc_id_table), | ||
| 1444 | }, | ||
| 1445 | .probe = qmc_probe, | ||
| 1446 | .remove = qmc_remove, | ||
| 1447 | }; | ||
| 1448 | module_platform_driver(qmc_driver); | ||
| 1449 | |||
| 1450 | struct qmc_chan *qmc_chan_get_byphandle(struct device_node *np, const char *phandle_name) | ||
| 1451 | { | ||
| 1452 | struct of_phandle_args out_args; | ||
| 1453 | struct platform_device *pdev; | ||
| 1454 | struct qmc_chan *qmc_chan; | ||
| 1455 | struct qmc *qmc; | ||
| 1456 | int ret; | ||
| 1457 | |||
| 1458 | ret = of_parse_phandle_with_fixed_args(np, phandle_name, 1, 0, | ||
| 1459 | &out_args); | ||
| 1460 | if (ret < 0) | ||
| 1461 | return ERR_PTR(ret); | ||
| 1462 | |||
| 1463 | if (!of_match_node(qmc_driver.driver.of_match_table, out_args.np)) { | ||
| 1464 | of_node_put(out_args.np); | ||
| 1465 | return ERR_PTR(-EINVAL); | ||
| 1466 | } | ||
| 1467 | |||
| 1468 | pdev = of_find_device_by_node(out_args.np); | ||
| 1469 | of_node_put(out_args.np); | ||
| 1470 | if (!pdev) | ||
| 1471 | return ERR_PTR(-ENODEV); | ||
| 1472 | |||
| 1473 | qmc = platform_get_drvdata(pdev); | ||
| 1474 | if (!qmc) { | ||
| 1475 | platform_device_put(pdev); | ||
| 1476 | return ERR_PTR(-EPROBE_DEFER); | ||
| 1477 | } | ||
| 1478 | |||
| 1479 | if (out_args.args_count != 1) { | ||
| 1480 | platform_device_put(pdev); | ||
| 1481 | return ERR_PTR(-EINVAL); | ||
| 1482 | } | ||
| 1483 | |||
| 1484 | if (out_args.args[0] >= ARRAY_SIZE(qmc->chans)) { | ||
| 1485 | platform_device_put(pdev); | ||
| 1486 | return ERR_PTR(-EINVAL); | ||
| 1487 | } | ||
| 1488 | |||
| 1489 | qmc_chan = qmc->chans[out_args.args[0]]; | ||
| 1490 | if (!qmc_chan) { | ||
| 1491 | platform_device_put(pdev); | ||
| 1492 | return ERR_PTR(-ENOENT); | ||
| 1493 | } | ||
| 1494 | |||
| 1495 | return qmc_chan; | ||
| 1496 | } | ||
| 1497 | EXPORT_SYMBOL(qmc_chan_get_byphandle); | ||
| 1498 | |||
| 1499 | void qmc_chan_put(struct qmc_chan *chan) | ||
| 1500 | { | ||
| 1501 | put_device(chan->qmc->dev); | ||
| 1502 | } | ||
| 1503 | EXPORT_SYMBOL(qmc_chan_put); | ||
| 1504 | |||
| 1505 | static void devm_qmc_chan_release(struct device *dev, void *res) | ||
| 1506 | { | ||
| 1507 | struct qmc_chan **qmc_chan = res; | ||
| 1508 | |||
| 1509 | qmc_chan_put(*qmc_chan); | ||
| 1510 | } | ||
| 1511 | |||
| 1512 | struct qmc_chan *devm_qmc_chan_get_byphandle(struct device *dev, | ||
| 1513 | struct device_node *np, | ||
| 1514 | const char *phandle_name) | ||
| 1515 | { | ||
| 1516 | struct qmc_chan *qmc_chan; | ||
| 1517 | struct qmc_chan **dr; | ||
| 1518 | |||
| 1519 | dr = devres_alloc(devm_qmc_chan_release, sizeof(*dr), GFP_KERNEL); | ||
| 1520 | if (!dr) | ||
| 1521 | return ERR_PTR(-ENOMEM); | ||
| 1522 | |||
| 1523 | qmc_chan = qmc_chan_get_byphandle(np, phandle_name); | ||
| 1524 | if (!IS_ERR(qmc_chan)) { | ||
| 1525 | *dr = qmc_chan; | ||
| 1526 | devres_add(dev, dr); | ||
| 1527 | } else { | ||
| 1528 | devres_free(dr); | ||
| 1529 | } | ||
| 1530 | |||
| 1531 | return qmc_chan; | ||
| 1532 | } | ||
| 1533 | EXPORT_SYMBOL(devm_qmc_chan_get_byphandle); | ||
| 1534 | |||
| 1535 | MODULE_AUTHOR("Herve Codina <herve.codina@bootlin.com>"); | ||
| 1536 | MODULE_DESCRIPTION("CPM QMC driver"); | ||
| 1537 | MODULE_LICENSE("GPL"); | ||
| @@ -0,0 +1,846 @@ | |||
| 1 | // SPDX-License-Identifier: GPL-2.0 | ||
| 2 | /* | ||
| 3 | * TSA driver | ||
| 4 | * | ||
| 5 | * Copyright 2022 CS GROUP France | ||
| 6 | * | ||
| 7 | * Author: Herve Codina <herve.codina@bootlin.com> | ||
| 8 | */ | ||
| 9 | |||
| 10 | #include "tsa.h" | ||
| 11 | #include <dt-bindings/soc/cpm1-fsl,tsa.h> | ||
| 12 | #include <linux/clk.h> | ||
| 13 | #include <linux/io.h> | ||
| 14 | #include <linux/module.h> | ||
| 15 | #include <linux/of.h> | ||
| 16 | #include <linux/of_platform.h> | ||
| 17 | #include <linux/platform_device.h> | ||
| 18 | #include <linux/slab.h> | ||
| 19 | |||
| 20 | |||
| 21 | /* TSA SI RAM routing tables entry */ | ||
| 22 | #define TSA_SIRAM_ENTRY_LAST (1 << 16) | ||
| 23 | #define TSA_SIRAM_ENTRY_BYTE (1 << 17) | ||
| 24 | #define TSA_SIRAM_ENTRY_CNT(x) (((x) & 0x0f) << 18) | ||
| 25 | #define TSA_SIRAM_ENTRY_CSEL_MASK (0x7 << 22) | ||
| 26 | #define TSA_SIRAM_ENTRY_CSEL_NU (0x0 << 22) | ||
| 27 | #define TSA_SIRAM_ENTRY_CSEL_SCC2 (0x2 << 22) | ||
| 28 | #define TSA_SIRAM_ENTRY_CSEL_SCC3 (0x3 << 22) | ||
| 29 | #define TSA_SIRAM_ENTRY_CSEL_SCC4 (0x4 << 22) | ||
| 30 | #define TSA_SIRAM_ENTRY_CSEL_SMC1 (0x5 << 22) | ||
| 31 | #define TSA_SIRAM_ENTRY_CSEL_SMC2 (0x6 << 22) | ||
| 32 | |||
| 33 | /* SI mode register (32 bits) */ | ||
| 34 | #define TSA_SIMODE 0x00 | ||
| 35 | #define TSA_SIMODE_SMC2 0x80000000 | ||
| 36 | #define TSA_SIMODE_SMC1 0x00008000 | ||
| 37 | #define TSA_SIMODE_TDMA(x) ((x) << 0) | ||
| 38 | #define TSA_SIMODE_TDMB(x) ((x) << 16) | ||
| 39 | #define TSA_SIMODE_TDM_MASK 0x0fff | ||
| 40 | #define TSA_SIMODE_TDM_SDM_MASK 0x0c00 | ||
| 41 | #define TSA_SIMODE_TDM_SDM_NORM 0x0000 | ||
| 42 | #define TSA_SIMODE_TDM_SDM_ECHO 0x0400 | ||
| 43 | #define TSA_SIMODE_TDM_SDM_INTL_LOOP 0x0800 | ||
| 44 | #define TSA_SIMODE_TDM_SDM_LOOP_CTRL 0x0c00 | ||
| 45 | #define TSA_SIMODE_TDM_RFSD(x) ((x) << 8) | ||
| 46 | #define TSA_SIMODE_TDM_DSC 0x0080 | ||
| 47 | #define TSA_SIMODE_TDM_CRT 0x0040 | ||
| 48 | #define TSA_SIMODE_TDM_STZ 0x0020 | ||
| 49 | #define TSA_SIMODE_TDM_CE 0x0010 | ||
| 50 | #define TSA_SIMODE_TDM_FE 0x0008 | ||
| 51 | #define TSA_SIMODE_TDM_GM 0x0004 | ||
| 52 | #define TSA_SIMODE_TDM_TFSD(x) ((x) << 0) | ||
| 53 | |||
| 54 | /* SI global mode register (8 bits) */ | ||
| 55 | #define TSA_SIGMR 0x04 | ||
| 56 | #define TSA_SIGMR_ENB (1<<3) | ||
| 57 | #define TSA_SIGMR_ENA (1<<2) | ||
| 58 | #define TSA_SIGMR_RDM_MASK 0x03 | ||
| 59 | #define TSA_SIGMR_RDM_STATIC_TDMA 0x00 | ||
| 60 | #define TSA_SIGMR_RDM_DYN_TDMA 0x01 | ||
| 61 | #define TSA_SIGMR_RDM_STATIC_TDMAB 0x02 | ||
| 62 | #define TSA_SIGMR_RDM_DYN_TDMAB 0x03 | ||
| 63 | |||
| 64 | /* SI status register (8 bits) */ | ||
| 65 | #define TSA_SISTR 0x06 | ||
| 66 | |||
| 67 | /* SI command register (8 bits) */ | ||
| 68 | #define TSA_SICMR 0x07 | ||
| 69 | |||
| 70 | /* SI clock route register (32 bits) */ | ||
| 71 | #define TSA_SICR 0x0C | ||
| 72 | #define TSA_SICR_SCC2(x) ((x) << 8) | ||
| 73 | #define TSA_SICR_SCC3(x) ((x) << 16) | ||
| 74 | #define TSA_SICR_SCC4(x) ((x) << 24) | ||
| 75 | #define TSA_SICR_SCC_MASK 0x0ff | ||
| 76 | #define TSA_SICR_SCC_GRX (1 << 7) | ||
| 77 | #define TSA_SICR_SCC_SCX_TSA (1 << 6) | ||
| 78 | #define TSA_SICR_SCC_RXCS_MASK (0x7 << 3) | ||
| 79 | #define TSA_SICR_SCC_RXCS_BRG1 (0x0 << 3) | ||
| 80 | #define TSA_SICR_SCC_RXCS_BRG2 (0x1 << 3) | ||
| 81 | #define TSA_SICR_SCC_RXCS_BRG3 (0x2 << 3) | ||
| 82 | #define TSA_SICR_SCC_RXCS_BRG4 (0x3 << 3) | ||
| 83 | #define TSA_SICR_SCC_RXCS_CLK15 (0x4 << 3) | ||
| 84 | #define TSA_SICR_SCC_RXCS_CLK26 (0x5 << 3) | ||
| 85 | #define TSA_SICR_SCC_RXCS_CLK37 (0x6 << 3) | ||
| 86 | #define TSA_SICR_SCC_RXCS_CLK48 (0x7 << 3) | ||
| 87 | #define TSA_SICR_SCC_TXCS_MASK (0x7 << 0) | ||
| 88 | #define TSA_SICR_SCC_TXCS_BRG1 (0x0 << 0) | ||
| 89 | #define TSA_SICR_SCC_TXCS_BRG2 (0x1 << 0) | ||
| 90 | #define TSA_SICR_SCC_TXCS_BRG3 (0x2 << 0) | ||
| 91 | #define TSA_SICR_SCC_TXCS_BRG4 (0x3 << 0) | ||
| 92 | #define TSA_SICR_SCC_TXCS_CLK15 (0x4 << 0) | ||
| 93 | #define TSA_SICR_SCC_TXCS_CLK26 (0x5 << 0) | ||
| 94 | #define TSA_SICR_SCC_TXCS_CLK37 (0x6 << 0) | ||
| 95 | #define TSA_SICR_SCC_TXCS_CLK48 (0x7 << 0) | ||
| 96 | |||
| 97 | /* Serial interface RAM pointer register (32 bits) */ | ||
| 98 | #define TSA_SIRP 0x10 | ||
| 99 | |||
| 100 | struct tsa_entries_area { | ||
| 101 | void *__iomem entries_start; | ||
| 102 | void *__iomem entries_next; | ||
| 103 | void *__iomem last_entry; | ||
| 104 | }; | ||
| 105 | |||
| 106 | struct tsa_tdm { | ||
| 107 | bool is_enable; | ||
| 108 | struct clk *l1rclk_clk; | ||
| 109 | struct clk *l1rsync_clk; | ||
| 110 | struct clk *l1tclk_clk; | ||
| 111 | struct clk *l1tsync_clk; | ||
| 112 | u32 simode_tdm; | ||
| 113 | }; | ||
| 114 | |||
| 115 | #define TSA_TDMA 0 | ||
| 116 | #define TSA_TDMB 1 | ||
| 117 | |||
| 118 | struct tsa { | ||
| 119 | struct device *dev; | ||
| 120 | void *__iomem si_regs; | ||
| 121 | void *__iomem si_ram; | ||
| 122 | resource_size_t si_ram_sz; | ||
| 123 | spinlock_t lock; | ||
| 124 | int tdms; /* TSA_TDMx ORed */ | ||
| 125 | struct tsa_tdm tdm[2]; /* TDMa and TDMb */ | ||
| 126 | struct tsa_serial { | ||
| 127 | unsigned int id; | ||
| 128 | struct tsa_serial_info info; | ||
| 129 | } serials[6]; | ||
| 130 | }; | ||
| 131 | |||
| 132 | static inline struct tsa *tsa_serial_get_tsa(struct tsa_serial *tsa_serial) | ||
| 133 | { | ||
| 134 | /* The serials table is indexed by the serial id */ | ||
| 135 | return container_of(tsa_serial, struct tsa, serials[tsa_serial->id]); | ||
| 136 | } | ||
| 137 | |||
| 138 | static inline void tsa_write32(void *__iomem addr, u32 val) | ||
| 139 | { | ||
| 140 | iowrite32be(val, addr); | ||
| 141 | } | ||
| 142 | |||
| 143 | static inline void tsa_write8(void *__iomem addr, u32 val) | ||
| 144 | { | ||
| 145 | iowrite8(val, addr); | ||
| 146 | } | ||
| 147 | |||
| 148 | static inline u32 tsa_read32(void *__iomem addr) | ||
| 149 | { | ||
| 150 | return ioread32be(addr); | ||
| 151 | } | ||
| 152 | |||
| 153 | static inline void tsa_clrbits32(void *__iomem addr, u32 clr) | ||
| 154 | { | ||
| 155 | tsa_write32(addr, tsa_read32(addr) & ~clr); | ||
| 156 | } | ||
| 157 | |||
| 158 | static inline void tsa_clrsetbits32(void *__iomem addr, u32 clr, u32 set) | ||
| 159 | { | ||
| 160 | tsa_write32(addr, (tsa_read32(addr) & ~clr) | set); | ||
| 161 | } | ||
| 162 | |||
| 163 | int tsa_serial_connect(struct tsa_serial *tsa_serial) | ||
| 164 | { | ||
| 165 | struct tsa *tsa = tsa_serial_get_tsa(tsa_serial); | ||
| 166 | unsigned long flags; | ||
| 167 | u32 clear; | ||
| 168 | u32 set; | ||
| 169 | |||
| 170 | switch (tsa_serial->id) { | ||
| 171 | case FSL_CPM_TSA_SCC2: | ||
| 172 | clear = TSA_SICR_SCC2(TSA_SICR_SCC_MASK); | ||
| 173 | set = TSA_SICR_SCC2(TSA_SICR_SCC_SCX_TSA); | ||
| 174 | break; | ||
| 175 | case FSL_CPM_TSA_SCC3: | ||
| 176 | clear = TSA_SICR_SCC3(TSA_SICR_SCC_MASK); | ||
| 177 | set = TSA_SICR_SCC3(TSA_SICR_SCC_SCX_TSA); | ||
| 178 | break; | ||
| 179 | case FSL_CPM_TSA_SCC4: | ||
| 180 | clear = TSA_SICR_SCC4(TSA_SICR_SCC_MASK); | ||
| 181 | set = TSA_SICR_SCC4(TSA_SICR_SCC_SCX_TSA); | ||
| 182 | break; | ||
| 183 | default: | ||
| 184 | dev_err(tsa->dev, "Unsupported serial id %u\n", tsa_serial->id); | ||
| 185 | return -EINVAL; | ||
| 186 | } | ||
| 187 | |||
| 188 | spin_lock_irqsave(&tsa->lock, flags); | ||
| 189 | tsa_clrsetbits32(tsa->si_regs + TSA_SICR, clear, set); | ||
| 190 | spin_unlock_irqrestore(&tsa->lock, flags); | ||
| 191 | |||
| 192 | return 0; | ||
| 193 | } | ||
| 194 | EXPORT_SYMBOL(tsa_serial_connect); | ||
| 195 | |||
| 196 | int tsa_serial_disconnect(struct tsa_serial *tsa_serial) | ||
| 197 | { | ||
| 198 | struct tsa *tsa = tsa_serial_get_tsa(tsa_serial); | ||
| 199 | unsigned long flags; | ||
| 200 | u32 clear; | ||
| 201 | |||
| 202 | switch (tsa_serial->id) { | ||
| 203 | case FSL_CPM_TSA_SCC2: | ||
| 204 | clear = TSA_SICR_SCC2(TSA_SICR_SCC_MASK); | ||
| 205 | break; | ||
| 206 | case FSL_CPM_TSA_SCC3: | ||
| 207 | clear = TSA_SICR_SCC3(TSA_SICR_SCC_MASK); | ||
| 208 | break; | ||
| 209 | case FSL_CPM_TSA_SCC4: | ||
| 210 | clear = TSA_SICR_SCC4(TSA_SICR_SCC_MASK); | ||
| 211 | break; | ||
| 212 | default: | ||
| 213 | dev_err(tsa->dev, "Unsupported serial id %u\n", tsa_serial->id); | ||
| 214 | return -EINVAL; | ||
| 215 | } | ||
| 216 | |||
| 217 | spin_lock_irqsave(&tsa->lock, flags); | ||
| 218 | tsa_clrsetbits32(tsa->si_regs + TSA_SICR, clear, 0); | ||
| 219 | spin_unlock_irqrestore(&tsa->lock, flags); | ||
| 220 | |||
| 221 | return 0; | ||
| 222 | } | ||
| 223 | EXPORT_SYMBOL(tsa_serial_disconnect); | ||
| 224 | |||
| 225 | int tsa_serial_get_info(struct tsa_serial *tsa_serial, struct tsa_serial_info *info) | ||
| 226 | { | ||
| 227 | memcpy(info, &tsa_serial->info, sizeof(*info)); | ||
| 228 | return 0; | ||
| 229 | } | ||
| 230 | EXPORT_SYMBOL(tsa_serial_get_info); | ||
| 231 | |||
| 232 | static void tsa_init_entries_area(struct tsa *tsa, struct tsa_entries_area *area, | ||
| 233 | u32 tdms, u32 tdm_id, bool is_rx) | ||
| 234 | { | ||
| 235 | resource_size_t quarter; | ||
| 236 | resource_size_t half; | ||
| 237 | |||
| 238 | quarter = tsa->si_ram_sz/4; | ||
| 239 | half = tsa->si_ram_sz/2; | ||
| 240 | |||
| 241 | if (tdms == BIT(TSA_TDMA)) { | ||
| 242 | /* Only TDMA */ | ||
| 243 | if (is_rx) { | ||
| 244 | /* First half of si_ram */ | ||
| 245 | area->entries_start = tsa->si_ram; | ||
| 246 | area->entries_next = area->entries_start + half; | ||
| 247 | area->last_entry = NULL; | ||
| 248 | } else { | ||
| 249 | /* Second half of si_ram */ | ||
| 250 | area->entries_start = tsa->si_ram + half; | ||
| 251 | area->entries_next = area->entries_start + half; | ||
| 252 | area->last_entry = NULL; | ||
| 253 | } | ||
| 254 | } else { | ||
| 255 | /* Only TDMB or both TDMs */ | ||
| 256 | if (tdm_id == TSA_TDMA) { | ||
| 257 | if (is_rx) { | ||
| 258 | /* First half of first half of si_ram */ | ||
| 259 | area->entries_start = tsa->si_ram; | ||
| 260 | area->entries_next = area->entries_start + quarter; | ||
| 261 | area->last_entry = NULL; | ||
| 262 | } else { | ||
| 263 | /* First half of second half of si_ram */ | ||
| 264 | area->entries_start = tsa->si_ram + (2 * quarter); | ||
| 265 | area->entries_next = area->entries_start + quarter; | ||
| 266 | area->last_entry = NULL; | ||
| 267 | } | ||
| 268 | } else { | ||
| 269 | if (is_rx) { | ||
| 270 | /* Second half of first half of si_ram */ | ||
| 271 | area->entries_start = tsa->si_ram + quarter; | ||
| 272 | area->entries_next = area->entries_start + quarter; | ||
| 273 | area->last_entry = NULL; | ||
| 274 | } else { | ||
| 275 | /* Second half of second half of si_ram */ | ||
| 276 | area->entries_start = tsa->si_ram + (3 * quarter); | ||
| 277 | area->entries_next = area->entries_start + quarter; | ||
| 278 | area->last_entry = NULL; | ||
| 279 | } | ||
| 280 | } | ||
| 281 | } | ||
| 282 | } | ||
| 283 | |||
| 284 | static const char *tsa_serial_id2name(struct tsa *tsa, u32 serial_id) | ||
| 285 | { | ||
| 286 | switch (serial_id) { | ||
| 287 | case FSL_CPM_TSA_NU: return "Not used"; | ||
| 288 | case FSL_CPM_TSA_SCC2: return "SCC2"; | ||
| 289 | case FSL_CPM_TSA_SCC3: return "SCC3"; | ||
| 290 | case FSL_CPM_TSA_SCC4: return "SCC4"; | ||
| 291 | case FSL_CPM_TSA_SMC1: return "SMC1"; | ||
| 292 | case FSL_CPM_TSA_SMC2: return "SMC2"; | ||
| 293 | default: | ||
| 294 | break; | ||
| 295 | } | ||
| 296 | return NULL; | ||
| 297 | } | ||
| 298 | |||
| 299 | static u32 tsa_serial_id2csel(struct tsa *tsa, u32 serial_id) | ||
| 300 | { | ||
| 301 | switch (serial_id) { | ||
| 302 | case FSL_CPM_TSA_SCC2: return TSA_SIRAM_ENTRY_CSEL_SCC2; | ||
| 303 | case FSL_CPM_TSA_SCC3: return TSA_SIRAM_ENTRY_CSEL_SCC3; | ||
| 304 | case FSL_CPM_TSA_SCC4: return TSA_SIRAM_ENTRY_CSEL_SCC4; | ||
| 305 | case FSL_CPM_TSA_SMC1: return TSA_SIRAM_ENTRY_CSEL_SMC1; | ||
| 306 | case FSL_CPM_TSA_SMC2: return TSA_SIRAM_ENTRY_CSEL_SMC2; | ||
| 307 | default: | ||
| 308 | break; | ||
| 309 | } | ||
| 310 | return TSA_SIRAM_ENTRY_CSEL_NU; | ||
| 311 | } | ||
| 312 | |||
| 313 | static int tsa_add_entry(struct tsa *tsa, struct tsa_entries_area *area, | ||
| 314 | u32 count, u32 serial_id) | ||
| 315 | { | ||
| 316 | void *__iomem addr; | ||
| 317 | u32 left; | ||
| 318 | u32 val; | ||
| 319 | u32 cnt; | ||
| 320 | u32 nb; | ||
| 321 | |||
| 322 | addr = area->last_entry ? area->last_entry + 4 : area->entries_start; | ||
| 323 | |||
| 324 | nb = DIV_ROUND_UP(count, 8); | ||
| 325 | if ((addr + (nb * 4)) > area->entries_next) { | ||
| 326 | dev_err(tsa->dev, "si ram area full\n"); | ||
| 327 | return -ENOSPC; | ||
| 328 | } | ||
| 329 | |||
| 330 | if (area->last_entry) { | ||
| 331 | /* Clear last flag */ | ||
| 332 | tsa_clrbits32(area->last_entry, TSA_SIRAM_ENTRY_LAST); | ||
| 333 | } | ||
| 334 | |||
| 335 | left = count; | ||
| 336 | while (left) { | ||
| 337 | val = TSA_SIRAM_ENTRY_BYTE | tsa_serial_id2csel(tsa, serial_id); | ||
| 338 | |||
| 339 | if (left > 16) { | ||
| 340 | cnt = 16; | ||
| 341 | } else { | ||
| 342 | cnt = left; | ||
| 343 | val |= TSA_SIRAM_ENTRY_LAST; | ||
| 344 | area->last_entry = addr; | ||
| 345 | } | ||
| 346 | val |= TSA_SIRAM_ENTRY_CNT(cnt - 1); | ||
| 347 | |||
| 348 | tsa_write32(addr, val); | ||
| 349 | addr += 4; | ||
| 350 | left -= cnt; | ||
| 351 | } | ||
| 352 | |||
| 353 | return 0; | ||
| 354 | } | ||
| 355 | |||
| 356 | static int tsa_of_parse_tdm_route(struct tsa *tsa, struct device_node *tdm_np, | ||
| 357 | u32 tdms, u32 tdm_id, bool is_rx) | ||
| 358 | { | ||
| 359 | struct tsa_entries_area area; | ||
| 360 | const char *route_name; | ||
| 361 | u32 serial_id; | ||
| 362 | int len, i; | ||
| 363 | u32 count; | ||
| 364 | const char *serial_name; | ||
| 365 | struct tsa_serial_info *serial_info; | ||
| 366 | struct tsa_tdm *tdm; | ||
| 367 | int ret; | ||
| 368 | u32 ts; | ||
| 369 | |||
| 370 | route_name = is_rx ? "fsl,rx-ts-routes" : "fsl,tx-ts-routes"; | ||
| 371 | |||
| 372 | len = of_property_count_u32_elems(tdm_np, route_name); | ||
| 373 | if (len < 0) { | ||
| 374 | dev_err(tsa->dev, "%pOF: failed to read %s\n", tdm_np, route_name); | ||
| 375 | return len; | ||
| 376 | } | ||
| 377 | if (len % 2 != 0) { | ||
| 378 | dev_err(tsa->dev, "%pOF: wrong %s format\n", tdm_np, route_name); | ||
| 379 | return -EINVAL; | ||
| 380 | } | ||
| 381 | |||
| 382 | tsa_init_entries_area(tsa, &area, tdms, tdm_id, is_rx); | ||
| 383 | ts = 0; | ||
| 384 | for (i = 0; i < len; i += 2) { | ||
| 385 | of_property_read_u32_index(tdm_np, route_name, i, &count); | ||
| 386 | of_property_read_u32_index(tdm_np, route_name, i + 1, &serial_id); | ||
| 387 | |||
| 388 | if (serial_id >= ARRAY_SIZE(tsa->serials)) { | ||
| 389 | dev_err(tsa->dev, "%pOF: invalid serial id (%u)\n", | ||
| 390 | tdm_np, serial_id); | ||
| 391 | return -EINVAL; | ||
| 392 | } | ||
| 393 | |||
| 394 | serial_name = tsa_serial_id2name(tsa, serial_id); | ||
| 395 | if (!serial_name) { | ||
| 396 | dev_err(tsa->dev, "%pOF: unsupported serial id (%u)\n", | ||
| 397 | tdm_np, serial_id); | ||
| 398 | return -EINVAL; | ||
| 399 | } | ||
| 400 | |||
| 401 | dev_dbg(tsa->dev, "tdm_id=%u, %s ts %u..%u -> %s\n", | ||
| 402 | tdm_id, route_name, ts, ts+count-1, serial_name); | ||
| 403 | ts += count; | ||
| 404 | |||
| 405 | ret = tsa_add_entry(tsa, &area, count, serial_id); | ||
| 406 | if (ret) | ||
| 407 | return ret; | ||
| 408 | |||
| 409 | serial_info = &tsa->serials[serial_id].info; | ||
| 410 | tdm = &tsa->tdm[tdm_id]; | ||
| 411 | if (is_rx) { | ||
| 412 | serial_info->rx_fs_rate = clk_get_rate(tdm->l1rsync_clk); | ||
| 413 | serial_info->rx_bit_rate = clk_get_rate(tdm->l1rclk_clk); | ||
| 414 | serial_info->nb_rx_ts += count; | ||
| 415 | } else { | ||
| 416 | serial_info->tx_fs_rate = tdm->l1tsync_clk ? | ||
| 417 | clk_get_rate(tdm->l1tsync_clk) : | ||
| 418 | clk_get_rate(tdm->l1rsync_clk); | ||
| 419 | serial_info->tx_bit_rate = tdm->l1tclk_clk ? | ||
| 420 | clk_get_rate(tdm->l1tclk_clk) : | ||
| 421 | clk_get_rate(tdm->l1rclk_clk); | ||
| 422 | serial_info->nb_tx_ts += count; | ||
| 423 | } | ||
| 424 | } | ||
| 425 | return 0; | ||
| 426 | } | ||
| 427 | |||
| 428 | static inline int tsa_of_parse_tdm_rx_route(struct tsa *tsa, | ||
| 429 | struct device_node *tdm_np, | ||
| 430 | u32 tdms, u32 tdm_id) | ||
| 431 | { | ||
| 432 | return tsa_of_parse_tdm_route(tsa, tdm_np, tdms, tdm_id, true); | ||
| 433 | } | ||
| 434 | |||
| 435 | static inline int tsa_of_parse_tdm_tx_route(struct tsa *tsa, | ||
| 436 | struct device_node *tdm_np, | ||
| 437 | u32 tdms, u32 tdm_id) | ||
| 438 | { | ||
| 439 | return tsa_of_parse_tdm_route(tsa, tdm_np, tdms, tdm_id, false); | ||
| 440 | } | ||
| 441 | |||
| 442 | static int tsa_of_parse_tdms(struct tsa *tsa, struct device_node *np) | ||
| 443 | { | ||
| 444 | struct device_node *tdm_np; | ||
| 445 | struct tsa_tdm *tdm; | ||
| 446 | struct clk *clk; | ||
| 447 | u32 tdm_id, val; | ||
| 448 | int ret; | ||
| 449 | int i; | ||
| 450 | |||
| 451 | tsa->tdms = 0; | ||
| 452 | tsa->tdm[0].is_enable = false; | ||
| 453 | tsa->tdm[1].is_enable = false; | ||
| 454 | |||
| 455 | for_each_available_child_of_node(np, tdm_np) { | ||
| 456 | ret = of_property_read_u32(tdm_np, "reg", &tdm_id); | ||
| 457 | if (ret) { | ||
| 458 | dev_err(tsa->dev, "%pOF: failed to read reg\n", tdm_np); | ||
| 459 | of_node_put(tdm_np); | ||
| 460 | return ret; | ||
| 461 | } | ||
| 462 | switch (tdm_id) { | ||
| 463 | case 0: | ||
| 464 | tsa->tdms |= BIT(TSA_TDMA); | ||
| 465 | break; | ||
| 466 | case 1: | ||
| 467 | tsa->tdms |= BIT(TSA_TDMB); | ||
| 468 | break; | ||
| 469 | default: | ||
| 470 | dev_err(tsa->dev, "%pOF: Invalid tdm_id (%u)\n", tdm_np, | ||
| 471 | tdm_id); | ||
| 472 | of_node_put(tdm_np); | ||
| 473 | return -EINVAL; | ||
| 474 | } | ||
| 475 | } | ||
| 476 | |||
| 477 | for_each_available_child_of_node(np, tdm_np) { | ||
| 478 | ret = of_property_read_u32(tdm_np, "reg", &tdm_id); | ||
| 479 | if (ret) { | ||
| 480 | dev_err(tsa->dev, "%pOF: failed to read reg\n", tdm_np); | ||
| 481 | of_node_put(tdm_np); | ||
| 482 | return ret; | ||
| 483 | } | ||
| 484 | |||
| 485 | tdm = &tsa->tdm[tdm_id]; | ||
| 486 | tdm->simode_tdm = TSA_SIMODE_TDM_SDM_NORM; | ||
| 487 | |||
| 488 | val = 0; | ||
| 489 | ret = of_property_read_u32(tdm_np, "fsl,rx-frame-sync-delay-bits", | ||
| 490 | &val); | ||
| 491 | if (ret && ret != -EINVAL) { | ||
| 492 | dev_err(tsa->dev, | ||
| 493 | "%pOF: failed to read fsl,rx-frame-sync-delay-bits\n", | ||
| 494 | tdm_np); | ||
| 495 | of_node_put(tdm_np); | ||
| 496 | return ret; | ||
| 497 | } | ||
| 498 | if (val > 3) { | ||
| 499 | dev_err(tsa->dev, | ||
| 500 | "%pOF: Invalid fsl,rx-frame-sync-delay-bits (%u)\n", | ||
| 501 | tdm_np, val); | ||
| 502 | of_node_put(tdm_np); | ||
| 503 | return -EINVAL; | ||
| 504 | } | ||
| 505 | tdm->simode_tdm |= TSA_SIMODE_TDM_RFSD(val); | ||
| 506 | |||
| 507 | val = 0; | ||
| 508 | ret = of_property_read_u32(tdm_np, "fsl,tx-frame-sync-delay-bits", | ||
| 509 | &val); | ||
| 510 | if (ret && ret != -EINVAL) { | ||
| 511 | dev_err(tsa->dev, | ||
| 512 | "%pOF: failed to read fsl,tx-frame-sync-delay-bits\n", | ||
| 513 | tdm_np); | ||
| 514 | of_node_put(tdm_np); | ||
| 515 | return ret; | ||
| 516 | } | ||
| 517 | if (val > 3) { | ||
| 518 | dev_err(tsa->dev, | ||
| 519 | "%pOF: Invalid fsl,tx-frame-sync-delay-bits (%u)\n", | ||
| 520 | tdm_np, val); | ||
| 521 | of_node_put(tdm_np); | ||
| 522 | return -EINVAL; | ||
| 523 | } | ||
| 524 | tdm->simode_tdm |= TSA_SIMODE_TDM_TFSD(val); | ||
| 525 | |||
| 526 | if (of_property_read_bool(tdm_np, "fsl,common-rxtx-pins")) | ||
| 527 | tdm->simode_tdm |= TSA_SIMODE_TDM_CRT; | ||
| 528 | |||
| 529 | if (of_property_read_bool(tdm_np, "fsl,clock-falling-edge")) | ||
| 530 | tdm->simode_tdm |= TSA_SIMODE_TDM_CE; | ||
| 531 | |||
| 532 | if (of_property_read_bool(tdm_np, "fsl,fsync-rising-edge")) | ||
| 533 | tdm->simode_tdm |= TSA_SIMODE_TDM_FE; | ||
| 534 | |||
| 535 | if (of_property_read_bool(tdm_np, "fsl,double-speed-clock")) | ||
| 536 | tdm->simode_tdm |= TSA_SIMODE_TDM_DSC; | ||
| 537 | |||
| 538 | clk = of_clk_get_by_name(tdm_np, "l1rsync"); | ||
| 539 | if (IS_ERR(clk)) { | ||
| 540 | ret = PTR_ERR(clk); | ||
| 541 | of_node_put(tdm_np); | ||
| 542 | goto err; | ||
| 543 | } | ||
| 544 | ret = clk_prepare_enable(clk); | ||
| 545 | if (ret) { | ||
| 546 | clk_put(clk); | ||
| 547 | of_node_put(tdm_np); | ||
| 548 | goto err; | ||
| 549 | } | ||
| 550 | tdm->l1rsync_clk = clk; | ||
| 551 | |||
| 552 | clk = of_clk_get_by_name(tdm_np, "l1rclk"); | ||
| 553 | if (IS_ERR(clk)) { | ||
| 554 | ret = PTR_ERR(clk); | ||
| 555 | of_node_put(tdm_np); | ||
| 556 | goto err; | ||
| 557 | } | ||
| 558 | ret = clk_prepare_enable(clk); | ||
| 559 | if (ret) { | ||
| 560 | clk_put(clk); | ||
| 561 | of_node_put(tdm_np); | ||
| 562 | goto err; | ||
| 563 | } | ||
| 564 | tdm->l1rclk_clk = clk; | ||
| 565 | |||
| 566 | if (!(tdm->simode_tdm & TSA_SIMODE_TDM_CRT)) { | ||
| 567 | clk = of_clk_get_by_name(tdm_np, "l1tsync"); | ||
| 568 | if (IS_ERR(clk)) { | ||
| 569 | ret = PTR_ERR(clk); | ||
| 570 | of_node_put(tdm_np); | ||
| 571 | goto err; | ||
| 572 | } | ||
| 573 | ret = clk_prepare_enable(clk); | ||
| 574 | if (ret) { | ||
| 575 | clk_put(clk); | ||
| 576 | of_node_put(tdm_np); | ||
| 577 | goto err; | ||
| 578 | } | ||
| 579 | tdm->l1tsync_clk = clk; | ||
| 580 | |||
| 581 | clk = of_clk_get_by_name(tdm_np, "l1tclk"); | ||
| 582 | if (IS_ERR(clk)) { | ||
| 583 | ret = PTR_ERR(clk); | ||
| 584 | of_node_put(tdm_np); | ||
| 585 | goto err; | ||
| 586 | } | ||
| 587 | ret = clk_prepare_enable(clk); | ||
| 588 | if (ret) { | ||
| 589 | clk_put(clk); | ||
| 590 | of_node_put(tdm_np); | ||
| 591 | goto err; | ||
| 592 | } | ||
| 593 | tdm->l1tclk_clk = clk; | ||
| 594 | } | ||
| 595 | |||
| 596 | ret = tsa_of_parse_tdm_rx_route(tsa, tdm_np, tsa->tdms, tdm_id); | ||
| 597 | if (ret) { | ||
| 598 | of_node_put(tdm_np); | ||
| 599 | goto err; | ||
| 600 | } | ||
| 601 | |||
| 602 | ret = tsa_of_parse_tdm_tx_route(tsa, tdm_np, tsa->tdms, tdm_id); | ||
| 603 | if (ret) { | ||
| 604 | of_node_put(tdm_np); | ||
| 605 | goto err; | ||
| 606 | } | ||
| 607 | |||
| 608 | tdm->is_enable = true; | ||
| 609 | } | ||
| 610 | return 0; | ||
| 611 | |||
| 612 | err: | ||
| 613 | for (i = 0; i < 2; i++) { | ||
| 614 | if (tsa->tdm[i].l1rsync_clk) { | ||
| 615 | clk_disable_unprepare(tsa->tdm[i].l1rsync_clk); | ||
| 616 | clk_put(tsa->tdm[i].l1rsync_clk); | ||
| 617 | } | ||
| 618 | if (tsa->tdm[i].l1rclk_clk) { | ||
| 619 | clk_disable_unprepare(tsa->tdm[i].l1rclk_clk); | ||
| 620 | clk_put(tsa->tdm[i].l1rclk_clk); | ||
| 621 | } | ||
| 622 | if (tsa->tdm[i].l1tsync_clk) { | ||
| 623 | clk_disable_unprepare(tsa->tdm[i].l1rsync_clk); | ||
| 624 | clk_put(tsa->tdm[i].l1rsync_clk); | ||
| 625 | } | ||
| 626 | if (tsa->tdm[i].l1tclk_clk) { | ||
| 627 | clk_disable_unprepare(tsa->tdm[i].l1rclk_clk); | ||
| 628 | clk_put(tsa->tdm[i].l1rclk_clk); | ||
| 629 | } | ||
| 630 | } | ||
| 631 | return ret; | ||
| 632 | } | ||
| 633 | |||
| 634 | static void tsa_init_si_ram(struct tsa *tsa) | ||
| 635 | { | ||
| 636 | resource_size_t i; | ||
| 637 | |||
| 638 | /* Fill all entries as the last one */ | ||
| 639 | for (i = 0; i < tsa->si_ram_sz; i += 4) | ||
| 640 | tsa_write32(tsa->si_ram + i, TSA_SIRAM_ENTRY_LAST); | ||
| 641 | } | ||
| 642 | |||
| 643 | static int tsa_probe(struct platform_device *pdev) | ||
| 644 | { | ||
| 645 | struct device_node *np = pdev->dev.of_node; | ||
| 646 | struct resource *res; | ||
| 647 | struct tsa *tsa; | ||
| 648 | unsigned int i; | ||
| 649 | u32 val; | ||
| 650 | int ret; | ||
| 651 | |||
| 652 | tsa = devm_kzalloc(&pdev->dev, sizeof(*tsa), GFP_KERNEL); | ||
| 653 | if (!tsa) | ||
| 654 | return -ENOMEM; | ||
| 655 | |||
| 656 | tsa->dev = &pdev->dev; | ||
| 657 | |||
| 658 | for (i = 0; i < ARRAY_SIZE(tsa->serials); i++) | ||
| 659 | tsa->serials[i].id = i; | ||
| 660 | |||
| 661 | spin_lock_init(&tsa->lock); | ||
| 662 | |||
| 663 | tsa->si_regs = devm_platform_ioremap_resource_byname(pdev, "si_regs"); | ||
| 664 | if (IS_ERR(tsa->si_regs)) | ||
| 665 | return PTR_ERR(tsa->si_regs); | ||
| 666 | |||
| 667 | res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "si_ram"); | ||
| 668 | if (!res) { | ||
| 669 | dev_err(tsa->dev, "si_ram resource missing\n"); | ||
| 670 | return -EINVAL; | ||
| 671 | } | ||
| 672 | tsa->si_ram_sz = resource_size(res); | ||
| 673 | tsa->si_ram = devm_ioremap_resource(&pdev->dev, res); | ||
| 674 | if (IS_ERR(tsa->si_ram)) | ||
| 675 | return PTR_ERR(tsa->si_ram); | ||
| 676 | |||
| 677 | tsa_init_si_ram(tsa); | ||
| 678 | |||
| 679 | ret = tsa_of_parse_tdms(tsa, np); | ||
| 680 | if (ret) | ||
| 681 | return ret; | ||
| 682 | |||
| 683 | /* Set SIMODE */ | ||
| 684 | val = 0; | ||
| 685 | if (tsa->tdm[0].is_enable) | ||
| 686 | val |= TSA_SIMODE_TDMA(tsa->tdm[0].simode_tdm); | ||
| 687 | if (tsa->tdm[1].is_enable) | ||
| 688 | val |= TSA_SIMODE_TDMB(tsa->tdm[1].simode_tdm); | ||
| 689 | |||
| 690 | tsa_clrsetbits32(tsa->si_regs + TSA_SIMODE, | ||
| 691 | TSA_SIMODE_TDMA(TSA_SIMODE_TDM_MASK) | | ||
| 692 | TSA_SIMODE_TDMB(TSA_SIMODE_TDM_MASK), | ||
| 693 | val); | ||
| 694 | |||
| 695 | /* Set SIGMR */ | ||
| 696 | val = (tsa->tdms == BIT(TSA_TDMA)) ? | ||
| 697 | TSA_SIGMR_RDM_STATIC_TDMA : TSA_SIGMR_RDM_STATIC_TDMAB; | ||
| 698 | if (tsa->tdms & BIT(TSA_TDMA)) | ||
| 699 | val |= TSA_SIGMR_ENA; | ||
| 700 | if (tsa->tdms & BIT(TSA_TDMB)) | ||
| 701 | val |= TSA_SIGMR_ENB; | ||
| 702 | tsa_write8(tsa->si_regs + TSA_SIGMR, val); | ||
| 703 | |||
| 704 | platform_set_drvdata(pdev, tsa); | ||
| 705 | |||
| 706 | return 0; | ||
| 707 | } | ||
| 708 | |||
| 709 | static int tsa_remove(struct platform_device *pdev) | ||
| 710 | { | ||
| 711 | struct tsa *tsa = platform_get_drvdata(pdev); | ||
| 712 | int i; | ||
| 713 | |||
| 714 | for (i = 0; i < 2; i++) { | ||
| 715 | if (tsa->tdm[i].l1rsync_clk) { | ||
| 716 | clk_disable_unprepare(tsa->tdm[i].l1rsync_clk); | ||
| 717 | clk_put(tsa->tdm[i].l1rsync_clk); | ||
| 718 | } | ||
| 719 | if (tsa->tdm[i].l1rclk_clk) { | ||
| 720 | clk_disable_unprepare(tsa->tdm[i].l1rclk_clk); | ||
| 721 | clk_put(tsa->tdm[i].l1rclk_clk); | ||
| 722 | } | ||
| 723 | if (tsa->tdm[i].l1tsync_clk) { | ||
| 724 | clk_disable_unprepare(tsa->tdm[i].l1rsync_clk); | ||
| 725 | clk_put(tsa->tdm[i].l1rsync_clk); | ||
| 726 | } | ||
| 727 | if (tsa->tdm[i].l1tclk_clk) { | ||
| 728 | clk_disable_unprepare(tsa->tdm[i].l1rclk_clk); | ||
| 729 | clk_put(tsa->tdm[i].l1rclk_clk); | ||
| 730 | } | ||
| 731 | } | ||
| 732 | return 0; | ||
| 733 | } | ||
| 734 | |||
| 735 | static const struct of_device_id tsa_id_table[] = { | ||
| 736 | { .compatible = "fsl,cpm1-tsa" }, | ||
| 737 | {} /* sentinel */ | ||
| 738 | }; | ||
| 739 | MODULE_DEVICE_TABLE(of, tsa_id_table); | ||
| 740 | |||
| 741 | static struct platform_driver tsa_driver = { | ||
| 742 | .driver = { | ||
| 743 | .name = "fsl-tsa", | ||
| 744 | .of_match_table = of_match_ptr(tsa_id_table), | ||
| 745 | }, | ||
| 746 | .probe = tsa_probe, | ||
| 747 | .remove = tsa_remove, | ||
| 748 | }; | ||
| 749 | module_platform_driver(tsa_driver); | ||
| 750 | |||
| 751 | struct tsa_serial *tsa_serial_get_byphandle(struct device_node *np, | ||
| 752 | const char *phandle_name) | ||
| 753 | { | ||
| 754 | struct of_phandle_args out_args; | ||
| 755 | struct platform_device *pdev; | ||
| 756 | struct tsa_serial *tsa_serial; | ||
| 757 | struct tsa *tsa; | ||
| 758 | int ret; | ||
| 759 | |||
| 760 | ret = of_parse_phandle_with_fixed_args(np, phandle_name, 1, 0, &out_args); | ||
| 761 | if (ret < 0) | ||
| 762 | return ERR_PTR(ret); | ||
| 763 | |||
| 764 | if (!of_match_node(tsa_driver.driver.of_match_table, out_args.np)) { | ||
| 765 | of_node_put(out_args.np); | ||
| 766 | return ERR_PTR(-EINVAL); | ||
| 767 | } | ||
| 768 | |||
| 769 | pdev = of_find_device_by_node(out_args.np); | ||
| 770 | of_node_put(out_args.np); | ||
| 771 | if (!pdev) | ||
| 772 | return ERR_PTR(-ENODEV); | ||
| 773 | |||
| 774 | tsa = platform_get_drvdata(pdev); | ||
| 775 | if (!tsa) { | ||
| 776 | platform_device_put(pdev); | ||
| 777 | return ERR_PTR(-EPROBE_DEFER); | ||
| 778 | } | ||
| 779 | |||
| 780 | if (out_args.args_count != 1) { | ||
| 781 | platform_device_put(pdev); | ||
| 782 | return ERR_PTR(-EINVAL); | ||
| 783 | } | ||
| 784 | |||
| 785 | if (out_args.args[0] >= ARRAY_SIZE(tsa->serials)) { | ||
| 786 | platform_device_put(pdev); | ||
| 787 | return ERR_PTR(-EINVAL); | ||
| 788 | } | ||
| 789 | |||
| 790 | tsa_serial = &tsa->serials[out_args.args[0]]; | ||
| 791 | |||
| 792 | /* | ||
| 793 | * Be sure that the serial id matches the phandle arg. | ||
| 794 | * The tsa_serials table is indexed by serial ids. The serial id is set | ||
| 795 | * during the probe() call and needs to be coherent. | ||
| 796 | */ | ||
| 797 | if (WARN_ON(tsa_serial->id != out_args.args[0])) { | ||
| 798 | platform_device_put(pdev); | ||
| 799 | return ERR_PTR(-EINVAL); | ||
| 800 | } | ||
| 801 | |||
| 802 | return tsa_serial; | ||
| 803 | } | ||
| 804 | EXPORT_SYMBOL(tsa_serial_get_byphandle); | ||
| 805 | |||
| 806 | void tsa_serial_put(struct tsa_serial *tsa_serial) | ||
| 807 | { | ||
| 808 | struct tsa *tsa = tsa_serial_get_tsa(tsa_serial); | ||
| 809 | |||
| 810 | put_device(tsa->dev); | ||
| 811 | } | ||
| 812 | EXPORT_SYMBOL(tsa_serial_put); | ||
| 813 | |||
| 814 | static void devm_tsa_serial_release(struct device *dev, void *res) | ||
| 815 | { | ||
| 816 | struct tsa_serial **tsa_serial = res; | ||
| 817 | |||
| 818 | tsa_serial_put(*tsa_serial); | ||
| 819 | } | ||
| 820 | |||
| 821 | struct tsa_serial *devm_tsa_serial_get_byphandle(struct device *dev, | ||
| 822 | struct device_node *np, | ||
| 823 | const char *phandle_name) | ||
| 824 | { | ||
| 825 | struct tsa_serial *tsa_serial; | ||
| 826 | struct tsa_serial **dr; | ||
| 827 | |||
| 828 | dr = devres_alloc(devm_tsa_serial_release, sizeof(*dr), GFP_KERNEL); | ||
| 829 | if (!dr) | ||
| 830 | return ERR_PTR(-ENOMEM); | ||
| 831 | |||
| 832 | tsa_serial = tsa_serial_get_byphandle(np, phandle_name); | ||
| 833 | if (!IS_ERR(tsa_serial)) { | ||
| 834 | *dr = tsa_serial; | ||
| 835 | devres_add(dev, dr); | ||
| 836 | } else { | ||
| 837 | devres_free(dr); | ||
| 838 | } | ||
| 839 | |||
| 840 | return tsa_serial; | ||
| 841 | } | ||
| 842 | EXPORT_SYMBOL(devm_tsa_serial_get_byphandle); | ||
| 843 | |||
| 844 | MODULE_AUTHOR("Herve Codina <herve.codina@bootlin.com>"); | ||
| 845 | MODULE_DESCRIPTION("CPM TSA driver"); | ||
| 846 | MODULE_LICENSE("GPL"); | ||
| @@ -0,0 +1,42 @@ | |||
| 1 | /* SPDX-License-Identifier: GPL-2.0 */ | ||
| 2 | /* | ||
| 3 | * TSA management | ||
| 4 | * | ||
| 5 | * Copyright 2022 CS GROUP France | ||
| 6 | * | ||
| 7 | * Author: Herve Codina <herve.codina@bootlin.com> | ||
| 8 | */ | ||
| 9 | #ifndef __SOC_FSL_TSA_H__ | ||
| 10 | #define __SOC_FSL_TSA_H__ | ||
| 11 | |||
| 12 | #include <linux/types.h> | ||
| 13 | |||
| 14 | struct device_node; | ||
| 15 | struct device; | ||
| 16 | struct tsa_serial; | ||
| 17 | |||
| 18 | struct tsa_serial *tsa_serial_get_byphandle(struct device_node *np, | ||
| 19 | const char *phandle_name); | ||
| 20 | void tsa_serial_put(struct tsa_serial *tsa_serial); | ||
| 21 | struct tsa_serial *devm_tsa_serial_get_byphandle(struct device *dev, | ||
| 22 | struct device_node *np, | ||
| 23 | const char *phandle_name); | ||
| 24 | |||
| 25 | /* Connect and disconnect the TSA serial */ | ||
| 26 | int tsa_serial_connect(struct tsa_serial *tsa_serial); | ||
| 27 | int tsa_serial_disconnect(struct tsa_serial *tsa_serial); | ||
| 28 | |||
| 29 | /* Cell information */ | ||
| 30 | struct tsa_serial_info { | ||
| 31 | unsigned long rx_fs_rate; | ||
| 32 | unsigned long rx_bit_rate; | ||
| 33 | u8 nb_rx_ts; | ||
| 34 | unsigned long tx_fs_rate; | ||
| 35 | unsigned long tx_bit_rate; | ||
| 36 | u8 nb_tx_ts; | ||
| 37 | }; | ||
| 38 | |||
| 39 | /* Get information */ | ||
| 40 | int tsa_serial_get_info(struct tsa_serial *tsa_serial, struct tsa_serial_info *info); | ||
| 41 | |||
| 42 | #endif /* __SOC_FSL_TSA_H__ */ | ||
| @@ -0,0 +1,13 @@ | |||
| 1 | /* SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause */ | ||
| 2 | |||
| 3 | #ifndef __DT_BINDINGS_SOC_FSL_TSA_H | ||
| 4 | #define __DT_BINDINGS_SOC_FSL_TSA_H | ||
| 5 | |||
| 6 | #define FSL_CPM_TSA_NU 0 /* Pseuso Cell Id for not used item */ | ||
| 7 | #define FSL_CPM_TSA_SCC2 1 | ||
| 8 | #define FSL_CPM_TSA_SCC3 2 | ||
| 9 | #define FSL_CPM_TSA_SCC4 3 | ||
| 10 | #define FSL_CPM_TSA_SMC1 4 | ||
| 11 | #define FSL_CPM_TSA_SMC2 5 | ||
| 12 | |||
| 13 | #endif | ||
| @@ -17,4 +17,61 @@ · 16 unmodified lines | |||
| 17 | #define CS35L45_ASP_TX_HIZ_UNUSED 0x1 | 17 | #define CS35L45_ASP_TX_HIZ_UNUSED 0x1 |
| 18 | #define CS35L45_ASP_TX_HIZ_DISABLED 0x2 | 18 | #define CS35L45_ASP_TX_HIZ_DISABLED 0x2 |
| 19 | 19 | ||
| 20 | /* | ||
| 21 | * Optional GPIOX Sub-nodes: | ||
| 22 | * The cs35l45 node can have up to three "cirrus,gpio-ctrlX" ('X' = [1,2,3]) | ||
| 23 | * sub-nodes for configuring the GPIO pins. | ||
| 24 | * | ||
| 25 | * - gpio-dir : GPIO pin direction. Valid only when 'gpio-ctrl' | ||
| 26 | * is 1. | ||
| 27 | * 0 = Output | ||
| 28 | * 1 = Input (Default) | ||
| 29 | * | ||
| 30 | * - gpio-lvl : GPIO level. Valid only when 'gpio-ctrl' is 1 and 'gpio-dir' is 0. | ||
| 31 | * | ||
| 32 | * 0 = Low (Default) | ||
| 33 | * 1 = High | ||
| 34 | * | ||
| 35 | * - gpio-op-cfg : GPIO output configuration. Valid only when 'gpio-ctrl' is 1 | ||
| 36 | * and 'gpio-dir' is 0. | ||
| 37 | * | ||
| 38 | * 0 = CMOS (Default) | ||
| 39 | * 1 = Open Drain | ||
| 40 | * | ||
| 41 | * - gpio-pol : GPIO output polarity select. Valid only when 'gpio-ctrl' is 1 | ||
| 42 | * and 'gpio-dir' is 0. | ||
| 43 | * | ||
| 44 | * 0 = Non-inverted, Active High (Default) | ||
| 45 | * 1 = Inverted, Active Low | ||
| 46 | * | ||
| 47 | * - gpio-invert : Defines the polarity of the GPIO pin if configured | ||
| 48 | * as input. | ||
| 49 | * | ||
| 50 | * 0 = Not inverted (Default) | ||
| 51 | * 1 = Inverted | ||
| 52 | * | ||
| 53 | * - gpio-ctrl : Defines the function of the GPIO pin. | ||
| 54 | * | ||
| 55 | * GPIO1: | ||
| 56 | * 0 = High impedance input (Default) | ||
| 57 | * 1 = Pin acts as a GPIO, direction controlled by 'gpio-dir' | ||
| 58 | * 2 = Pin acts as MDSYNC, direction controlled by MDSYNC | ||
| 59 | * 3-7 = Reserved | ||
| 60 | * | ||
| 61 | * GPIO2: | ||
| 62 | * 0 = High impedance input (Default) | ||
| 63 | * 1 = Pin acts as a GPIO, direction controlled by 'gpio-dir' | ||
| 64 | * 2 = Pin acts as open drain INT | ||
| 65 | * 3 = Reserved | ||
| 66 | * 4 = Pin acts as push-pull output INT. Active low. | ||
| 67 | * 5 = Pin acts as push-pull output INT. Active high. | ||
| 68 | * 6,7 = Reserved | ||
| 69 | * | ||
| 70 | * GPIO3: | ||
| 71 | * 0 = High impedance input (Default) | ||
| 72 | * 1 = Pin acts as a GPIO, direction controlled by 'gpio-dir' | ||
| 73 | * 2-7 = Reserved | ||
| 74 | */ | ||
| 75 | #define CS35L45_NUM_GPIOS 0x3 | ||
| 76 | |||
| 20 | #endif /* DT_CS35L45_H */ | 77 | #endif /* DT_CS35L45_H */ |
| @@ -156,6 +156,7 @@ struct cs_dsp { · 155 unmodified lines | |||
| 156 | unsigned int sysclk_reg; | 156 | unsigned int sysclk_reg; |
| 157 | unsigned int sysclk_mask; | 157 | unsigned int sysclk_mask; |
| 158 | unsigned int sysclk_shift; | 158 | unsigned int sysclk_shift; |
| 159 | bool no_core_startstop; | ||
| 159 | 160 | ||
| 160 | struct list_head alg_regions; | 161 | struct list_head alg_regions; |
| 161 | 162 | ||
| @@ -0,0 +1,71 @@ | |||
| 1 | /* SPDX-License-Identifier: GPL-2.0-or-later */ | ||
| 2 | /* | ||
| 3 | * QMC management | ||
| 4 | * | ||
| 5 | * Copyright 2022 CS GROUP France | ||
| 6 | * | ||
| 7 | * Author: Herve Codina <herve.codina@bootlin.com> | ||
| 8 | */ | ||
| 9 | #ifndef __SOC_FSL_QMC_H__ | ||
| 10 | #define __SOC_FSL_QMC_H__ | ||
| 11 | |||
| 12 | #include <linux/types.h> | ||
| 13 | |||
| 14 | struct device_node; | ||
| 15 | struct device; | ||
| 16 | struct qmc_chan; | ||
| 17 | |||
| 18 | struct qmc_chan *qmc_chan_get_byphandle(struct device_node *np, const char *phandle_name); | ||
| 19 | void qmc_chan_put(struct qmc_chan *chan); | ||
| 20 | struct qmc_chan *devm_qmc_chan_get_byphandle(struct device *dev, struct device_node *np, | ||
| 21 | const char *phandle_name); | ||
| 22 | |||
| 23 | enum qmc_mode { | ||
| 24 | QMC_TRANSPARENT, | ||
| 25 | QMC_HDLC, | ||
| 26 | }; | ||
| 27 | |||
| 28 | struct qmc_chan_info { | ||
| 29 | enum qmc_mode mode; | ||
| 30 | unsigned long rx_fs_rate; | ||
| 31 | unsigned long rx_bit_rate; | ||
| 32 | u8 nb_rx_ts; | ||
| 33 | unsigned long tx_fs_rate; | ||
| 34 | unsigned long tx_bit_rate; | ||
| 35 | u8 nb_tx_ts; | ||
| 36 | }; | ||
| 37 | |||
| 38 | int qmc_chan_get_info(struct qmc_chan *chan, struct qmc_chan_info *info); | ||
| 39 | |||
| 40 | struct qmc_chan_param { | ||
| 41 | enum qmc_mode mode; | ||
| 42 | union { | ||
| 43 | struct { | ||
| 44 | u16 max_rx_buf_size; | ||
| 45 | u16 max_rx_frame_size; | ||
| 46 | bool is_crc32; | ||
| 47 | } hdlc; | ||
| 48 | struct { | ||
| 49 | u16 max_rx_buf_size; | ||
| 50 | } transp; | ||
| 51 | }; | ||
| 52 | }; | ||
| 53 | |||
| 54 | int qmc_chan_set_param(struct qmc_chan *chan, const struct qmc_chan_param *param); | ||
| 55 | |||
| 56 | int qmc_chan_write_submit(struct qmc_chan *chan, dma_addr_t addr, size_t length, | ||
| 57 | void (*complete)(void *context), void *context); | ||
| 58 | |||
| 59 | int qmc_chan_read_submit(struct qmc_chan *chan, dma_addr_t addr, size_t length, | ||
| 60 | void (*complete)(void *context, size_t length), | ||
| 61 | void *context); | ||
| 62 | |||
| 63 | #define QMC_CHAN_READ (1<<0) | ||
| 64 | #define QMC_CHAN_WRITE (1<<1) | ||
| 65 | #define QMC_CHAN_ALL (QMC_CHAN_READ | QMC_CHAN_WRITE) | ||
| 66 | |||
| 67 | int qmc_chan_start(struct qmc_chan *chan, int direction); | ||
| 68 | int qmc_chan_stop(struct qmc_chan *chan, int direction); | ||
| 69 | int qmc_chan_reset(struct qmc_chan *chan, int direction); | ||
| 70 | |||
| 71 | #endif /* __SOC_FSL_QMC_H__ */ | ||
| @@ -335,6 +335,9 @@ static inline int snd_ac97_update_power(struct snd_ac97 *ac97, int reg, · 334 unmodified lines | |||
| 335 | #ifdef CONFIG_PM | 335 | #ifdef CONFIG_PM |
| 336 | void snd_ac97_suspend(struct snd_ac97 *ac97); | 336 | void snd_ac97_suspend(struct snd_ac97 *ac97); |
| 337 | void snd_ac97_resume(struct snd_ac97 *ac97); | 337 | void snd_ac97_resume(struct snd_ac97 *ac97); |
| 338 | #else | ||
| 339 | static inline void snd_ac97_suspend(struct snd_ac97 *ac97) {} | ||
| 340 | static inline void snd_ac97_resume(struct snd_ac97 *ac97) {} | ||
| 338 | #endif | 341 | #endif |
| 339 | int snd_ac97_reset(struct snd_ac97 *ac97, bool try_warm, unsigned int id, | 342 | int snd_ac97_reset(struct snd_ac97 *ac97, bool try_warm, unsigned int id, |
| 340 | unsigned int id_mask); | 343 | unsigned int id_mask); |
| @@ -11,6 +11,7 @@ · 10 unmodified lines | |||
| 11 | #define __CS35L41_H | 11 | #define __CS35L41_H |
| 12 | 12 | ||
| 13 | #include <linux/regmap.h> | 13 | #include <linux/regmap.h> |
| 14 | #include <linux/completion.h> | ||
| 14 | #include <linux/firmware/cirrus/cs_dsp.h> | 15 | #include <linux/firmware/cirrus/cs_dsp.h> |
| 15 | 16 | ||
| 16 | #define CS35L41_FIRSTREG 0x00000000 | 17 | #define CS35L41_FIRSTREG 0x00000000 |
| @@ -677,6 +678,7 @@ · 660 unmodified lines | |||
| 677 | 678 | ||
| 678 | #define CS35L36_PUP_DONE_IRQ_UNMASK 0x5F | 679 | #define CS35L36_PUP_DONE_IRQ_UNMASK 0x5F |
| 679 | #define CS35L36_PUP_DONE_IRQ_MASK 0xBF | 680 | #define CS35L36_PUP_DONE_IRQ_MASK 0xBF |
| 681 | #define CS35L41_SYNC_EN_MASK BIT(8) | ||
| 680 | 682 | ||
| 681 | #define CS35L41_AMP_SHORT_ERR 0x80000000 | 683 | #define CS35L41_AMP_SHORT_ERR 0x80000000 |
| 682 | #define CS35L41_BST_SHORT_ERR 0x0100 | 684 | #define CS35L41_BST_SHORT_ERR 0x0100 |
| @@ -686,6 +688,7 @@ · 3 unmodified lines | |||
| 686 | #define CS35L41_BST_DCM_UVP_ERR 0x80 | 688 | #define CS35L41_BST_DCM_UVP_ERR 0x80 |
| 687 | #define CS35L41_OTP_BOOT_DONE 0x02 | 689 | #define CS35L41_OTP_BOOT_DONE 0x02 |
| 688 | #define CS35L41_PLL_UNLOCK 0x10 | 690 | #define CS35L41_PLL_UNLOCK 0x10 |
| 691 | #define CS35L41_PLL_LOCK BIT(1) | ||
| 689 | #define CS35L41_OTP_BOOT_ERR 0x80000000 | 692 | #define CS35L41_OTP_BOOT_ERR 0x80000000 |
| 690 | 693 | ||
| 691 | #define CS35L41_AMP_SHORT_ERR_RLS 0x02 | 694 | #define CS35L41_AMP_SHORT_ERR_RLS 0x02 |
| @@ -705,6 +708,8 @@ · 13 unmodified lines | |||
| 705 | #define CS35L41_INT1_MASK_DEFAULT 0x7FFCFE3F | 708 | #define CS35L41_INT1_MASK_DEFAULT 0x7FFCFE3F |
| 706 | #define CS35L41_INT1_UNMASK_PUP 0xFEFFFFFF | 709 | #define CS35L41_INT1_UNMASK_PUP 0xFEFFFFFF |
| 707 | #define CS35L41_INT1_UNMASK_PDN 0xFF7FFFFF | 710 | #define CS35L41_INT1_UNMASK_PDN 0xFF7FFFFF |
| 711 | #define CS35L41_INT3_PLL_LOCK_SHIFT 1 | ||
| 712 | #define CS35L41_INT3_PLL_LOCK_MASK BIT(CS35L41_INT3_PLL_LOCK_SHIFT) | ||
| 708 | 713 | ||
| 709 | #define CS35L41_GPIO_DIR_MASK 0x80000000 | 714 | #define CS35L41_GPIO_DIR_MASK 0x80000000 |
| 710 | #define CS35L41_GPIO_DIR_SHIFT 31 | 715 | #define CS35L41_GPIO_DIR_SHIFT 31 |
| @@ -742,6 +747,11 @@ · 31 unmodified lines | |||
| 742 | enum cs35l41_boost_type { | 747 | enum cs35l41_boost_type { |
| 743 | CS35L41_INT_BOOST, | 748 | CS35L41_INT_BOOST, |
| 744 | CS35L41_EXT_BOOST, | 749 | CS35L41_EXT_BOOST, |
| 750 | CS35L41_SHD_BOOST_ACTV, | ||
| 751 | CS35L41_SHD_BOOST_PASS, | ||
| 752 | |||
| 753 | // Not present in Binding Documentation, so no system should use this value. | ||
| 754 | // This value is only used in CLSA0100 Laptop | ||
| 745 | CS35L41_EXT_BOOST_NO_VSPK_SWITCH, | 755 | CS35L41_EXT_BOOST_NO_VSPK_SWITCH, |
| 746 | }; | 756 | }; |
| 747 | 757 | ||
| @@ -891,6 +901,7 @@ int cs35l41_exit_hibernate(struct device *dev, struct regmap *regmap); · 143 unmodified lines | |||
| 891 | int cs35l41_init_boost(struct device *dev, struct regmap *regmap, | 901 | int cs35l41_init_boost(struct device *dev, struct regmap *regmap, |
| 892 | struct cs35l41_hw_cfg *hw_cfg); | 902 | struct cs35l41_hw_cfg *hw_cfg); |
| 893 | bool cs35l41_safe_reset(struct regmap *regmap, enum cs35l41_boost_type b_type); | 903 | bool cs35l41_safe_reset(struct regmap *regmap, enum cs35l41_boost_type b_type); |
| 894 | int cs35l41_global_enable(struct regmap *regmap, enum cs35l41_boost_type b_type, int enable); | 904 | int cs35l41_global_enable(struct regmap *regmap, enum cs35l41_boost_type b_type, int enable, |
| 905 | struct completion *pll_lock); | ||
| 895 | 906 | ||
| 896 | #endif /* __CS35L41_H */ | 907 | #endif /* __CS35L41_H */ |
| @@ -0,0 +1,266 @@ | |||
| 1 | /* SPDX-License-Identifier: GPL-2.0-only */ | ||
| 2 | /* | ||
| 3 | * Common definitions 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_H | ||
| 10 | #define __CS35L56_H | ||
| 11 | |||
| 12 | #include <linux/firmware/cirrus/cs_dsp.h> | ||
| 13 | #include <linux/regulator/consumer.h> | ||
| 14 | #include <linux/regmap.h> | ||
| 15 | |||
| 16 | #define CS35L56_DEVID 0x0000000 | ||
| 17 | #define CS35L56_REVID 0x0000004 | ||
| 18 | #define CS35L56_RELID 0x000000C | ||
| 19 | #define CS35L56_OTPID 0x0000010 | ||
| 20 | #define CS35L56_SFT_RESET 0x0000020 | ||
| 21 | #define CS35L56_GLOBAL_ENABLES 0x0002014 | ||
| 22 | #define CS35L56_BLOCK_ENABLES 0x0002018 | ||
| 23 | #define CS35L56_BLOCK_ENABLES2 0x000201C | ||
| 24 | #define CS35L56_REFCLK_INPUT 0x0002C04 | ||
| 25 | #define CS35L56_GLOBAL_SAMPLE_RATE 0x0002C0C | ||
| 26 | #define CS35L56_ASP1_ENABLES1 0x0004800 | ||
| 27 | #define CS35L56_ASP1_CONTROL1 0x0004804 | ||
| 28 | #define CS35L56_ASP1_CONTROL2 0x0004808 | ||
| 29 | #define CS35L56_ASP1_CONTROL3 0x000480C | ||
| 30 | #define CS35L56_ASP1_FRAME_CONTROL1 0x0004810 | ||
| 31 | #define CS35L56_ASP1_FRAME_CONTROL5 0x0004820 | ||
| 32 | #define CS35L56_ASP1_DATA_CONTROL1 0x0004830 | ||
| 33 | #define CS35L56_ASP1_DATA_CONTROL5 0x0004840 | ||
| 34 | #define CS35L56_DACPCM1_INPUT 0x0004C00 | ||
| 35 | #define CS35L56_DACPCM2_INPUT 0x0004C08 | ||
| 36 | #define CS35L56_ASP1TX1_INPUT 0x0004C20 | ||
| 37 | #define CS35L56_ASP1TX2_INPUT 0x0004C24 | ||
| 38 | #define CS35L56_ASP1TX3_INPUT 0x0004C28 | ||
| 39 | #define CS35L56_ASP1TX4_INPUT 0x0004C2C | ||
| 40 | #define CS35L56_DSP1RX1_INPUT 0x0004C40 | ||
| 41 | #define CS35L56_DSP1RX2_INPUT 0x0004C44 | ||
| 42 | #define CS35L56_SWIRE_DP3_CH1_INPUT 0x0004C70 | ||
| 43 | #define CS35L56_SWIRE_DP3_CH2_INPUT 0x0004C74 | ||
| 44 | #define CS35L56_SWIRE_DP3_CH3_INPUT 0x0004C78 | ||
| 45 | #define CS35L56_SWIRE_DP3_CH4_INPUT 0x0004C7C | ||
| 46 | #define CS35L56_IRQ1_CFG 0x000E000 | ||
| 47 | #define CS35L56_IRQ1_STATUS 0x000E004 | ||
| 48 | #define CS35L56_IRQ1_EINT_1 0x000E010 | ||
| 49 | #define CS35L56_IRQ1_EINT_2 0x000E014 | ||
| 50 | #define CS35L56_IRQ1_EINT_4 0x000E01C | ||
| 51 | #define CS35L56_IRQ1_EINT_8 0x000E02C | ||
| 52 | #define CS35L56_IRQ1_EINT_18 0x000E054 | ||
| 53 | #define CS35L56_IRQ1_EINT_20 0x000E05C | ||
| 54 | #define CS35L56_IRQ1_MASK_1 0x000E090 | ||
| 55 | #define CS35L56_IRQ1_MASK_2 0x000E094 | ||
| 56 | #define CS35L56_IRQ1_MASK_4 0x000E09C | ||
| 57 | #define CS35L56_IRQ1_MASK_8 0x000E0AC | ||
| 58 | #define CS35L56_IRQ1_MASK_18 0x000E0D4 | ||
| 59 | #define CS35L56_IRQ1_MASK_20 0x000E0DC | ||
| 60 | #define CS35L56_DSP_VIRTUAL1_MBOX_1 0x0011020 | ||
| 61 | #define CS35L56_DSP_VIRTUAL1_MBOX_2 0x0011024 | ||
| 62 | #define CS35L56_DSP_VIRTUAL1_MBOX_3 0x0011028 | ||
| 63 | #define CS35L56_DSP_VIRTUAL1_MBOX_4 0x001102C | ||
| 64 | #define CS35L56_DSP_VIRTUAL1_MBOX_5 0x0011030 | ||
| 65 | #define CS35L56_DSP_VIRTUAL1_MBOX_6 0x0011034 | ||
| 66 | #define CS35L56_DSP_VIRTUAL1_MBOX_7 0x0011038 | ||
| 67 | #define CS35L56_DSP_VIRTUAL1_MBOX_8 0x001103C | ||
| 68 | #define CS35L56_DSP_RESTRICT_STS1 0x00190F0 | ||
| 69 | #define CS35L56_DSP1_XMEM_PACKED_0 0x2000000 | ||
| 70 | #define CS35L56_DSP1_XMEM_PACKED_6143 0x2005FFC | ||
| 71 | #define CS35L56_DSP1_XMEM_UNPACKED32_0 0x2400000 | ||
| 72 | #define CS35L56_DSP1_XMEM_UNPACKED32_4095 0x2403FFC | ||
| 73 | #define CS35L56_DSP1_SYS_INFO_ID 0x25E0000 | ||
| 74 | #define CS35L56_DSP1_SYS_INFO_END 0x25E004C | ||
| 75 | #define CS35L56_DSP1_AHBM_WINDOW_DEBUG_0 0x25E2040 | ||
| 76 | #define CS35L56_DSP1_AHBM_WINDOW_DEBUG_1 0x25E2044 | ||
| 77 | #define CS35L56_DSP1_XMEM_UNPACKED24_0 0x2800000 | ||
| 78 | #define CS35L56_DSP1_HALO_STATE_A1 0x2801E58 | ||
| 79 | #define CS35L56_DSP1_HALO_STATE 0x28021E0 | ||
| 80 | #define CS35L56_DSP1_PM_CUR_STATE_A1 0x2804000 | ||
| 81 | #define CS35L56_DSP1_PM_CUR_STATE 0x2804308 | ||
| 82 | #define CS35L56_DSP1_XMEM_UNPACKED24_8191 0x2807FFC | ||
| 83 | #define CS35L56_DSP1_CORE_BASE 0x2B80000 | ||
| 84 | #define CS35L56_DSP1_SCRATCH1 0x2B805C0 | ||
| 85 | #define CS35L56_DSP1_SCRATCH2 0x2B805C8 | ||
| 86 | #define CS35L56_DSP1_SCRATCH3 0x2B805D0 | ||
| 87 | #define CS35L56_DSP1_SCRATCH4 0x2B805D8 | ||
| 88 | #define CS35L56_DSP1_YMEM_PACKED_0 0x2C00000 | ||
| 89 | #define CS35L56_DSP1_YMEM_PACKED_4604 0x2C047F0 | ||
| 90 | #define CS35L56_DSP1_YMEM_UNPACKED32_0 0x3000000 | ||
| 91 | #define CS35L56_DSP1_YMEM_UNPACKED32_3070 0x3002FF8 | ||
| 92 | #define CS35L56_DSP1_YMEM_UNPACKED24_0 0x3400000 | ||
| 93 | #define CS35L56_MAIN_RENDER_USER_MUTE 0x3400024 | ||
| 94 | #define CS35L56_MAIN_RENDER_USER_VOLUME 0x340002C | ||
| 95 | #define CS35L56_MAIN_POSTURE_NUMBER 0x3400094 | ||
| 96 | #define CS35L56_PROTECTION_STATUS 0x34000D8 | ||
| 97 | #define CS35L56_TRANSDUCER_ACTUAL_PS 0x3400150 | ||
| 98 | #define CS35L56_DSP1_YMEM_UNPACKED24_6141 0x3405FF4 | ||
| 99 | #define CS35L56_DSP1_PMEM_0 0x3800000 | ||
| 100 | #define CS35L56_DSP1_PMEM_5114 0x3804FE8 | ||
| 101 | |||
| 102 | /* DEVID */ | ||
| 103 | #define CS35L56_DEVID_MASK 0x00FFFFFF | ||
| 104 | |||
| 105 | /* REVID */ | ||
| 106 | #define CS35L56_AREVID_MASK 0x000000F0 | ||
| 107 | #define CS35L56_MTLREVID_MASK 0x0000000F | ||
| 108 | #define CS35L56_REVID_B0 0x000000B0 | ||
| 109 | |||
| 110 | /* ASP_ENABLES1 */ | ||
| 111 | #define CS35L56_ASP_RX2_EN_SHIFT 17 | ||
| 112 | #define CS35L56_ASP_RX1_EN_SHIFT 16 | ||
| 113 | #define CS35L56_ASP_TX4_EN_SHIFT 3 | ||
| 114 | #define CS35L56_ASP_TX3_EN_SHIFT 2 | ||
| 115 | #define CS35L56_ASP_TX2_EN_SHIFT 1 | ||
| 116 | #define CS35L56_ASP_TX1_EN_SHIFT 0 | ||
| 117 | |||
| 118 | /* ASP_CONTROL1 */ | ||
| 119 | #define CS35L56_ASP_BCLK_FREQ_MASK 0x0000003F | ||
| 120 | #define CS35L56_ASP_BCLK_FREQ_SHIFT 0 | ||
| 121 | |||
| 122 | /* ASP_CONTROL2 */ | ||
| 123 | #define CS35L56_ASP_RX_WIDTH_MASK 0xFF000000 | ||
| 124 | #define CS35L56_ASP_RX_WIDTH_SHIFT 24 | ||
| 125 | #define CS35L56_ASP_TX_WIDTH_MASK 0x00FF0000 | ||
| 126 | #define CS35L56_ASP_TX_WIDTH_SHIFT 16 | ||
| 127 | #define CS35L56_ASP_FMT_MASK 0x00000700 | ||
| 128 | #define CS35L56_ASP_FMT_SHIFT 8 | ||
| 129 | #define CS35L56_ASP_BCLK_INV_MASK 0x00000040 | ||
| 130 | #define CS35L56_ASP_FSYNC_INV_MASK 0x00000004 | ||
| 131 | |||
| 132 | /* ASP_CONTROL3 */ | ||
| 133 | #define CS35L56_ASP1_DOUT_HIZ_CTRL_MASK 0x00000003 | ||
| 134 | |||
| 135 | /* ASP_DATA_CONTROL1 */ | ||
| 136 | #define CS35L56_ASP_TX_WL_MASK 0x0000003F | ||
| 137 | |||
| 138 | /* ASP_DATA_CONTROL5 */ | ||
| 139 | #define CS35L56_ASP_RX_WL_MASK 0x0000003F | ||
| 140 | |||
| 141 | /* ASPTXn_INPUT */ | ||
| 142 | #define CS35L56_ASP_TXn_SRC_MASK 0x0000007F | ||
| 143 | |||
| 144 | /* SWIRETX[1..7]_SRC SDWTXn INPUT */ | ||
| 145 | #define CS35L56_SWIRETXn_SRC_MASK 0x0000007F | ||
| 146 | |||
| 147 | /* IRQ1_STATUS */ | ||
| 148 | #define CS35L56_IRQ1_STS_MASK 0x00000001 | ||
| 149 | |||
| 150 | /* IRQ1_EINT_1 */ | ||
| 151 | #define CS35L56_AMP_SHORT_ERR_EINT1_MASK 0x80000000 | ||
| 152 | |||
| 153 | /* IRQ1_EINT_2 */ | ||
| 154 | #define CS35L56_DSP_VIRTUAL2_MBOX_WR_EINT1_MASK 0x00200000 | ||
| 155 | |||
| 156 | /* IRQ1_EINT_4 */ | ||
| 157 | #define CS35L56_OTP_BOOT_DONE_MASK 0x00000002 | ||
| 158 | |||
| 159 | /* IRQ1_EINT_8 */ | ||
| 160 | #define CS35L56_TEMP_ERR_EINT1_MASK 0x80000000 | ||
| 161 | |||
| 162 | /* Mixer input sources */ | ||
| 163 | #define CS35L56_INPUT_SRC_NONE 0x00 | ||
| 164 | #define CS35L56_INPUT_SRC_ASP1RX1 0x08 | ||
| 165 | #define CS35L56_INPUT_SRC_ASP1RX2 0x09 | ||
| 166 | #define CS35L56_INPUT_SRC_VMON 0x18 | ||
| 167 | #define CS35L56_INPUT_SRC_IMON 0x19 | ||
| 168 | #define CS35L56_INPUT_SRC_ERR_VOL 0x20 | ||
| 169 | #define CS35L56_INPUT_SRC_CLASSH 0x21 | ||
| 170 | #define CS35L56_INPUT_SRC_VDDBMON 0x28 | ||
| 171 | #define CS35L56_INPUT_SRC_VBSTMON 0x29 | ||
| 172 | #define CS35L56_INPUT_SRC_DSP1TX1 0x32 | ||
| 173 | #define CS35L56_INPUT_SRC_DSP1TX2 0x33 | ||
| 174 | #define CS35L56_INPUT_SRC_DSP1TX3 0x34 | ||
| 175 | #define CS35L56_INPUT_SRC_DSP1TX4 0x35 | ||
| 176 | #define CS35L56_INPUT_SRC_DSP1TX5 0x36 | ||
| 177 | #define CS35L56_INPUT_SRC_DSP1TX6 0x37 | ||
| 178 | #define CS35L56_INPUT_SRC_DSP1TX7 0x38 | ||
| 179 | #define CS35L56_INPUT_SRC_DSP1TX8 0x39 | ||
| 180 | #define CS35L56_INPUT_SRC_TEMPMON 0x3A | ||
| 181 | #define CS35L56_INPUT_SRC_INTERPOLATOR 0x40 | ||
| 182 | #define CS35L56_INPUT_SRC_SWIRE_DP1_CHANNEL1 0x44 | ||
| 183 | #define CS35L56_INPUT_SRC_SWIRE_DP1_CHANNEL2 0x45 | ||
| 184 | #define CS35L56_INPUT_MASK 0x7F | ||
| 185 | |||
| 186 | #define CS35L56_NUM_INPUT_SRC 21 | ||
| 187 | |||
| 188 | /* ASP formats */ | ||
| 189 | #define CS35L56_ASP_FMT_DSP_A 0 | ||
| 190 | #define CS35L56_ASP_FMT_I2S 2 | ||
| 191 | |||
| 192 | /* ASP HiZ modes */ | ||
| 193 | #define CS35L56_ASP_UNUSED_HIZ_OFF_HIZ 3 | ||
| 194 | |||
| 195 | /* MAIN_RENDER_ACTUAL_PS */ | ||
| 196 | #define CS35L56_PS0 0 | ||
| 197 | #define CS35L56_PS3 3 | ||
| 198 | |||
| 199 | /* CS35L56_DSP_RESTRICT_STS1 */ | ||
| 200 | #define CS35L56_RESTRICTED_MASK 0x7 | ||
| 201 | |||
| 202 | /* CS35L56_MAIN_RENDER_USER_MUTE */ | ||
| 203 | #define CS35L56_MAIN_RENDER_USER_MUTE_MASK 1 | ||
| 204 | |||
| 205 | /* CS35L56_MAIN_RENDER_USER_VOLUME */ | ||
| 206 | #define CS35L56_MAIN_RENDER_USER_VOLUME_MIN -400 | ||
| 207 | #define CS35L56_MAIN_RENDER_USER_VOLUME_MAX 400 | ||
| 208 | #define CS35L56_MAIN_RENDER_USER_VOLUME_MASK 0x0000FFC0 | ||
| 209 | #define CS35L56_MAIN_RENDER_USER_VOLUME_SHIFT 6 | ||
| 210 | #define CS35L56_MAIN_RENDER_USER_VOLUME_SIGNBIT 9 | ||
| 211 | |||
| 212 | /* CS35L56_MAIN_POSTURE_NUMBER */ | ||
| 213 | #define CS35L56_MAIN_POSTURE_MIN 0 | ||
| 214 | #define CS35L56_MAIN_POSTURE_MAX 255 | ||
| 215 | #define CS35L56_MAIN_POSTURE_MASK CS35L56_MAIN_POSTURE_MAX | ||
| 216 | |||
| 217 | /* CS35L56_PROTECTION_STATUS */ | ||
| 218 | #define CS35L56_FIRMWARE_MISSING BIT(0) | ||
| 219 | |||
| 220 | /* Software Values */ | ||
| 221 | #define CS35L56_HALO_STATE_SHUTDOWN 1 | ||
| 222 | #define CS35L56_HALO_STATE_BOOT_DONE 2 | ||
| 223 | |||
| 224 | #define CS35L56_MBOX_CMD_AUDIO_PLAY 0x0B000001 | ||
| 225 | #define CS35L56_MBOX_CMD_AUDIO_PAUSE 0x0B000002 | ||
| 226 | #define CS35L56_MBOX_CMD_HIBERNATE_NOW 0x02000001 | ||
| 227 | #define CS35L56_MBOX_CMD_WAKEUP 0x02000002 | ||
| 228 | #define CS35L56_MBOX_CMD_PREVENT_AUTO_HIBERNATE 0x02000003 | ||
| 229 | #define CS35L56_MBOX_CMD_ALLOW_AUTO_HIBERNATE 0x02000004 | ||
| 230 | #define CS35L56_MBOX_CMD_SHUTDOWN 0x02000005 | ||
| 231 | #define CS35L56_MBOX_CMD_SYSTEM_RESET 0x02000007 | ||
| 232 | |||
| 233 | #define CS35L56_MBOX_TIMEOUT_US 5000 | ||
| 234 | #define CS35L56_MBOX_POLL_US 250 | ||
| 235 | |||
| 236 | #define CS35L56_PS0_POLL_US 500 | ||
| 237 | #define CS35L56_PS0_TIMEOUT_US 50000 | ||
| 238 | #define CS35L56_PS3_POLL_US 500 | ||
| 239 | #define CS35L56_PS3_TIMEOUT_US 300000 | ||
| 240 | |||
| 241 | #define CS35L56_CONTROL_PORT_READY_US 2200 | ||
| 242 | #define CS35L56_HALO_STATE_POLL_US 1000 | ||
| 243 | #define CS35L56_HALO_STATE_TIMEOUT_US 50000 | ||
| 244 | #define CS35L56_HIBERNATE_WAKE_POLL_US 500 | ||
| 245 | #define CS35L56_HIBERNATE_WAKE_TIMEOUT_US 5000 | ||
| 246 | #define CS35L56_RESET_PULSE_MIN_US 1100 | ||
| 247 | |||
| 248 | #define CS35L56_SDW1_PLAYBACK_PORT 1 | ||
| 249 | #define CS35L56_SDW1_CAPTURE_PORT 3 | ||
| 250 | |||
| 251 | #define CS35L56_NUM_BULK_SUPPLIES 3 | ||
| 252 | #define CS35L56_NUM_DSP_REGIONS 5 | ||
| 253 | |||
| 254 | extern struct regmap_config cs35l56_regmap_i2c; | ||
| 255 | extern struct regmap_config cs35l56_regmap_spi; | ||
| 256 | extern struct regmap_config cs35l56_regmap_sdw; | ||
| 257 | |||
| 258 | extern const struct cs_dsp_region cs35l56_dsp1_regions[CS35L56_NUM_DSP_REGIONS]; | ||
| 259 | extern const char * const cs35l56_tx_input_texts[CS35L56_NUM_INPUT_SRC]; | ||
| 260 | extern const unsigned int cs35l56_tx_input_values[CS35L56_NUM_INPUT_SRC]; | ||
| 261 | |||
| 262 | void cs35l56_reread_firmware_registers(struct device *dev, struct regmap *regmap); | ||
| 263 | int cs35l56_get_bclk_freq_id(unsigned int freq); | ||
| 264 | void cs35l56_fill_supply_names(struct regulator_bulk_data *data); | ||
| 265 | |||
| 266 | #endif /* ifndef __CS35L56_H */ | ||
| @@ -25,13 +25,9 @@ · 24 unmodified lines | |||
| 25 | /* ------------------- DEFINES -------------------- */ | 25 | /* ------------------- DEFINES -------------------- */ |
| 26 | 26 | ||
| 27 | #define EMUPAGESIZE 4096 | 27 | #define EMUPAGESIZE 4096 |
| 28 | #define MAXREQVOICES 8 | ||
| 29 | #define MAXPAGES0 4096 /* 32 bit mode */ | 28 | #define MAXPAGES0 4096 /* 32 bit mode */ |
| 30 | #define MAXPAGES1 8192 /* 31 bit mode */ | 29 | #define MAXPAGES1 8192 /* 31 bit mode */ |
| 31 | #define RESERVED 0 | ||
| 32 | #define NUM_MIDI 16 | ||
| 33 | #define NUM_G 64 /* use all channels */ | 30 | #define NUM_G 64 /* use all channels */ |
| 34 | #define NUM_FXSENDS 4 | ||
| 35 | #define NUM_EFX_PLAYBACK 16 | 31 | #define NUM_EFX_PLAYBACK 16 |
| 36 | 32 | ||
| 37 | /* FIXME? - according to the OSS driver the EMU10K1 needs a 29 bit DMA mask */ | 33 | /* FIXME? - according to the OSS driver the EMU10K1 needs a 29 bit DMA mask */ |
| @@ -39,7 +35,6 @@ · 1 unmodified line | |||
| 39 | #define AUDIGY_DMA_MASK 0xffffffffUL /* 32bit mode */ | 35 | #define AUDIGY_DMA_MASK 0xffffffffUL /* 32bit mode */ |
| 40 | 36 | ||
| 41 | #define TMEMSIZE 256*1024 | 37 | #define TMEMSIZE 256*1024 |
| 42 | #define TMEMSIZEREG 4 | ||
| 43 | 38 | ||
| 44 | #define IP_TO_CP(ip) ((ip == 0) ? 0 : (((0x00001000uL | (ip & 0x00000FFFL)) << (((ip >> 12) & 0x000FL) + 4)) & 0xFFFF0000uL)) | 39 | #define IP_TO_CP(ip) ((ip == 0) ? 0 : (((0x00001000uL | (ip & 0x00000FFFL)) << (((ip >> 12) & 0x000FL) + 4)) & 0xFFFF0000uL)) |
| 45 | 40 | ||
| @@ -66,8 +61,8 @@ · 20 unmodified lines | |||
| 66 | /* the relevant bits and zero to the other bits */ | 61 | /* the relevant bits and zero to the other bits */ |
| 67 | #define IPR_P16V 0x80000000 /* Bit set when the CA0151 P16V chip wishes | 62 | #define IPR_P16V 0x80000000 /* Bit set when the CA0151 P16V chip wishes |
| 68 | to interrupt */ | 63 | to interrupt */ |
| 69 | #define IPR_GPIOMSG 0x20000000 /* GPIO message interrupt (RE'd, still not sure | 64 | #define IPR_WATERMARK_REACHED 0x40000000 |
| 70 | which INTE bits enable it) */ | 65 | #define IPR_A_GPIO 0x20000000 /* GPIO input pin change */ |
| 71 | 66 | ||
| 72 | /* The next two interrupts are for the midi port on the Audigy Drive (A_MPU1) */ | 67 | /* The next two interrupts are for the midi port on the Audigy Drive (A_MPU1) */ |
| 73 | #define IPR_A_MIDITRANSBUFEMPTY2 0x10000000 /* MIDI UART transmit buffer empty */ | 68 | #define IPR_A_MIDITRANSBUFEMPTY2 0x10000000 /* MIDI UART transmit buffer empty */ |
| @@ -97,9 +92,9 @@ · 23 unmodified lines | |||
| 97 | #define IPR_CHANNELLOOP 0x00000040 /* Channel (half) loop interrupt(s) pending */ | 92 | #define IPR_CHANNELLOOP 0x00000040 /* Channel (half) loop interrupt(s) pending */ |
| 98 | #define IPR_CHANNELNUMBERMASK 0x0000003f /* When IPR_CHANNELLOOP is set, indicates the */ | 93 | #define IPR_CHANNELNUMBERMASK 0x0000003f /* When IPR_CHANNELLOOP is set, indicates the */ |
| 99 | /* highest set channel in CLIPL, CLIPH, HLIPL, */ | 94 | /* highest set channel in CLIPL, CLIPH, HLIPL, */ |
| 100 | /* or HLIPH. When IP is written with CL set, */ | 95 | /* or HLIPH. When IPR is written with CL set, */ |
| 101 | /* the bit in H/CLIPL or H/CLIPH corresponding */ | 96 | /* the bit in H/CLIPL or H/CLIPH corresponding */ |
| 102 | /* to the CIN value written will be cleared. */ | 97 | /* to the CN value written will be cleared. */ |
| 103 | 98 | ||
| 104 | #define INTE 0x0c /* Interrupt enable register */ | 99 | #define INTE 0x0c /* Interrupt enable register */ |
| 105 | #define INTE_VIRTUALSB_MASK 0xc0000000 /* Virtual Soundblaster I/O port capture */ | 100 | #define INTE_VIRTUALSB_MASK 0xc0000000 /* Virtual Soundblaster I/O port capture */ |
| @@ -127,10 +122,14 @@ · 21 unmodified lines | |||
| 127 | /* behavior and possibly random segfaults and */ | 122 | /* behavior and possibly random segfaults and */ |
| 128 | /* lockups if enabled. */ | 123 | /* lockups if enabled. */ |
| 129 | 124 | ||
| 125 | #define INTE_A_GPIOENABLE 0x00040000 /* Enable GPIO input change interrupts */ | ||
| 126 | |||
| 130 | /* The next two interrupts are for the midi port on the Audigy Drive (A_MPU1) */ | 127 | /* The next two interrupts are for the midi port on the Audigy Drive (A_MPU1) */ |
| 131 | #define INTE_A_MIDITXENABLE2 0x00020000 /* Enable MIDI transmit-buffer-empty interrupts */ | 128 | #define INTE_A_MIDITXENABLE2 0x00020000 /* Enable MIDI transmit-buffer-empty interrupts */ |
| 132 | #define INTE_A_MIDIRXENABLE2 0x00010000 /* Enable MIDI receive-buffer-empty interrupts */ | 129 | #define INTE_A_MIDIRXENABLE2 0x00010000 /* Enable MIDI receive-buffer-empty interrupts */ |
| 133 | 130 | ||
| 131 | #define INTE_A_SPDIF_BUFFULL_ENABLE 0x00008000 | ||
| 132 | #define INTE_A_SPDIF_HALFBUFFULL_ENABLE 0x00004000 | ||
| 134 | 133 | ||
| 135 | #define INTE_SAMPLERATETRACKER 0x00002000 /* Enable sample rate tracker interrupts */ | 134 | #define INTE_SAMPLERATETRACKER 0x00002000 /* Enable sample rate tracker interrupts */ |
| 136 | /* NOTE: This bit must always be enabled */ | 135 | /* NOTE: This bit must always be enabled */ |
| @@ -151,9 +150,10 @@ · 14 unmodified lines | |||
| 151 | #define WC 0x10 /* Wall Clock register */ | 150 | #define WC 0x10 /* Wall Clock register */ |
| 152 | #define WC_SAMPLECOUNTER_MASK 0x03FFFFC0 /* Sample periods elapsed since reset */ | 151 | #define WC_SAMPLECOUNTER_MASK 0x03FFFFC0 /* Sample periods elapsed since reset */ |
| 153 | #define WC_SAMPLECOUNTER 0x14060010 | 152 | #define WC_SAMPLECOUNTER 0x14060010 |
| 154 | #define WC_CURRENTCHANNEL 0x0000003F /* Channel [0..63] currently being serviced */ | 153 | #define WC_CURRENTCHANNEL_MASK 0x0000003F /* Channel [0..63] currently being serviced */ |
| 155 | /* NOTE: Each channel takes 1/64th of a sample */ | 154 | /* NOTE: Each channel takes 1/64th of a sample */ |
| 156 | /* period to be serviced. */ | 155 | /* period to be serviced. */ |
| 156 | #define WC_CURRENTCHANNEL 0x06000010 | ||
| 157 | 157 | ||
| 158 | #define HCFG 0x14 /* Hardware config register */ | 158 | #define HCFG 0x14 /* Hardware config register */ |
| 159 | /* NOTE: There is no reason to use the legacy */ | 159 | /* NOTE: There is no reason to use the legacy */ |
| @@ -180,6 +180,7 @@ · 20 unmodified lines | |||
| 180 | #define HCFG_CODECFORMAT_MASK 0x00030000 /* CODEC format */ | 180 | #define HCFG_CODECFORMAT_MASK 0x00030000 /* CODEC format */ |
| 181 | 181 | ||
| 182 | /* Specific to Alice2, CA0102 */ | 182 | /* Specific to Alice2, CA0102 */ |
| 183 | |||
| 183 | #define HCFG_CODECFORMAT_AC97_1 0x00000000 /* AC97 CODEC format -- Ver 1.03 */ | 184 | #define HCFG_CODECFORMAT_AC97_1 0x00000000 /* AC97 CODEC format -- Ver 1.03 */ |
| 184 | #define HCFG_CODECFORMAT_AC97_2 0x00010000 /* AC97 CODEC format -- Ver 2.1 */ | 185 | #define HCFG_CODECFORMAT_AC97_2 0x00010000 /* AC97 CODEC format -- Ver 2.1 */ |
| 185 | #define HCFG_AUTOMUTE_ASYNC 0x00008000 /* When set, the async sample rate convertors */ | 186 | #define HCFG_AUTOMUTE_ASYNC 0x00008000 /* When set, the async sample rate convertors */ |
| @@ -200,9 +201,8 @@ · 14 unmodified lines | |||
| 200 | /* I2S format input */ | 201 | /* I2S format input */ |
| 201 | /* Rest of HCFG 0x0000000f same as below. LOCKSOUNDCACHE etc. */ | 202 | /* Rest of HCFG 0x0000000f same as below. LOCKSOUNDCACHE etc. */ |
| 202 | 203 | ||
| 203 | |||
| 204 | |||
| 205 | /* Older chips */ | 204 | /* Older chips */ |
| 205 | |||
| 206 | #define HCFG_CODECFORMAT_AC97 0x00000000 /* AC97 CODEC format -- Primary Output */ | 206 | #define HCFG_CODECFORMAT_AC97 0x00000000 /* AC97 CODEC format -- Primary Output */ |
| 207 | #define HCFG_CODECFORMAT_I2S 0x00010000 /* I2S CODEC format -- Secondary (Rear) Output */ | 207 | #define HCFG_CODECFORMAT_I2S 0x00010000 /* I2S CODEC format -- Secondary (Rear) Output */ |
| 208 | #define HCFG_GPINPUT0 0x00004000 /* External pin112 */ | 208 | #define HCFG_GPINPUT0 0x00004000 /* External pin112 */ |
| @@ -238,7 +238,7 @@ · 29 unmodified lines | |||
| 238 | /* Should be set to 1 when the EMU10K1 is */ | 238 | /* Should be set to 1 when the EMU10K1 is */ |
| 239 | /* completely initialized. */ | 239 | /* completely initialized. */ |
| 240 | 240 | ||
| 241 | //For Audigy, MPU port move to 0x70-0x74 ptr register | 241 | // On Audigy, the MPU port moved to the 0x70-0x74 ptr registers |
| 242 | 242 | ||
| 243 | #define MUDATA 0x18 /* MPU401 data register (8 bits) */ | 243 | #define MUDATA 0x18 /* MPU401 data register (8 bits) */ |
| 244 | 244 | ||
| @@ -251,11 +251,17 @@ · 6 unmodified lines | |||
| 251 | #define MUSTAT_IRDYN 0x80 /* 0 = MIDI data or command ACK */ | 251 | #define MUSTAT_IRDYN 0x80 /* 0 = MIDI data or command ACK */ |
| 252 | #define MUSTAT_ORDYN 0x40 /* 0 = MUDATA can accept a command or data */ | 252 | #define MUSTAT_ORDYN 0x40 /* 0 = MUDATA can accept a command or data */ |
| 253 | 253 | ||
| 254 | #define A_IOCFG 0x18 /* GPIO on Audigy card (16bits) */ | 254 | #define A_GPIO 0x18 /* GPIO on Audigy card (16bits) */ |
| 255 | #define A_GPINPUT_MASK 0xff00 | 255 | #define A_GPINPUT_MASK 0xff00 /* Alice/2 has 8 input pins */ |
| 256 | #define A3_GPINPUT_MASK 0x3f00 /* ... while Tina/2 has only 6 */ | ||
| 256 | #define A_GPOUTPUT_MASK 0x00ff | 257 | #define A_GPOUTPUT_MASK 0x00ff |
| 257 | 258 | ||
| 259 | // The GPIO port is used for I/O config on Sound Blasters; | ||
| 260 | // card-specific info can be found in the emu_chip_details table. | ||
| 261 | // On E-MU cards the port is used as the interface to the FPGA. | ||
| 262 | |||
| 258 | // Audigy output/GPIO stuff taken from the kX drivers | 263 | // Audigy output/GPIO stuff taken from the kX drivers |
| 264 | #define A_IOCFG A_GPIO | ||
| 259 | #define A_IOCFG_GPOUT0 0x0044 /* analog/digital */ | 265 | #define A_IOCFG_GPOUT0 0x0044 /* analog/digital */ |
| 260 | #define A_IOCFG_DISABLE_ANALOG 0x0040 /* = 'enable' for Audigy2 (chiprev=4) */ | 266 | #define A_IOCFG_DISABLE_ANALOG 0x0040 /* = 'enable' for Audigy2 (chiprev=4) */ |
| 261 | #define A_IOCFG_ENABLE_DIGITAL 0x0004 | 267 | #define A_IOCFG_ENABLE_DIGITAL 0x0004 |
| @@ -271,19 +277,12 @@ · 9 unmodified lines | |||
| 271 | #define A_IOCFG_REAR_JACK 0x8000 | 277 | #define A_IOCFG_REAR_JACK 0x8000 |
| 272 | #define A_IOCFG_PHONES_JACK 0x0100 /* LiveDrive */ | 278 | #define A_IOCFG_PHONES_JACK 0x0100 /* LiveDrive */ |
| 273 | 279 | ||
| 274 | /* outputs: | ||
| 275 | * for audigy2 platinum: 0xa00 | ||
| 276 | * for a2 platinum ex: 0x1c00 | ||
| 277 | * for a1 platinum: 0x0 | ||
| 278 | */ | ||
| 279 | |||
| 280 | #define TIMER 0x1a /* Timer terminal count register */ | 280 | #define TIMER 0x1a /* Timer terminal count register */ |
| 281 | /* NOTE: After the rate is changed, a maximum */ | 281 | /* NOTE: After the rate is changed, a maximum */ |
| 282 | /* of 1024 sample periods should be allowed */ | 282 | /* of 1024 sample periods should be allowed */ |
| 283 | /* before the new rate is guaranteed accurate. */ | 283 | /* before the new rate is guaranteed accurate. */ |
| 284 | #define TIMER_RATE_MASK 0x000003ff /* Timer interrupt rate in sample periods */ | 284 | #define TIMER_RATE_MASK 0x03ff /* Timer interrupt rate in sample periods */ |
| 285 | /* 0 == 1024 periods, [1..4] are not useful */ | 285 | /* 0 == 1024 periods, [1..4] are not useful */ |
| 286 | #define TIMER_RATE 0x0a00001a | ||
| 287 | 286 | ||
| 288 | #define AC97DATA 0x1c /* AC97 register set data register (16 bit) */ | 287 | #define AC97DATA 0x1c /* AC97 register set data register (16 bit) */ |
| 289 | 288 | ||
| @@ -317,7 +316,7 @@ · 27 unmodified lines | |||
| 317 | /* 0x00000000 2-channel output. */ | 316 | /* 0x00000000 2-channel output. */ |
| 318 | /* 0x00000200 8-channel output. */ | 317 | /* 0x00000200 8-channel output. */ |
| 319 | /* 0x00000004 pauses stream/irq fail. */ | 318 | /* 0x00000004 pauses stream/irq fail. */ |
| 320 | /* Rest of bits no nothing to sound output */ | 319 | /* Rest of bits do nothing to sound output */ |
| 321 | /* bit 0: Enable P16V audio. | 320 | /* bit 0: Enable P16V audio. |
| 322 | * bit 1: Lock P16V record memory cache. | 321 | * bit 1: Lock P16V record memory cache. |
| 323 | * bit 2: Lock P16V playback memory cache. | 322 | * bit 2: Lock P16V playback memory cache. |
| @@ -331,6 +330,7 @@ · 7 unmodified lines | |||
| 331 | */ | 330 | */ |
| 332 | #define IPR3 0x38 /* Cdif interrupt pending register */ | 331 | #define IPR3 0x38 /* Cdif interrupt pending register */ |
| 333 | #define INTE3 0x3c /* Cdif interrupt enable register. */ | 332 | #define INTE3 0x3c /* Cdif interrupt enable register. */ |
| 333 | |||
| 334 | /************************************************************************************************/ | 334 | /************************************************************************************************/ |
| 335 | /* PCI function 1 registers, address = <val> + PCIBASE1 */ | 335 | /* PCI function 1 registers, address = <val> + PCIBASE1 */ |
| 336 | /************************************************************************************************/ | 336 | /************************************************************************************************/ |
| @@ -349,11 +349,38 @@ · 12 unmodified lines | |||
| 349 | #define JOYSTICK_BUTTONS 0x0f /* Joystick button data */ | 349 | #define JOYSTICK_BUTTONS 0x0f /* Joystick button data */ |
| 350 | #define JOYSTICK_COMPARATOR 0xf0 /* Joystick comparator data */ | 350 | #define JOYSTICK_COMPARATOR 0xf0 /* Joystick comparator data */ |
| 351 | 351 | ||
| 352 | |||
| 353 | /********************************************************************************************************/ | 352 | /********************************************************************************************************/ |
| 354 | /* Emu10k1 pointer-offset register set, accessed through the PTR and DATA registers */ | 353 | /* Emu10k1 pointer-offset register set, accessed through the PTR and DATA registers */ |
| 355 | /********************************************************************************************************/ | 354 | /********************************************************************************************************/ |
| 356 | 355 | ||
| 356 | // No official documentation was released for EMU10K1, but some info | ||
| 357 | // about playback can be extrapolated from the EMU8K documents: | ||
| 358 | // "AWE32/EMU8000 Programmer’s Guide" (emu8kpgm.pdf) - registers | ||
| 359 | // "AWE32 Developer's Information Pack" (adip301.pdf) - high-level view | ||
| 360 | |||
| 361 | // The short version: | ||
| 362 | // - The engine has 64 playback channels, also called voices. The channels | ||
| 363 | // operate independently, except when paired for stereo (see below). | ||
| 364 | // - PCM samples are fetched into the cache; see description of CD0 below. | ||
| 365 | // - Samples are consumed at the rate CPF_CURRENTPITCH. | ||
| 366 | // - 8-bit samples are transformed upon use: cooked = (raw ^ 0x80) << 8 | ||
| 367 | // - 8 samples are read at CCR_READADDRESS:CPF_FRACADDRESS and interpolated | ||
| 368 | // according to CCCA_INTERPROM_*. With CCCA_INTERPROM_0 selected and a zero | ||
| 369 | // CPF_FRACADDRESS, this results in CCR_READADDRESS[3] being used verbatim. | ||
| 370 | // - The value is multiplied by CVCF_CURRENTVOL. | ||
| 371 | // - The value goes through a filter with cutoff CVCF_CURRENTFILTER; | ||
| 372 | // delay stages Z1 and Z2. | ||
| 373 | // - The value is added by so-called `sends` to 4 (EMU10K1) / 8 (EMU10K2) | ||
| 374 | // of the 16 (EMU10K1) / 64 (EMU10K2) FX bus accumulators via FXRT*, | ||
| 375 | // multiplied by a per-send amount (*_FXSENDAMOUNT_*). | ||
| 376 | // The scaling of the send amounts is exponential-ish. | ||
| 377 | // - The DSP has a go at FXBUS* and outputs the values to EXTOUT* or EMU32OUT*. | ||
| 378 | // - The pitch, volume, and filter cutoff can be modulated by two envelope | ||
| 379 | // engines and two low frequency oscillators. | ||
| 380 | // - To avoid abrupt changes to the parameters (which may cause audible | ||
| 381 | // distortion), the modulation engine sets the target registers, towards | ||
| 382 | // which the current registers "swerve" gradually. | ||
| 383 | |||
| 357 | #define CPF 0x00 /* Current pitch and fraction register */ | 384 | #define CPF 0x00 /* Current pitch and fraction register */ |
| 358 | #define CPF_CURRENTPITCH_MASK 0xffff0000 /* Current pitch (linear, 0x4000 == unity pitch shift) */ | 385 | #define CPF_CURRENTPITCH_MASK 0xffff0000 /* Current pitch (linear, 0x4000 == unity pitch shift) */ |
| 359 | #define CPF_CURRENTPITCH 0x10100000 | 386 | #define CPF_CURRENTPITCH 0x10100000 |
| @@ -393,7 +420,7 @@ · 33 unmodified lines | |||
| 393 | #define PSST_LOOPSTARTADDR_MASK 0x00ffffff /* Loop start address of the specified channel */ | 420 | #define PSST_LOOPSTARTADDR_MASK 0x00ffffff /* Loop start address of the specified channel */ |
| 394 | #define PSST_LOOPSTARTADDR 0x18000006 | 421 | #define PSST_LOOPSTARTADDR 0x18000006 |
| 395 | 422 | ||
| 396 | #define DSL 0x07 /* Send D amount and loop start address register */ | 423 | #define DSL 0x07 /* Send D amount and loop end address register */ |
| 397 | #define DSL_FXSENDAMOUNT_D_MASK 0xff000000 /* Linear level of channel output sent to FX send bus D */ | 424 | #define DSL_FXSENDAMOUNT_D_MASK 0xff000000 /* Linear level of channel output sent to FX send bus D */ |
| 398 | 425 | ||
| 399 | #define DSL_FXSENDAMOUNT_D 0x08180007 | 426 | #define DSL_FXSENDAMOUNT_D 0x08180007 |
| @@ -402,8 +429,9 @@ · 2 unmodified lines | |||
| 402 | #define DSL_LOOPENDADDR 0x18000007 | 429 | #define DSL_LOOPENDADDR 0x18000007 |
| 403 | 430 | ||
| 404 | #define CCCA 0x08 /* Filter Q, interp. ROM, byte size, cur. addr register */ | 431 | #define CCCA 0x08 /* Filter Q, interp. ROM, byte size, cur. addr register */ |
| 405 | #define CCCA_RESONANCE 0xf0000000 /* Lowpass filter resonance (Q) height */ | 432 | #define CCCA_RESONANCE_MASK 0xf0000000 /* Lowpass filter resonance (Q) height */ |
| 406 | #define CCCA_INTERPROMMASK 0x0e000000 /* Selects passband of interpolation ROM */ | 433 | #define CCCA_RESONANCE 0x041c0008 |
| 434 | #define CCCA_INTERPROM_MASK 0x0e000000 /* Selects passband of interpolation ROM */ | ||
| 407 | /* 1 == full band, 7 == lowpass */ | 435 | /* 1 == full band, 7 == lowpass */ |
| 408 | /* ROM 0 is used when pitch shifting downward or less */ | 436 | /* ROM 0 is used when pitch shifting downward or less */ |
| 409 | /* then 3 semitones upward. Increasingly higher ROM */ | 437 | /* then 3 semitones upward. Increasingly higher ROM */ |
| @@ -418,25 +446,28 @@ · 8 unmodified lines | |||
| 418 | #define CCCA_INTERPROM_6 0x0c000000 /* Select interpolation ROM 6 */ | 446 | #define CCCA_INTERPROM_6 0x0c000000 /* Select interpolation ROM 6 */ |
| 419 | #define CCCA_INTERPROM_7 0x0e000000 /* Select interpolation ROM 7 */ | 447 | #define CCCA_INTERPROM_7 0x0e000000 /* Select interpolation ROM 7 */ |
| 420 | #define CCCA_8BITSELECT 0x01000000 /* 1 = Sound memory for this channel uses 8-bit samples */ | 448 | #define CCCA_8BITSELECT 0x01000000 /* 1 = Sound memory for this channel uses 8-bit samples */ |
| 449 | /* 8-bit samples are unsigned, 16-bit ones signed */ | ||
| 421 | #define CCCA_CURRADDR_MASK 0x00ffffff /* Current address of the selected channel */ | 450 | #define CCCA_CURRADDR_MASK 0x00ffffff /* Current address of the selected channel */ |
| 422 | #define CCCA_CURRADDR 0x18000008 | 451 | #define CCCA_CURRADDR 0x18000008 |
| 423 | 452 | ||
| 424 | #define CCR 0x09 /* Cache control register */ | 453 | #define CCR 0x09 /* Cache control register */ |
| 425 | #define CCR_CACHEINVALIDSIZE 0x07190009 | 454 | #define CCR_CACHEINVALIDSIZE 0x07190009 |
| 426 | #define CCR_CACHEINVALIDSIZE_MASK 0xfe000000 /* Number of invalid samples cache for this channel */ | 455 | #define CCR_CACHEINVALIDSIZE_MASK 0xfe000000 /* Number of invalid samples before the read address */ |
| 427 | #define CCR_CACHELOOPFLAG 0x01000000 /* 1 = Cache has a loop service pending */ | 456 | #define CCR_CACHELOOPFLAG 0x01000000 /* 1 = Cache has a loop service pending */ |
| 428 | #define CCR_INTERLEAVEDSAMPLES 0x00800000 /* 1 = A cache service will fetch interleaved samples */ | 457 | #define CCR_INTERLEAVEDSAMPLES 0x00800000 /* 1 = A cache service will fetch interleaved samples */ |
| 458 | /* Auto-set from CPF_STEREO_MASK */ | ||
| 429 | #define CCR_WORDSIZEDSAMPLES 0x00400000 /* 1 = A cache service will fetch word sized samples */ | 459 | #define CCR_WORDSIZEDSAMPLES 0x00400000 /* 1 = A cache service will fetch word sized samples */ |
| 460 | /* Auto-set from CCCA_8BITSELECT */ | ||
| 430 | #define CCR_READADDRESS 0x06100009 | 461 | #define CCR_READADDRESS 0x06100009 |
| 431 | #define CCR_READADDRESS_MASK 0x003f0000 /* Location of cache just beyond current cache service */ | 462 | #define CCR_READADDRESS_MASK 0x003f0000 /* Next cached sample to play */ |
| 432 | #define CCR_LOOPINVALSIZE 0x0000fe00 /* Number of invalid samples in cache prior to loop */ | 463 | #define CCR_LOOPINVALSIZE 0x0000fe00 /* Number of invalid samples in cache prior to loop */ |
| 433 | /* NOTE: This is valid only if CACHELOOPFLAG is set */ | 464 | /* NOTE: This is valid only if CACHELOOPFLAG is set */ |
| 434 | #define CCR_LOOPFLAG 0x00000100 /* Set for a single sample period when a loop occurs */ | 465 | #define CCR_LOOPFLAG 0x00000100 /* Set for a single sample period when a loop occurs */ |
| 435 | #define CCR_CACHELOOPADDRHI 0x000000ff /* DSL_LOOPSTARTADDR's hi byte if CACHELOOPFLAG is set */ | 466 | #define CCR_CACHELOOPADDRHI 0x000000ff /* CLP_LOOPSTARTADDR's hi byte if CACHELOOPFLAG is set */ |
| 436 | 467 | ||
| 437 | #define CLP 0x0a /* Cache loop register (valid if CCR_CACHELOOPFLAG = 1) */ | 468 | #define CLP 0x0a /* Cache loop register (valid if CCR_CACHELOOPFLAG = 1) */ |
| 438 | /* NOTE: This register is normally not used */ | 469 | /* NOTE: This register is normally not used */ |
| 439 | #define CLP_CACHELOOPADDR 0x0000ffff /* Cache loop address (DSL_LOOPSTARTADDR [0..15]) */ | 470 | #define CLP_CACHELOOPADDR 0x0000ffff /* Cache loop address low word */ |
| 440 | 471 | ||
| 441 | #define FXRT 0x0b /* Effects send routing register */ | 472 | #define FXRT 0x0b /* Effects send routing register */ |
| 442 | /* NOTE: It is illegal to assign the same routing to */ | 473 | /* NOTE: It is illegal to assign the same routing to */ |
| @@ -446,9 +477,7 @@ · 3 unmodified lines | |||
| 446 | #define FXRT_CHANNELC 0x0f000000 /* Effects send bus number for channel's effects send C */ | 477 | #define FXRT_CHANNELC 0x0f000000 /* Effects send bus number for channel's effects send C */ |
| 447 | #define FXRT_CHANNELD 0xf0000000 /* Effects send bus number for channel's effects send D */ | 478 | #define FXRT_CHANNELD 0xf0000000 /* Effects send bus number for channel's effects send D */ |
| 448 | 479 | ||
| 449 | #define A_HR 0x0b /* High Resolution. 24bit playback from host to DSP. */ | ||
| 450 | #define MAPA 0x0c /* Cache map A */ | 480 | #define MAPA 0x0c /* Cache map A */ |
| 451 | |||
| 452 | #define MAPB 0x0d /* Cache map B */ | 481 | #define MAPB 0x0d /* Cache map B */ |
| 453 | 482 | ||
| 454 | #define MAP_PTE_MASK0 0xfffff000 /* The 20 MSBs of the PTE indexed by the PTI */ | 483 | #define MAP_PTE_MASK0 0xfffff000 /* The 20 MSBs of the PTE indexed by the PTI */ |
| @@ -457,22 +486,22 @@ · 2 unmodified lines | |||
| 457 | #define MAP_PTE_MASK1 0xffffe000 /* The 19 MSBs of the PTE indexed by the PTI */ | 486 | #define MAP_PTE_MASK1 0xffffe000 /* The 19 MSBs of the PTE indexed by the PTI */ |
| 458 | #define MAP_PTI_MASK1 0x00001fff /* The 13 bit index to one of the 8192 PTE dwords */ | 487 | #define MAP_PTI_MASK1 0x00001fff /* The 13 bit index to one of the 8192 PTE dwords */ |
| 459 | 488 | ||
| 460 | /* 0x0e, 0x0f: Not used */ | 489 | /* 0x0e, 0x0f: Internal state, at least on Audigy */ |
| 461 | 490 | ||
| 462 | #define ENVVOL 0x10 /* Volume envelope register */ | 491 | #define ENVVOL 0x10 /* Volume envelope register */ |
| 463 | #define ENVVOL_MASK 0x0000ffff /* Current value of volume envelope state variable */ | 492 | #define ENVVOL_MASK 0x0000ffff /* Current value of volume envelope state variable */ |
| 464 | /* 0x8000-n == 666*n usec delay */ | 493 | /* 0x8000-n == 666*n usec delay */ |
| 465 | 494 | ||
| 466 | #define ATKHLDV 0x11 /* Volume envelope hold and attack register */ | 495 | #define ATKHLDV 0x11 /* Volume envelope hold and attack register */ |
| 467 | #define ATKHLDV_PHASE0 0x00008000 /* 0 = Begin attack phase */ | 496 | #define ATKHLDV_PHASE0_MASK 0x00008000 /* 0 = Begin attack phase */ |
| 468 | #define ATKHLDV_HOLDTIME_MASK 0x00007f00 /* Envelope hold time (127-n == n*88.2msec) */ | 497 | #define ATKHLDV_HOLDTIME_MASK 0x00007f00 /* Envelope hold time (127-n == n*88.2msec) */ |
| 469 | #define ATKHLDV_ATTACKTIME_MASK 0x0000007f /* Envelope attack time, log encoded */ | 498 | #define ATKHLDV_ATTACKTIME_MASK 0x0000007f /* Envelope attack time, log encoded */ |
| 470 | /* 0 = infinite, 1 = 10.9msec, ... 0x7f = 5.5msec */ | 499 | /* 0 = infinite, 1 = 10.9msec, ... 0x7f = 5.5msec */ |
| 471 | 500 | ||
| 472 | #define DCYSUSV 0x12 /* Volume envelope sustain and decay register */ | 501 | #define DCYSUSV 0x12 /* Volume envelope sustain and decay register */ |
| 473 | #define DCYSUSV_PHASE1_MASK 0x00008000 /* 0 = Begin attack phase, 1 = begin release phase */ | 502 | #define DCYSUSV_PHASE1_MASK 0x00008000 /* 0 = Begin decay phase, 1 = begin release phase */ |
| 474 | #define DCYSUSV_SUSTAINLEVEL_MASK 0x00007f00 /* 127 = full, 0 = off, 0.75dB increments */ | 503 | #define DCYSUSV_SUSTAINLEVEL_MASK 0x00007f00 /* 127 = full, 0 = off, 0.75dB increments */ |
| 475 | #define DCYSUSV_CHANNELENABLE_MASK 0x00000080 /* 1 = Inhibit envelope engine from writing values in */ | 504 | #define DCYSUSV_CHANNELENABLE_MASK 0x00000080 /* 0 = Inhibit envelope engine from writing values in */ |
| 476 | /* this channel and from writing to pitch, filter and */ | 505 | /* this channel and from writing to pitch, filter and */ |
| 477 | /* volume targets. */ | 506 | /* volume targets. */ |
| 478 | #define DCYSUSV_DECAYTIME_MASK 0x0000007f /* Volume envelope decay time, log encoded */ | 507 | #define DCYSUSV_DECAYTIME_MASK 0x0000007f /* Volume envelope decay time, log encoded */ |
| @@ -487,13 +516,13 @@ · 8 unmodified lines | |||
| 487 | /* 0x8000-n == 666*n usec delay */ | 516 | /* 0x8000-n == 666*n usec delay */ |
| 488 | 517 | ||
| 489 | #define ATKHLDM 0x15 /* Modulation envelope hold and attack register */ | 518 | #define ATKHLDM 0x15 /* Modulation envelope hold and attack register */ |
| 490 | #define ATKHLDM_PHASE0 0x00008000 /* 0 = Begin attack phase */ | 519 | #define ATKHLDM_PHASE0_MASK 0x00008000 /* 0 = Begin attack phase */ |
| 491 | #define ATKHLDM_HOLDTIME 0x00007f00 /* Envelope hold time (127-n == n*42msec) */ | 520 | #define ATKHLDM_HOLDTIME 0x00007f00 /* Envelope hold time (127-n == n*42msec) */ |
| 492 | #define ATKHLDM_ATTACKTIME 0x0000007f /* Envelope attack time, log encoded */ | 521 | #define ATKHLDM_ATTACKTIME 0x0000007f /* Envelope attack time, log encoded */ |
| 493 | /* 0 = infinite, 1 = 11msec, ... 0x7f = 5.5msec */ | 522 | /* 0 = infinite, 1 = 11msec, ... 0x7f = 5.5msec */ |
| 494 | 523 | ||
| 495 | #define DCYSUSM 0x16 /* Modulation envelope decay and sustain register */ | 524 | #define DCYSUSM 0x16 /* Modulation envelope decay and sustain register */ |
| 496 | #define DCYSUSM_PHASE1_MASK 0x00008000 /* 0 = Begin attack phase, 1 = begin release phase */ | 525 | #define DCYSUSM_PHASE1_MASK 0x00008000 /* 0 = Begin decay phase, 1 = begin release phase */ |
| 497 | #define DCYSUSM_SUSTAINLEVEL_MASK 0x00007f00 /* 127 = full, 0 = off, 0.75dB increments */ | 526 | #define DCYSUSM_SUSTAINLEVEL_MASK 0x00007f00 /* 127 = full, 0 = off, 0.75dB increments */ |
| 498 | #define DCYSUSM_DECAYTIME_MASK 0x0000007f /* Envelope decay time, log encoded */ | 527 | #define DCYSUSM_DECAYTIME_MASK 0x0000007f /* Envelope decay time, log encoded */ |
| 499 | /* 0 = 43.7msec, 1 = 21.8msec, 0x7f = 22msec */ | 528 | /* 0 = 43.7msec, 1 = 21.8msec, 0x7f = 22msec */ |
| @@ -515,7 +544,6 @@ · 15 unmodified lines | |||
| 515 | #define IFATN_ATTENUATION_MASK 0x000000ff /* Initial attenuation in 0.375dB steps */ | 544 | #define IFATN_ATTENUATION_MASK 0x000000ff /* Initial attenuation in 0.375dB steps */ |
| 516 | #define IFATN_ATTENUATION 0x08000019 | 545 | #define IFATN_ATTENUATION 0x08000019 |
| 517 | 546 | ||
| 518 | |||
| 519 | #define PEFE 0x1a /* Pitch envelope and filter envelope amount register */ | 547 | #define PEFE 0x1a /* Pitch envelope and filter envelope amount register */ |
| 520 | #define PEFE_PITCHAMOUNT_MASK 0x0000ff00 /* Pitch envlope amount */ | 548 | #define PEFE_PITCHAMOUNT_MASK 0x0000ff00 /* Pitch envlope amount */ |
| 521 | /* Signed 2's complement, +/- one octave peak extremes */ | 549 | /* Signed 2's complement, +/- one octave peak extremes */ |
| @@ -523,19 +551,19 @@ · 1 unmodified line | |||
| 523 | #define PEFE_FILTERAMOUNT_MASK 0x000000ff /* Filter envlope amount */ | 551 | #define PEFE_FILTERAMOUNT_MASK 0x000000ff /* Filter envlope amount */ |
| 524 | /* Signed 2's complement, +/- six octaves peak extremes */ | 552 | /* Signed 2's complement, +/- six octaves peak extremes */ |
| 525 | #define PEFE_FILTERAMOUNT 0x0800001a | 553 | #define PEFE_FILTERAMOUNT 0x0800001a |
| 554 | |||
| 526 | #define FMMOD 0x1b /* Vibrato/filter modulation from LFO register */ | 555 | #define FMMOD 0x1b /* Vibrato/filter modulation from LFO register */ |
| 527 | #define FMMOD_MODVIBRATO 0x0000ff00 /* Vibrato LFO modulation depth */ | 556 | #define FMMOD_MODVIBRATO 0x0000ff00 /* Vibrato LFO modulation depth */ |
| 528 | /* Signed 2's complement, +/- one octave extremes */ | 557 | /* Signed 2's complement, +/- one octave extremes */ |
| 529 | #define FMMOD_MOFILTER 0x000000ff /* Filter LFO modulation depth */ | 558 | #define FMMOD_MOFILTER 0x000000ff /* Filter LFO modulation depth */ |
| 530 | /* Signed 2's complement, +/- three octave extremes */ | 559 | /* Signed 2's complement, +/- three octave extremes */ |
| 531 | 560 | ||
| 532 | |||
| 533 | #define TREMFRQ 0x1c /* Tremolo amount and modulation LFO frequency register */ | 561 | #define TREMFRQ 0x1c /* Tremolo amount and modulation LFO frequency register */ |
| 534 | #define TREMFRQ_DEPTH 0x0000ff00 /* Tremolo depth */ | 562 | #define TREMFRQ_DEPTH 0x0000ff00 /* Tremolo depth */ |
| 535 | /* Signed 2's complement, with +/- 12dB extremes */ | 563 | /* Signed 2's complement, with +/- 12dB extremes */ |
| 536 | |||
| 537 | #define TREMFRQ_FREQUENCY 0x000000ff /* Tremolo LFO frequency */ | 564 | #define TREMFRQ_FREQUENCY 0x000000ff /* Tremolo LFO frequency */ |
| 538 | /* ??Hz steps, maximum of ?? Hz. */ | 565 | /* ??Hz steps, maximum of ?? Hz. */ |
| 566 | |||
| 539 | #define FM2FRQ2 0x1d /* Vibrato amount and vibrato LFO frequency register */ | 567 | #define FM2FRQ2 0x1d /* Vibrato amount and vibrato LFO frequency register */ |
| 540 | #define FM2FRQ2_DEPTH 0x0000ff00 /* Vibrato LFO vibrato depth */ | 568 | #define FM2FRQ2_DEPTH 0x0000ff00 /* Vibrato LFO vibrato depth */ |
| 541 | /* Signed 2's complement, +/- one octave extremes */ | 569 | /* Signed 2's complement, +/- one octave extremes */ |
| @@ -603,20 +631,6 @@ · 61 unmodified lines | |||
| 603 | /* is 16bit, 48KHz only. All 32 channels can be enabled */ | 631 | /* is 16bit, 48KHz only. All 32 channels can be enabled */ |
| 604 | /* simultaneously. */ | 632 | /* simultaneously. */ |
| 605 | 633 | ||
| 606 | #define FXWC_DEFAULTROUTE_C (1<<0) /* left emu out? */ | ||
| 607 | #define FXWC_DEFAULTROUTE_B (1<<1) /* right emu out? */ | ||
| 608 | #define FXWC_DEFAULTROUTE_A (1<<12) | ||
| 609 | #define FXWC_DEFAULTROUTE_D (1<<13) | ||
| 610 | #define FXWC_ADCLEFT (1<<18) | ||
| 611 | #define FXWC_CDROMSPDIFLEFT (1<<18) | ||
| 612 | #define FXWC_ADCRIGHT (1<<19) | ||
| 613 | #define FXWC_CDROMSPDIFRIGHT (1<<19) | ||
| 614 | #define FXWC_MIC (1<<20) | ||
| 615 | #define FXWC_ZOOMLEFT (1<<20) | ||
| 616 | #define FXWC_ZOOMRIGHT (1<<21) | ||
| 617 | #define FXWC_SPDIFLEFT (1<<22) /* 0x00400000 */ | ||
| 618 | #define FXWC_SPDIFRIGHT (1<<23) /* 0x00800000 */ | ||
| 619 | |||
| 620 | #define A_TBLSZ 0x43 /* Effects Tank Internal Table Size. Only low byte or register used */ | 634 | #define A_TBLSZ 0x43 /* Effects Tank Internal Table Size. Only low byte or register used */ |
| 621 | 635 | ||
| 622 | #define TCBS 0x44 /* Tank cache buffer size register */ | 636 | #define TCBS 0x44 /* Tank cache buffer size register */ |
| @@ -639,7 +653,7 @@ · 16 unmodified lines | |||
| 639 | #define FXBA 0x47 /* FX Buffer Address */ | 653 | #define FXBA 0x47 /* FX Buffer Address */ |
| 640 | #define FXBA_MASK 0xfffff000 /* 20 bit base address */ | 654 | #define FXBA_MASK 0xfffff000 /* 20 bit base address */ |
| 641 | 655 | ||
| 642 | #define A_HWM 0x48 /* High PCI Water Mark - word access, defaults to 3f */ | 656 | #define A_HWM 0x48 /* High PCI Water Mark - word access, defaults to 3f */ |
| 643 | 657 | ||
| 644 | #define MICBS 0x49 /* Microphone buffer size register */ | 658 | #define MICBS 0x49 /* Microphone buffer size register */ |
| 645 | 659 | ||
| @@ -647,9 +661,7 @@ · 1 unmodified line | |||
| 647 | 661 | ||
| 648 | #define FXBS 0x4b /* FX buffer size register */ | 662 | #define FXBS 0x4b /* FX buffer size register */ |
| 649 | 663 | ||
| 650 | /* register: 0x4c..4f: ffff-ffff current amounts, per-channel */ | 664 | /* The following mask values define the size of the ADC, MIC and FX buffers in bytes */ |
| 651 | |||
| 652 | /* The following mask values define the size of the ADC, MIX and FX buffers in bytes */ | ||
| 653 | #define ADCBS_BUFSIZE_NONE 0x00000000 | 665 | #define ADCBS_BUFSIZE_NONE 0x00000000 |
| 654 | #define ADCBS_BUFSIZE_384 0x00000001 | 666 | #define ADCBS_BUFSIZE_384 0x00000001 |
| 655 | #define ADCBS_BUFSIZE_448 0x00000002 | 667 | #define ADCBS_BUFSIZE_448 0x00000002 |
| @@ -683,38 +695,27 @@ · 27 unmodified lines | |||
| 683 | #define ADCBS_BUFSIZE_57344 0x0000001e | 695 | #define ADCBS_BUFSIZE_57344 0x0000001e |
| 684 | #define ADCBS_BUFSIZE_65536 0x0000001f | 696 | #define ADCBS_BUFSIZE_65536 0x0000001f |
| 685 | 697 | ||
| 686 | /* Current Send B, A Amounts */ | 698 | #define A_CSBA 0x4c /* FX send B & A current amounts */ |
| 687 | #define A_CSBA 0x4c | 699 | #define A_CSDC 0x4d /* FX send D & C current amounts */ |
| 688 | 700 | #define A_CSFE 0x4e /* FX send F & E current amounts */ | |
| 689 | /* Current Send D, C Amounts */ | 701 | #define A_CSHG 0x4f /* FX send H & G current amounts */ |
| 690 | #define A_CSDC 0x4d | ||
| 691 | |||
| 692 | /* Current Send F, E Amounts */ | ||
| 693 | #define A_CSFE 0x4e | ||
| 694 | |||
| 695 | /* Current Send H, G Amounts */ | ||
| 696 | #define A_CSHG 0x4f | ||
| 697 | 702 | ||
| 703 | // NOTE: 0x50,51,52: 64-bit (split over voices 0 & 1) | ||
| 704 | #define CDCS 0x50 /* CD-ROM digital channel status register */ | ||
| 698 | 705 | ||
| 699 | #define CDCS 0x50 /* CD-ROM digital channel status register */ | 706 | #define GPSCS 0x51 /* General Purpose SPDIF channel status register */ |
| 700 | 707 | ||
| 701 | #define GPSCS 0x51 /* General Purpose SPDIF channel status register*/ | 708 | // Corresponding EMU10K1_DBG_* constants are in the public header |
| 709 | #define DBG 0x52 | ||
| 702 | 710 | ||
| 703 | #define DBG 0x52 /* DO NOT PROGRAM THIS REGISTER!!! MAY DESTROY CHIP */ | 711 | #define A_SPSC 0x52 /* S/PDIF Input C Channel Status */ |
| 704 | 712 | ||
| 705 | /* S/PDIF Input C Channel Status */ | 713 | #define REG53 0x53 /* DO NOT PROGRAM THIS REGISTER!!! MAY DESTROY CHIP */ |
| 706 | #define A_SPSC 0x52 | ||
| 707 | 714 | ||
| 708 | #define REG53 0x53 /* DO NOT PROGRAM THIS REGISTER!!! MAY DESTROY CHIP */ | 715 | // Corresponding A_DBG_* constants are in the public header |
| 716 | #define A_DBG 0x53 | ||
| 709 | 717 | ||
| 710 | #define A_DBG 0x53 | 718 | // NOTE: 0x54,55,56: 64-bit (split over voices 0 & 1) |
| 711 | #define A_DBG_SINGLE_STEP 0x00020000 /* Set to zero to start dsp */ | ||
| 712 | #define A_DBG_ZC 0x40000000 /* zero tram counter */ | ||
| 713 | #define A_DBG_STEP_ADDR 0x000003ff | ||
| 714 | #define A_DBG_SATURATION_OCCURED 0x20000000 | ||
| 715 | #define A_DBG_SATURATION_ADDR 0x0ffc0000 | ||
| 716 | |||
| 717 | // NOTE: 0x54,55,56: 64-bit | ||
| 718 | #define SPCS0 0x54 /* SPDIF output Channel Status 0 register */ | 719 | #define SPCS0 0x54 /* SPDIF output Channel Status 0 register */ |
| 719 | 720 | ||
| 720 | #define SPCS1 0x55 /* SPDIF output Channel Status 1 register */ | 721 | #define SPCS1 0x55 /* SPDIF output Channel Status 1 register */ |
| @@ -747,17 +748,14 @@ · 26 unmodified lines | |||
| 747 | 748 | ||
| 748 | /* 0x57: Not used */ | 749 | /* 0x57: Not used */ |
| 749 | 750 | ||
| 750 | /* The 32-bit CLIx and SOLx registers all have one bit per channel control/status */ | 751 | /* The 32-bit CLIx and SOLEx registers all have one bit per channel control/status */ |
| 751 | #define CLIEL 0x58 /* Channel loop interrupt enable low register */ | 752 | #define CLIEL 0x58 /* Channel loop interrupt enable low register */ |
| 752 | |||
| 753 | #define CLIEH 0x59 /* Channel loop interrupt enable high register */ | 753 | #define CLIEH 0x59 /* Channel loop interrupt enable high register */ |
| 754 | 754 | ||
| 755 | #define CLIPL 0x5a /* Channel loop interrupt pending low register */ | 755 | #define CLIPL 0x5a /* Channel loop interrupt pending low register */ |
| 756 | |||
| 757 | #define CLIPH 0x5b /* Channel loop interrupt pending high register */ | 756 | #define CLIPH 0x5b /* Channel loop interrupt pending high register */ |
| 758 | 757 | ||
| 759 | #define SOLEL 0x5c /* Stop on loop enable low register */ | 758 | #define SOLEL 0x5c /* Stop on loop enable low register */ |
| 760 | |||
| 761 | #define SOLEH 0x5d /* Stop on loop enable high register */ | 759 | #define SOLEH 0x5d /* Stop on loop enable high register */ |
| 762 | 760 | ||
| 763 | #define SPBYPASS 0x5e /* SPDIF BYPASS mode register */ | 761 | #define SPBYPASS 0x5e /* SPDIF BYPASS mode register */ |
| @@ -767,13 +765,12 @@ · 3 unmodified lines | |||
| 767 | #define SPBYPASS_FORMAT 0x00000f00 /* If 1, SPDIF XX uses 24 bit, if 0 - 20 bit */ | 765 | #define SPBYPASS_FORMAT 0x00000f00 /* If 1, SPDIF XX uses 24 bit, if 0 - 20 bit */ |
| 768 | 766 | ||
| 769 | #define AC97SLOT 0x5f /* additional AC97 slots enable bits */ | 767 | #define AC97SLOT 0x5f /* additional AC97 slots enable bits */ |
| 770 | #define AC97SLOT_REAR_RIGHT 0x01 /* Rear left */ | 768 | #define AC97SLOT_REAR_RIGHT 0x01 /* Rear left */ |
| 771 | #define AC97SLOT_REAR_LEFT 0x02 /* Rear right */ | 769 | #define AC97SLOT_REAR_LEFT 0x02 /* Rear right */ |
| 772 | #define AC97SLOT_CNTR 0x10 /* Center enable */ | 770 | #define AC97SLOT_CNTR 0x10 /* Center enable */ |
| 773 | #define AC97SLOT_LFE 0x20 /* LFE enable */ | 771 | #define AC97SLOT_LFE 0x20 /* LFE enable */ |
| 774 | 772 | ||
| 775 | /* PCB Revision */ | 773 | #define A_PCB 0x5f /* PCB Revision */ |
| 776 | #define A_PCB 0x5f | ||
| 777 | 774 | ||
| 778 | // NOTE: 0x60,61,62: 64-bit | 775 | // NOTE: 0x60,61,62: 64-bit |
| 779 | #define CDSRCS 0x60 /* CD-ROM Sample Rate Converter status register */ | 776 | #define CDSRCS 0x60 /* CD-ROM Sample Rate Converter status register */ |
| @@ -813,27 +810,21 @@ · 33 unmodified lines | |||
| 813 | #define FXIDX_MASK 0x0000ffff /* 16-bit value */ | 810 | #define FXIDX_MASK 0x0000ffff /* 16-bit value */ |
| 814 | #define FXIDX_IDX 0x10000065 | 811 | #define FXIDX_IDX 0x10000065 |
| 815 | 812 | ||
| 816 | /* The 32-bit HLIx and HLIPx registers all have one bit per channel control/status */ | 813 | /* The 32-bit HLIEx and HLIPx registers all have one bit per channel control/status */ |
| 817 | #define HLIEL 0x66 /* Channel half loop interrupt enable low register */ | 814 | #define HLIEL 0x66 /* Channel half loop interrupt enable low register */ |
| 818 | |||
| 819 | #define HLIEH 0x67 /* Channel half loop interrupt enable high register */ | 815 | #define HLIEH 0x67 /* Channel half loop interrupt enable high register */ |
| 820 | 816 | ||
| 821 | #define HLIPL 0x68 /* Channel half loop interrupt pending low register */ | 817 | #define HLIPL 0x68 /* Channel half loop interrupt pending low register */ |
| 822 | |||
| 823 | #define HLIPH 0x69 /* Channel half loop interrupt pending high register */ | 818 | #define HLIPH 0x69 /* Channel half loop interrupt pending high register */ |
| 824 | 819 | ||
| 825 | /* S/PDIF Host Record Index (bypasses SRC) */ | 820 | #define A_SPRI 0x6a /* S/PDIF Host Record Index (bypasses SRC) */ |
| 826 | #define A_SPRI 0x6a | 821 | #define A_SPRA 0x6b /* S/PDIF Host Record Address */ |
| 827 | /* S/PDIF Host Record Address */ | 822 | #define A_SPRC 0x6c /* S/PDIF Host Record Control */ |
| 828 | #define A_SPRA 0x6b | 823 | |
| 829 | /* S/PDIF Host Record Control */ | 824 | #define A_DICE 0x6d /* Delayed Interrupt Counter & Enable */ |
| 830 | #define A_SPRC 0x6c | 825 | |
| 831 | /* Delayed Interrupt Counter & Enable */ | 826 | #define A_TTB 0x6e /* Tank Table Base */ |
| 832 | #define A_DICE 0x6d | 827 | #define A_TDOF 0x6f /* Tank Delay Offset */ |
| 833 | /* Tank Table Base */ | ||
| 834 | #define A_TTB 0x6e | ||
| 835 | /* Tank Delay Offset */ | ||
| 836 | #define A_TDOF 0x6f | ||
| 837 | 828 | ||
| 838 | /* This is the MPU port on the card (via the game port) */ | 829 | /* This is the MPU port on the card (via the game port) */ |
| 839 | #define A_MUDATA1 0x70 | 830 | #define A_MUDATA1 0x70 |
| @@ -846,48 +837,53 @@ · 6 unmodified lines | |||
| 846 | #define A_MUSTAT2 A_MUCMD2 | 837 | #define A_MUSTAT2 A_MUCMD2 |
| 847 | 838 | ||
| 848 | /* The next two are the Audigy equivalent of FXWC */ | 839 | /* The next two are the Audigy equivalent of FXWC */ |
| 849 | /* the Audigy can record any output (16bit, 48kHz, up to 64 channel simultaneously) */ | 840 | /* the Audigy can record any output (16bit, 48kHz, up to 64 channels simultaneously) */ |
| 850 | /* Each bit selects a channel for recording */ | 841 | /* Each bit selects a channel for recording */ |
| 851 | #define A_FXWC1 0x74 /* Selects 0x7f-0x60 for FX recording */ | 842 | #define A_FXWC1 0x74 /* Selects 0x7f-0x60 for FX recording */ |
| 852 | #define A_FXWC2 0x75 /* Selects 0x9f-0x80 for FX recording */ | 843 | #define A_FXWC2 0x75 /* Selects 0x9f-0x80 for FX recording */ |
| 853 | 844 | ||
| 854 | /* Extended Hardware Control */ | 845 | #define A_EHC 0x76 /* Extended Hardware Control */ |
| 855 | #define A_SPDIF_SAMPLERATE 0x76 /* Set the sample rate of SPDIF output */ | 846 | |
| 856 | #define A_SAMPLE_RATE 0x76 /* Various sample rate settings. */ | 847 | #define A_SPDIF_SAMPLERATE A_EHC /* Set the sample rate of SPDIF output */ |
| 857 | #define A_SAMPLE_RATE_NOT_USED 0x0ffc111e /* Bits that are not used and cannot be set. */ | ||
| 858 | #define A_SAMPLE_RATE_UNKNOWN 0xf0030001 /* Bits that can be set, but have unknown use. */ | ||
| 859 | #define A_SPDIF_RATE_MASK 0x000000e0 /* Any other values for rates, just use 48000 */ | 848 | #define A_SPDIF_RATE_MASK 0x000000e0 /* Any other values for rates, just use 48000 */ |
| 860 | #define A_SPDIF_48000 0x00000000 | 849 | #define A_SPDIF_48000 0x00000000 /* kX calls this BYPASS */ |
| 861 | #define A_SPDIF_192000 0x00000020 | 850 | #define A_SPDIF_192000 0x00000020 |
| 862 | #define A_SPDIF_96000 0x00000040 | 851 | #define A_SPDIF_96000 0x00000040 |
| 863 | #define A_SPDIF_44100 0x00000080 | 852 | #define A_SPDIF_44100 0x00000080 |
| 853 | #define A_SPDIF_MUTED 0x000000c0 | ||
| 864 | 854 | ||
| 865 | #define A_I2S_CAPTURE_RATE_MASK 0x00000e00 /* This sets the capture PCM rate, but it is */ | 855 | #define A_I2S_CAPTURE_RATE_MASK 0x00000e00 /* This sets the capture PCM rate, but it is */ |
| 866 | #define A_I2S_CAPTURE_48000 0x00000000 /* unclear if this sets the ADC rate as well. */ | 856 | #define A_I2S_CAPTURE_RATE 0x03090076 /* unclear if this sets the ADC rate as well. */ |
| 867 | #define A_I2S_CAPTURE_192000 0x00000200 | 857 | #define A_I2S_CAPTURE_48000 0x0 |
| 868 | #define A_I2S_CAPTURE_96000 0x00000400 | 858 | #define A_I2S_CAPTURE_192000 0x1 |
| 869 | #define A_I2S_CAPTURE_44100 0x00000800 | 859 | #define A_I2S_CAPTURE_96000 0x2 |
| 870 | 860 | #define A_I2S_CAPTURE_44100 0x4 | |
| 871 | #define A_PCM_RATE_MASK 0x0000e000 /* This sets the playback PCM rate on the P16V */ | 861 | |
| 872 | #define A_PCM_48000 0x00000000 | 862 | #define A_EHC_SRC48_MASK 0x0000e000 /* This sets the playback PCM rate on the P16V */ |
| 873 | #define A_PCM_192000 0x00002000 | 863 | #define A_EHC_SRC48_BYPASS 0x00000000 |
| 874 | #define A_PCM_96000 0x00004000 | 864 | #define A_EHC_SRC48_192 0x00002000 |
| 875 | #define A_PCM_44100 0x00008000 | 865 | #define A_EHC_SRC48_96 0x00004000 |
| 876 | 866 | #define A_EHC_SRC48_44 0x00008000 | |
| 877 | /* I2S0 Sample Rate Tracker Status */ | 867 | #define A_EHC_SRC48_MUTED 0x0000c000 |
| 878 | #define A_SRT3 0x77 | 868 | |
| 879 | 869 | #define A_EHC_P17V_TVM 0x00000001 /* Tank virtual memory mode */ | |
| 880 | /* I2S1 Sample Rate Tracker Status */ | 870 | #define A_EHC_P17V_SEL0_MASK 0x00030000 /* Aka A_EHC_P16V_PB_RATE; 00: 48, 01: 44.1, 10: 96, 11: 192 */ |
| 881 | #define A_SRT4 0x78 | 871 | #define A_EHC_P17V_SEL1_MASK 0x000c0000 |
| 882 | 872 | #define A_EHC_P17V_SEL2_MASK 0x00300000 | |
| 883 | /* I2S2 Sample Rate Tracker Status */ | 873 | #define A_EHC_P17V_SEL3_MASK 0x00c00000 |
| 884 | #define A_SRT5 0x79 | 874 | |
| 875 | #define A_EHC_ASYNC_BYPASS 0x80000000 | ||
| 876 | |||
| 877 | #define A_SRT3 0x77 /* I2S0 Sample Rate Tracker Status */ | ||
| 878 | #define A_SRT4 0x78 /* I2S1 Sample Rate Tracker Status */ | ||
| 879 | #define A_SRT5 0x79 /* I2S2 Sample Rate Tracker Status */ | ||
| 885 | /* - default to 0x01080000 on my audigy 2 ZS --rlrevell */ | 880 | /* - default to 0x01080000 on my audigy 2 ZS --rlrevell */ |
| 886 | 881 | ||
| 887 | /* Tank Table DMA Address */ | 882 | #define A_SRT_ESTSAMPLERATE 0x001fffff |
| 888 | #define A_TTDA 0x7a | 883 | #define A_SRT_RATELOCKED 0x01000000 |
| 889 | /* Tank Table DMA Data */ | 884 | |
| 890 | #define A_TTDD 0x7b | 885 | #define A_TTDA 0x7a /* Tank Table DMA Address */ |
| 886 | #define A_TTDD 0x7b /* Tank Table DMA Data */ | ||
| 891 | 887 | ||
| 892 | #define A_FXRT2 0x7c | 888 | #define A_FXRT2 0x7c |
| 893 | #define A_FXRT_CHANNELE 0x0000003f /* Effects send bus number for channel's effects send E */ | 889 | #define A_FXRT_CHANNELE 0x0000003f /* Effects send bus number for channel's effects send E */ |
| @@ -900,6 +896,7 @@ · 6 unmodified lines | |||
| 900 | #define A_FXSENDAMOUNT_F_MASK 0x00FF0000 | 896 | #define A_FXSENDAMOUNT_F_MASK 0x00FF0000 |
| 901 | #define A_FXSENDAMOUNT_G_MASK 0x0000FF00 | 897 | #define A_FXSENDAMOUNT_G_MASK 0x0000FF00 |
| 902 | #define A_FXSENDAMOUNT_H_MASK 0x000000FF | 898 | #define A_FXSENDAMOUNT_H_MASK 0x000000FF |
| 899 | |||
| 903 | /* 0x7c, 0x7e "high bit is used for filtering" */ | 900 | /* 0x7c, 0x7e "high bit is used for filtering" */ |
| 904 | 901 | ||
| 905 | /* The send amounts for this one are the same as used with the emu10k1 */ | 902 | /* The send amounts for this one are the same as used with the emu10k1 */ |
| @@ -910,55 +907,56 @@ · 4 unmodified lines | |||
| 910 | #define A_FXRT_CHANNELD 0x3f000000 | 907 | #define A_FXRT_CHANNELD 0x3f000000 |
| 911 | 908 | ||
| 912 | /* 0x7f: Not used */ | 909 | /* 0x7f: Not used */ |
| 913 | /* Each FX general purpose register is 32 bits in length, all bits are used */ | ||
| 914 | #define FXGPREGBASE 0x100 /* FX general purpose registers base */ | ||
| 915 | #define A_FXGPREGBASE 0x400 /* Audigy GPRs, 0x400 to 0x5ff */ | ||
| 916 | |||
| 917 | #define A_TANKMEMCTLREGBASE 0x100 /* Tank memory control registers base - only for Audigy */ | ||
| 918 | #define A_TANKMEMCTLREG_MASK 0x1f /* only 5 bits used - only for Audigy */ | ||
| 919 | |||
| 920 | /* Tank audio data is logarithmically compressed down to 16 bits before writing to TRAM and is */ | ||
| 921 | /* decompressed back to 20 bits on a read. There are a total of 160 locations, the last 32 */ | ||
| 922 | /* locations are for external TRAM. */ | ||
| 923 | #define TANKMEMDATAREGBASE 0x200 /* Tank memory data registers base */ | ||
| 924 | #define TANKMEMDATAREG_MASK 0x000fffff /* 20 bit tank audio data field */ | ||
| 925 | |||
| 926 | /* Combined address field and memory opcode or flag field. 160 locations, last 32 are external */ | ||
| 927 | #define TANKMEMADDRREGBASE 0x300 /* Tank memory address registers base */ | ||
| 928 | #define TANKMEMADDRREG_ADDR_MASK 0x000fffff /* 20 bit tank address field */ | ||
| 929 | #define TANKMEMADDRREG_CLEAR 0x00800000 /* Clear tank memory */ | ||
| 930 | #define TANKMEMADDRREG_ALIGN 0x00400000 /* Align read or write relative to tank access */ | ||
| 931 | #define TANKMEMADDRREG_WRITE 0x00200000 /* Write to tank memory */ | ||
| 932 | #define TANKMEMADDRREG_READ 0x00100000 /* Read from tank memory */ | ||
| 933 | 910 | ||
| 934 | #define MICROCODEBASE 0x400 /* Microcode data base address */ | 911 | /* The public header defines the GPR and TRAM base addresses that |
| 912 | * are valid for _both_ CPU and DSP addressing. */ | ||
| 935 | 913 | ||
| 936 | /* Each DSP microcode instruction is mapped into 2 doublewords */ | 914 | /* Each DSP microcode instruction is mapped into 2 doublewords */ |
| 937 | /* NOTE: When writing, always write the LO doubleword first. Reads can be in either order. */ | 915 | /* NOTE: When writing, always write the LO doubleword first. Reads can be in either order. */ |
| 938 | #define LOWORD_OPX_MASK 0x000ffc00 /* Instruction operand X */ | 916 | #define MICROCODEBASE 0x400 /* Microcode data base address */ |
| 939 | #define LOWORD_OPY_MASK 0x000003ff /* Instruction operand Y */ | 917 | #define A_MICROCODEBASE 0x600 |
| 940 | #define HIWORD_OPCODE_MASK 0x00f00000 /* Instruction opcode */ | ||
| 941 | #define HIWORD_RESULT_MASK 0x000ffc00 /* Instruction result */ | ||
| 942 | #define HIWORD_OPA_MASK 0x000003ff /* Instruction operand A */ | ||
| 943 | 918 | ||
| 944 | 919 | ||
| 945 | /* Audigy Soundcard have a different instruction format */ | 920 | /************************************************************************************************/ |
| 946 | #define A_MICROCODEBASE 0x600 | 921 | /* E-MU Digital Audio System overview */ |
| 947 | #define A_LOWORD_OPY_MASK 0x000007ff | 922 | /************************************************************************************************/ |
| 948 | #define A_LOWORD_OPX_MASK 0x007ff000 | 923 | |
| 949 | #define A_HIWORD_OPCODE_MASK 0x0f000000 | 924 | // - These cards use a regular PCI-attached Audigy chip (Alice2/Tina/Tina2); |
| 950 | #define A_HIWORD_RESULT_MASK 0x007ff000 | 925 | // the PCIe variants simply put the Audigy chip behind a PCI bridge. |
| 951 | #define A_HIWORD_OPA_MASK 0x000007ff | 926 | // - All physical PCM I/O is routed through an additional FPGA; the regular |
| 927 | // EXTIN/EXTOUT ports are unconnected. | ||
| 928 | // - The FPGA has a signal routing matrix, to connect each destination (output | ||
| 929 | // socket or capture channel) to a source (input socket or playback channel). | ||
| 930 | // - The FPGA is controlled via Audigy's GPIO port, while sample data is | ||
| 931 | // transmitted via proprietary EMU32 serial links. On first-generation | ||
| 932 | // E-MU 1010 cards, Audigy's I2S inputs are also used for sample data. | ||
| 933 | // - The Audio/Micro Dock is attached to Hana via EDI, a "network" link. | ||
| 934 | // - The Audigy chip operates in slave mode; the clock is supplied by the FPGA. | ||
| 935 | // Gen1 E-MU 1010 cards have two crystals (for 44.1 kHz and 48 kHz multiples), | ||
| 936 | // while the later cards use a single crystal and a PLL chip. | ||
| 937 | // - The whole card is switched to 2x/4x mode to achieve 88.2/96/176.4/192 kHz | ||
| 938 | // sample rates. Alice2/Tina keeps running at 44.1/48 kHz, but multiple channels | ||
| 939 | // are bundled. | ||
| 940 | // - The number of available EMU32/EDI channels is hit in 2x/4x mode, so the total | ||
| 941 | // number of usable inputs/outputs is limited, esp. with ADAT in use. | ||
| 942 | // - S/PDIF is unavailable in 4x mode (only over TOSLINK on newer 1010 cards) due | ||
| 943 | // to being unspecified at 176.4/192 kHz. Therefore, the Dock's S/PDIF channels | ||
| 944 | // can overlap with the Dock's ADC/DAC's high channels. | ||
| 945 | // - The code names are mentioned below and in the emu_chip_details table. | ||
| 952 | 946 | ||
| 953 | /************************************************************************************************/ | 947 | /************************************************************************************************/ |
| 954 | /* EMU1010m HANA FPGA registers */ | 948 | /* EMU1010 FPGA registers */ |
| 955 | /************************************************************************************************/ | 949 | /************************************************************************************************/ |
| 950 | |||
| 956 | #define EMU_HANA_DESTHI 0x00 /* 0000xxx 3 bits Link Destination */ | 951 | #define EMU_HANA_DESTHI 0x00 /* 0000xxx 3 bits Link Destination */ |
| 957 | #define EMU_HANA_DESTLO 0x01 /* 00xxxxx 5 bits */ | 952 | #define EMU_HANA_DESTLO 0x01 /* 00xxxxx 5 bits */ |
| 953 | |||
| 958 | #define EMU_HANA_SRCHI 0x02 /* 0000xxx 3 bits Link Source */ | 954 | #define EMU_HANA_SRCHI 0x02 /* 0000xxx 3 bits Link Source */ |
| 959 | #define EMU_HANA_SRCLO 0x03 /* 00xxxxx 5 bits */ | 955 | #define EMU_HANA_SRCLO 0x03 /* 00xxxxx 5 bits */ |
| 956 | |||
| 960 | #define EMU_HANA_DOCK_PWR 0x04 /* 000000x 1 bits Audio Dock power */ | 957 | #define EMU_HANA_DOCK_PWR 0x04 /* 000000x 1 bits Audio Dock power */ |
| 961 | #define EMU_HANA_DOCK_PWR_ON 0x01 /* Audio Dock power on */ | 958 | #define EMU_HANA_DOCK_PWR_ON 0x01 /* Audio Dock power on */ |
| 959 | |||
| 962 | #define EMU_HANA_WCLOCK 0x05 /* 0000xxx 3 bits Word Clock source select */ | 960 | #define EMU_HANA_WCLOCK 0x05 /* 0000xxx 3 bits Word Clock source select */ |
| 963 | /* Must be written after power on to reset DLL */ | 961 | /* Must be written after power on to reset DLL */ |
| 964 | /* One is unable to detect the Audio dock without this */ | 962 | /* One is unable to detect the Audio dock without this */ |
| @@ -967,7 +965,7 @@ · 2 unmodified lines | |||
| 967 | #define EMU_HANA_WCLOCK_INT_44_1K 0x01 | 965 | #define EMU_HANA_WCLOCK_INT_44_1K 0x01 |
| 968 | #define EMU_HANA_WCLOCK_HANA_SPDIF_IN 0x02 | 966 | #define EMU_HANA_WCLOCK_HANA_SPDIF_IN 0x02 |
| 969 | #define EMU_HANA_WCLOCK_HANA_ADAT_IN 0x03 | 967 | #define EMU_HANA_WCLOCK_HANA_ADAT_IN 0x03 |
| 970 | #define EMU_HANA_WCLOCK_SYNC_BNCN 0x04 | 968 | #define EMU_HANA_WCLOCK_SYNC_BNC 0x04 |
| 971 | #define EMU_HANA_WCLOCK_2ND_HANA 0x05 | 969 | #define EMU_HANA_WCLOCK_2ND_HANA 0x05 |
| 972 | #define EMU_HANA_WCLOCK_SRC_RESERVED 0x06 | 970 | #define EMU_HANA_WCLOCK_SRC_RESERVED 0x06 |
| 973 | #define EMU_HANA_WCLOCK_OFF 0x07 /* For testing, forces fallback to DEFCLOCK */ | 971 | #define EMU_HANA_WCLOCK_OFF 0x07 /* For testing, forces fallback to DEFCLOCK */ |
| @@ -996,10 +994,10 @@ · 22 unmodified lines | |||
| 996 | #define EMU_HANA_IRQ_DOCK_LOST 0x08 | 994 | #define EMU_HANA_IRQ_DOCK_LOST 0x08 |
| 997 | 995 | ||
| 998 | #define EMU_HANA_SPDIF_MODE 0x0a /* 00xxxxx 5 bits SPDIF MODE */ | 996 | #define EMU_HANA_SPDIF_MODE 0x0a /* 00xxxxx 5 bits SPDIF MODE */ |
| 999 | #define EMU_HANA_SPDIF_MODE_TX_COMSUMER 0x00 | 997 | #define EMU_HANA_SPDIF_MODE_TX_CONSUMER 0x00 |
| 1000 | #define EMU_HANA_SPDIF_MODE_TX_PRO 0x01 | 998 | #define EMU_HANA_SPDIF_MODE_TX_PRO 0x01 |
| 1001 | #define EMU_HANA_SPDIF_MODE_TX_NOCOPY 0x02 | 999 | #define EMU_HANA_SPDIF_MODE_TX_NOCOPY 0x02 |
| 1002 | #define EMU_HANA_SPDIF_MODE_RX_COMSUMER 0x00 | 1000 | #define EMU_HANA_SPDIF_MODE_RX_CONSUMER 0x00 |
| 1003 | #define EMU_HANA_SPDIF_MODE_RX_PRO 0x04 | 1001 | #define EMU_HANA_SPDIF_MODE_RX_PRO 0x04 |
| 1004 | #define EMU_HANA_SPDIF_MODE_RX_NOCOPY 0x08 | 1002 | #define EMU_HANA_SPDIF_MODE_RX_NOCOPY 0x08 |
| 1005 | #define EMU_HANA_SPDIF_MODE_RX_INVALID 0x10 | 1003 | #define EMU_HANA_SPDIF_MODE_RX_INVALID 0x10 |
| @@ -1011,8 +1009,12 @@ · 5 unmodified lines | |||
| 1011 | #define EMU_HANA_OPTICAL_OUT_ADAT 0x02 | 1009 | #define EMU_HANA_OPTICAL_OUT_ADAT 0x02 |
| 1012 | 1010 | ||
| 1013 | #define EMU_HANA_MIDI_IN 0x0c /* 000000x 1 bit Control MIDI */ | 1011 | #define EMU_HANA_MIDI_IN 0x0c /* 000000x 1 bit Control MIDI */ |
| 1014 | #define EMU_HANA_MIDI_IN_FROM_HAMOA 0x00 /* HAMOA MIDI in to Alice 2 MIDI B */ | 1012 | #define EMU_HANA_MIDI_INA_FROM_HAMOA 0x01 /* HAMOA MIDI in to Alice 2 MIDI A */ |
| 1015 | #define EMU_HANA_MIDI_IN_FROM_DOCK 0x01 /* Audio Dock MIDI in to Alice 2 MIDI B */ | 1013 | #define EMU_HANA_MIDI_INA_FROM_DOCK1 0x02 /* Audio Dock-1 MIDI in to Alice 2 MIDI A */ |
| 1014 | #define EMU_HANA_MIDI_INA_FROM_DOCK2 0x03 /* Audio Dock-2 MIDI in to Alice 2 MIDI A */ | ||
| 1015 | #define EMU_HANA_MIDI_INB_FROM_HAMOA 0x08 /* HAMOA MIDI in to Alice 2 MIDI B */ | ||
| 1016 | #define EMU_HANA_MIDI_INB_FROM_DOCK1 0x10 /* Audio Dock-1 MIDI in to Alice 2 MIDI B */ | ||
| 1017 | #define EMU_HANA_MIDI_INB_FROM_DOCK2 0x18 /* Audio Dock-2 MIDI in to Alice 2 MIDI B */ | ||
| 1016 | 1018 | ||
| 1017 | #define EMU_HANA_DOCK_LEDS_1 0x0d /* 000xxxx 4 bit Audio Dock LEDs */ | 1019 | #define EMU_HANA_DOCK_LEDS_1 0x0d /* 000xxxx 4 bit Audio Dock LEDs */ |
| 1018 | #define EMU_HANA_DOCK_LEDS_1_MIDI1 0x01 /* MIDI 1 LED on */ | 1020 | #define EMU_HANA_DOCK_LEDS_1_MIDI1 0x01 /* MIDI 1 LED on */ |
| @@ -1037,51 +1039,49 @@ · 18 unmodified lines | |||
| 1037 | #define EMU_HANA_DOCK_LEDS_3_MANUAL_SIGNAL 0x20 /* Manual Signal detection */ | 1039 | #define EMU_HANA_DOCK_LEDS_3_MANUAL_SIGNAL 0x20 /* Manual Signal detection */ |
| 1038 | 1040 | ||
| 1039 | #define EMU_HANA_ADC_PADS 0x10 /* 0000xxx 3 bit Audio Dock ADC 14dB pads */ | 1041 | #define EMU_HANA_ADC_PADS 0x10 /* 0000xxx 3 bit Audio Dock ADC 14dB pads */ |
| 1040 | #define EMU_HANA_DOCK_ADC_PAD1 0x01 /* 14dB Attenuation on Audio Dock ADC 1 */ | 1042 | #define EMU_HANA_DOCK_ADC_PAD1 0x01 /* 14dB Attenuation on Audio Dock ADC 1 */ |
| 1041 | #define EMU_HANA_DOCK_ADC_PAD2 0x02 /* 14dB Attenuation on Audio Dock ADC 2 */ | 1043 | #define EMU_HANA_DOCK_ADC_PAD2 0x02 /* 14dB Attenuation on Audio Dock ADC 2 */ |
| 1042 | #define EMU_HANA_DOCK_ADC_PAD3 0x04 /* 14dB Attenuation on Audio Dock ADC 3 */ | 1044 | #define EMU_HANA_DOCK_ADC_PAD3 0x04 /* 14dB Attenuation on Audio Dock ADC 3 */ |
| 1043 | #define EMU_HANA_0202_ADC_PAD1 0x08 /* 14dB Attenuation on 0202 ADC 1 */ | 1045 | #define EMU_HANA_0202_ADC_PAD1 0x08 /* 14dB Attenuation on 0202 ADC 1 */ |
| 1044 | 1046 | ||
| 1045 | #define EMU_HANA_DOCK_MISC 0x11 /* 0xxxxxx 6 bit Audio Dock misc bits */ | 1047 | #define EMU_HANA_DOCK_MISC 0x11 /* 0xxxxxx 6 bit Audio Dock misc bits */ |
| 1046 | #define EMU_HANA_DOCK_DAC1_MUTE 0x01 /* DAC 1 Mute */ | 1048 | #define EMU_HANA_DOCK_DAC1_MUTE 0x01 /* DAC 1 Mute */ |
| 1047 | #define EMU_HANA_DOCK_DAC2_MUTE 0x02 /* DAC 2 Mute */ | 1049 | #define EMU_HANA_DOCK_DAC2_MUTE 0x02 /* DAC 2 Mute */ |
| 1048 | #define EMU_HANA_DOCK_DAC3_MUTE 0x04 /* DAC 3 Mute */ | 1050 | #define EMU_HANA_DOCK_DAC3_MUTE 0x04 /* DAC 3 Mute */ |
| 1049 | #define EMU_HANA_DOCK_DAC4_MUTE 0x08 /* DAC 4 Mute */ | 1051 | #define EMU_HANA_DOCK_DAC4_MUTE 0x08 /* DAC 4 Mute */ |
| 1050 | #define EMU_HANA_DOCK_PHONES_192_DAC1 0x00 /* DAC 1 Headphones source at 192kHz */ | 1052 | #define EMU_HANA_DOCK_PHONES_192_DAC1 0x00 /* DAC 1 Headphones source at 192kHz */ |
| 1051 | #define EMU_HANA_DOCK_PHONES_192_DAC2 0x10 /* DAC 2 Headphones source at 192kHz */ | 1053 | #define EMU_HANA_DOCK_PHONES_192_DAC2 0x10 /* DAC 2 Headphones source at 192kHz */ |
| 1052 | #define EMU_HANA_DOCK_PHONES_192_DAC3 0x20 /* DAC 3 Headphones source at 192kHz */ | 1054 | #define EMU_HANA_DOCK_PHONES_192_DAC3 0x20 /* DAC 3 Headphones source at 192kHz */ |
| 1053 | #define EMU_HANA_DOCK_PHONES_192_DAC4 0x30 /* DAC 4 Headphones source at 192kHz */ | 1055 | #define EMU_HANA_DOCK_PHONES_192_DAC4 0x30 /* DAC 4 Headphones source at 192kHz */ |
| 1054 | 1056 | ||
| 1055 | #define EMU_HANA_MIDI_OUT 0x12 /* 00xxxxx 5 bit Source for each MIDI out port */ | 1057 | #define EMU_HANA_MIDI_OUT 0x12 /* 00xxxxx 5 bit Source for each MIDI out port */ |
| 1056 | #define EMU_HANA_MIDI_OUT_0202 0x01 /* 0202 MIDI from Alice 2. 0 = A, 1 = B */ | 1058 | #define EMU_HANA_MIDI_OUT_0202 0x01 /* 0202 MIDI from Alice 2. 0 = A, 1 = B */ |
| 1057 | #define EMU_HANA_MIDI_OUT_DOCK1 0x02 /* Audio Dock MIDI1 front, from Alice 2. 0 = A, 1 = B */ | 1059 | #define EMU_HANA_MIDI_OUT_DOCK1 0x02 /* Audio Dock MIDI1 front, from Alice 2. 0 = A, 1 = B */ |
| 1058 | #define EMU_HANA_MIDI_OUT_DOCK2 0x04 /* Audio Dock MIDI2 rear, from Alice 2. 0 = A, 1 = B */ | 1060 | #define EMU_HANA_MIDI_OUT_DOCK2 0x04 /* Audio Dock MIDI2 rear, from Alice 2. 0 = A, 1 = B */ |
| 1059 | #define EMU_HANA_MIDI_OUT_SYNC2 0x08 /* Sync card. Not the actual MIDI out jack. 0 = A, 1 = B */ | 1061 | #define EMU_HANA_MIDI_OUT_SYNC2 0x08 /* Sync card. Not the actual MIDI out jack. 0 = A, 1 = B */ |
| 1060 | #define EMU_HANA_MIDI_OUT_LOOP 0x10 /* 0 = bits (3:0) normal. 1 = MIDI loopback enabled. */ | 1062 | #define EMU_HANA_MIDI_OUT_LOOP 0x10 /* 0 = bits (3:0) normal. 1 = MIDI loopback enabled. */ |
| 1061 | 1063 | ||
| 1062 | #define EMU_HANA_DAC_PADS 0x13 /* 00xxxxx 5 bit DAC 14dB attenuation pads */ | 1064 | #define EMU_HANA_DAC_PADS 0x13 /* 00xxxxx 5 bit DAC 14dB attenuation pads */ |
| 1063 | #define EMU_HANA_DOCK_DAC_PAD1 0x01 /* 14dB Attenuation on AudioDock DAC 1. Left and Right */ | 1065 | #define EMU_HANA_DOCK_DAC_PAD1 0x01 /* 14dB Attenuation on AudioDock DAC 1. Left and Right */ |
| 1064 | #define EMU_HANA_DOCK_DAC_PAD2 0x02 /* 14dB Attenuation on AudioDock DAC 2. Left and Right */ | 1066 | #define EMU_HANA_DOCK_DAC_PAD2 0x02 /* 14dB Attenuation on AudioDock DAC 2. Left and Right */ |
| 1065 | #define EMU_HANA_DOCK_DAC_PAD3 0x04 /* 14dB Attenuation on AudioDock DAC 3. Left and Right */ | 1067 | #define EMU_HANA_DOCK_DAC_PAD3 0x04 /* 14dB Attenuation on AudioDock DAC 3. Left and Right */ |
| 1066 | #define EMU_HANA_DOCK_DAC_PAD4 0x08 /* 14dB Attenuation on AudioDock DAC 4. Left and Right */ | 1068 | #define EMU_HANA_DOCK_DAC_PAD4 0x08 /* 14dB Attenuation on AudioDock DAC 4. Left and Right */ |
| 1067 | #define EMU_HANA_0202_DAC_PAD1 0x10 /* 14dB Attenuation on 0202 DAC 1. Left and Right */ | 1069 | #define EMU_HANA_0202_DAC_PAD1 0x10 /* 14dB Attenuation on 0202 DAC 1. Left and Right */ |
| 1068 | 1070 | ||
| 1069 | /* 0x14 - 0x1f Unused R/W registers */ | 1071 | /* 0x14 - 0x1f Unused R/W registers */ |
| 1070 | #define EMU_HANA_IRQ_STATUS 0x20 /* 000xxxx 4 bits IRQ Status */ | 1072 | |
| 1071 | #if 0 /* Already defined for reg 0x09 IRQ_ENABLE */ | 1073 | #define EMU_HANA_IRQ_STATUS 0x20 /* 00xxxxx 5 bits IRQ Status */ |
| 1072 | #define EMU_HANA_IRQ_WCLK_CHANGED 0x01 | 1074 | /* Same bits as for EMU_HANA_IRQ_ENABLE */ |
| 1073 | #define EMU_HANA_IRQ_ADAT 0x02 | 1075 | /* Reading the register resets it. */ |
| 1074 | #define EMU_HANA_IRQ_DOCK 0x04 | ||
| 1075 | #define EMU_HANA_IRQ_DOCK_LOST 0x08 | ||
| 1076 | #endif | ||
| 1077 | 1076 | ||
| 1078 | #define EMU_HANA_OPTION_CARDS 0x21 /* 000xxxx 4 bits Presence of option cards */ | 1077 | #define EMU_HANA_OPTION_CARDS 0x21 /* 000xxxx 4 bits Presence of option cards */ |
| 1079 | #define EMU_HANA_OPTION_HAMOA 0x01 /* HAMOA card present */ | 1078 | #define EMU_HANA_OPTION_HAMOA 0x01 /* Hamoa (analog I/O) card present */ |
| 1080 | #define EMU_HANA_OPTION_SYNC 0x02 /* Sync card present */ | 1079 | #define EMU_HANA_OPTION_SYNC 0x02 /* Sync card present */ |
| 1081 | #define EMU_HANA_OPTION_DOCK_ONLINE 0x04 /* Audio Dock online and FPGA configured */ | 1080 | #define EMU_HANA_OPTION_DOCK_ONLINE 0x04 /* Audio/Micro dock present and FPGA configured */ |
| 1082 | #define EMU_HANA_OPTION_DOCK_OFFLINE 0x08 /* Audio Dock online and FPGA not configured */ | 1081 | #define EMU_HANA_OPTION_DOCK_OFFLINE 0x08 /* Audio/Micro dock present and FPGA not configured */ |
| 1083 | 1082 | ||
| 1084 | #define EMU_HANA_ID 0x22 /* 1010101 7 bits ID byte & 0x7f = 0x55 */ | 1083 | #define EMU_HANA_ID 0x22 /* 1010101 7 bits ID byte & 0x7f = 0x55 with Alice2 */ |
| 1084 | /* 0010101 5 bits ID byte & 0x1f = 0x15 with Tina/2 */ | ||
| 1085 | 1085 | ||
| 1086 | #define EMU_HANA_MAJOR_REV 0x23 /* 0000xxx 3 bit Hana FPGA Major rev */ | 1086 | #define EMU_HANA_MAJOR_REV 0x23 /* 0000xxx 3 bit Hana FPGA Major rev */ |
| 1087 | #define EMU_HANA_MINOR_REV 0x24 /* 0000xxx 3 bit Hana FPGA Minor rev */ | 1087 | #define EMU_HANA_MINOR_REV 0x24 /* 0000xxx 3 bit Hana FPGA Minor rev */ |
| @@ -1090,8 +1090,8 @@ · 2 unmodified lines | |||
| 1090 | #define EMU_DOCK_MINOR_REV 0x26 /* 0000xxx 3 bit Audio Dock FPGA Minor rev */ | 1090 | #define EMU_DOCK_MINOR_REV 0x26 /* 0000xxx 3 bit Audio Dock FPGA Minor rev */ |
| 1091 | 1091 | ||
| 1092 | #define EMU_DOCK_BOARD_ID 0x27 /* 00000xx 2 bits Audio Dock ID pins */ | 1092 | #define EMU_DOCK_BOARD_ID 0x27 /* 00000xx 2 bits Audio Dock ID pins */ |
| 1093 | #define EMU_DOCK_BOARD_ID0 0x00 /* ID bit 0 */ | 1093 | #define EMU_DOCK_BOARD_ID0 0x00 /* ID bit 0 */ |
| 1094 | #define EMU_DOCK_BOARD_ID1 0x03 /* ID bit 1 */ | 1094 | #define EMU_DOCK_BOARD_ID1 0x03 /* ID bit 1 */ |
| 1095 | 1095 | ||
| 1096 | #define EMU_HANA_WC_SPDIF_HI 0x28 /* 0xxxxxx 6 bit SPDIF IN Word clock, upper 6 bits */ | 1096 | #define EMU_HANA_WC_SPDIF_HI 0x28 /* 0xxxxxx 6 bit SPDIF IN Word clock, upper 6 bits */ |
| 1097 | #define EMU_HANA_WC_SPDIF_LO 0x29 /* 0xxxxxx 6 bit SPDIF IN Word clock, lower 6 bits */ | 1097 | #define EMU_HANA_WC_SPDIF_LO 0x29 /* 0xxxxxx 6 bit SPDIF IN Word clock, lower 6 bits */ |
| @@ -1104,31 +1104,35 @@ · 6 unmodified lines | |||
| 1104 | 1104 | ||
| 1105 | #define EMU_HANA2_WC_SPDIF_HI 0x2e /* 0xxxxxx 6 bit HANA2 SPDIF IN Word clock, upper 6 bits */ | 1105 | #define EMU_HANA2_WC_SPDIF_HI 0x2e /* 0xxxxxx 6 bit HANA2 SPDIF IN Word clock, upper 6 bits */ |
| 1106 | #define EMU_HANA2_WC_SPDIF_LO 0x2f /* 0xxxxxx 6 bit HANA2 SPDIF IN Word clock, lower 6 bits */ | 1106 | #define EMU_HANA2_WC_SPDIF_LO 0x2f /* 0xxxxxx 6 bit HANA2 SPDIF IN Word clock, lower 6 bits */ |
| 1107 | |||
| 1107 | /* 0x30 - 0x3f Unused Read only registers */ | 1108 | /* 0x30 - 0x3f Unused Read only registers */ |
| 1108 | 1109 | ||
| 1110 | // The meaning of this is not clear; kX-project just calls it "lock" in some info-only code. | ||
| 1111 | #define EMU_HANA_LOCK_STS_LO 0x38 /* 0xxxxxx lower 6 bits */ | ||
| 1112 | #define EMU_HANA_LOCK_STS_HI 0x39 /* 0xxxxxx upper 6 bits */ | ||
| 1113 | |||
| 1109 | /************************************************************************************************/ | 1114 | /************************************************************************************************/ |
| 1110 | /* EMU1010m HANA Destinations */ | 1115 | /* EMU1010 Audio Destinations */ |
| 1111 | /************************************************************************************************/ | 1116 | /************************************************************************************************/ |
| 1112 | /* Hana, original 1010,1212,1820 using Alice2 | 1117 | /* Hana, original 1010,1212m,1820[m] using Alice2 |
| 1113 | * Destiniations for SRATEX = 1X rates: 44.1 kHz or 48 kHz | ||
| 1114 | * 0x00, 0x00-0x0f: 16 EMU32 channels to Alice2 | 1118 | * 0x00, 0x00-0x0f: 16 EMU32 channels to Alice2 |
| 1115 | * 0x01, 0x10-0x1f: 32 Elink channels to Audio Dock | 1119 | * 0x01, 0x00-0x1f: 32 EDI channels to Audio Dock |
| 1116 | * 0x01, 0x00: Dock DAC 1 Left | 1120 | * 0x00: Dock DAC 1 Left |
| 1117 | * 0x01, 0x04: Dock DAC 1 Right | 1121 | * 0x04: Dock DAC 1 Right |
| 1118 | * 0x01, 0x08: Dock DAC 2 Left | 1122 | * 0x08: Dock DAC 2 Left |
| 1119 | * 0x01, 0x0c: Dock DAC 2 Right | 1123 | * 0x0c: Dock DAC 2 Right |
| 1120 | * 0x01, 0x10: Dock DAC 3 Left | 1124 | * 0x10: Dock DAC 3 Left |
| 1121 | * 0x01, 0x12: PHONES Left | 1125 | * 0x12: PHONES Left (n/a in 2x/4x mode; output mirrors DAC4 Left) |
| 1122 | * 0x01, 0x14: Dock DAC 3 Right | 1126 | * 0x14: Dock DAC 3 Right |
| 1123 | * 0x01, 0x16: PHONES Right | 1127 | * 0x16: PHONES Right (n/a in 2x/4x mode; output mirrors DAC4 Right) |
| 1124 | * 0x01, 0x18: Dock DAC 4 Left | 1128 | * 0x18: Dock DAC 4 Left |
| 1125 | * 0x01, 0x1a: S/PDIF Left | 1129 | * 0x1a: S/PDIF Left |
| 1126 | * 0x01, 0x1c: Dock DAC 4 Right | 1130 | * 0x1c: Dock DAC 4 Right |
| 1127 | * 0x01, 0x1e: S/PDIF Right | 1131 | * 0x1e: S/PDIF Right |
| 1128 | * 0x02, 0x00: Hana S/PDIF Left | 1132 | * 0x02, 0x00: Hana S/PDIF Left |
| 1129 | * 0x02, 0x01: Hana S/PDIF Right | 1133 | * 0x02, 0x01: Hana S/PDIF Right |
| 1130 | * 0x03, 0x00: Hanoa DAC Left | 1134 | * 0x03, 0x00: Hamoa DAC Left |
| 1131 | * 0x03, 0x01: Hanoa DAC Right | 1135 | * 0x03, 0x01: Hamoa DAC Right |
| 1132 | * 0x04, 0x00-0x07: Hana ADAT | 1136 | * 0x04, 0x00-0x07: Hana ADAT |
| 1133 | * 0x05, 0x00: I2S0 Left to Alice2 | 1137 | * 0x05, 0x00: I2S0 Left to Alice2 |
| 1134 | * 0x05, 0x01: I2S0 Right to Alice2 | 1138 | * 0x05, 0x01: I2S0 Right to Alice2 |
| @@ -1140,40 +1144,29 @@ · 5 unmodified lines | |||
| 1140 | * Hana2 never released, but used Tina | 1144 | * Hana2 never released, but used Tina |
| 1141 | * Not needed. | 1145 | * Not needed. |
| 1142 | * | 1146 | * |
| 1143 | * Hana3, rev2 1010,1212,1616 using Tina | 1147 | * Hana3, rev2 1010,1212m,1616[m] using Tina |
| 1144 | * Destinations for SRATEX = 1X rates: 44.1 kHz or 48 kHz | ||
| 1145 | * 0x00, 0x00-0x0f: 16 EMU32A channels to Tina | 1148 | * 0x00, 0x00-0x0f: 16 EMU32A channels to Tina |
| 1146 | * 0x01, 0x10-0x1f: 32 EDI channels to Micro Dock | 1149 | * 0x01, 0x00-0x1f: 32 EDI channels to Micro Dock |
| 1147 | * 0x01, 0x00: Dock DAC 1 Left | 1150 | * 0x00: Dock DAC 1 Left |
| 1148 | * 0x01, 0x04: Dock DAC 1 Right | 1151 | * 0x04: Dock DAC 1 Right |
| 1149 | * 0x01, 0x08: Dock DAC 2 Left | 1152 | * 0x08: Dock DAC 2 Left |
| 1150 | * 0x01, 0x0c: Dock DAC 2 Right | 1153 | * 0x0c: Dock DAC 2 Right |
| 1151 | * 0x01, 0x10: Dock DAC 3 Left | 1154 | * 0x10: Dock DAC 3 Left |
| 1152 | * 0x01, 0x12: Dock S/PDIF Left | 1155 | * 0x12: Dock S/PDIF Left |
| 1153 | * 0x01, 0x14: Dock DAC 3 Right | 1156 | * 0x14: Dock DAC 3 Right |
| 1154 | * 0x01, 0x16: Dock S/PDIF Right | 1157 | * 0x16: Dock S/PDIF Right |
| 1155 | * 0x01, 0x18-0x1f: Dock ADAT 0-7 | 1158 | * 0x18-0x1f: Dock ADAT 0-7 |
| 1156 | * 0x02, 0x00: Hana3 S/PDIF Left | 1159 | * 0x02, 0x00: Hana3 S/PDIF Left |
| 1157 | * 0x02, 0x01: Hana3 S/PDIF Right | 1160 | * 0x02, 0x01: Hana3 S/PDIF Right |
| 1158 | * 0x03, 0x00: Hanoa DAC Left | 1161 | * 0x03, 0x00: Hamoa DAC Left |
| 1159 | * 0x03, 0x01: Hanoa DAC Right | 1162 | * 0x03, 0x01: Hamoa DAC Right |
| 1160 | * 0x04, 0x00-0x07: Hana3 ADAT 0-7 | 1163 | * 0x04, 0x00-0x07: Hana3 ADAT 0-7 |
| 1161 | * 0x05, 0x00-0x0f: 16 EMU32B channels to Tina | 1164 | * 0x05, 0x00-0x0f: 16 EMU32B channels to Tina |
| 1162 | * 0x06-0x07: Not used | 1165 | * 0x06-0x07: Not used |
| 1163 | * | 1166 | * |
| 1164 | * HanaLite, rev1 0404 using Alice2 | 1167 | * HanaLite, rev1 0404 using Alice2 |
| 1165 | * Destiniations for SRATEX = 1X rates: 44.1 kHz or 48 kHz | 1168 | * HanaLiteLite, rev2 0404 using Tina |
| 1166 | * 0x00, 0x00-0x0f: 16 EMU32 channels to Alice2 | 1169 | * 0x00, 0x00-0x0f: 16 EMU32 channels to Alice2/Tina |
| 1167 | * 0x01: Not used | ||
| 1168 | * 0x02, 0x00: S/PDIF Left | ||
| 1169 | * 0x02, 0x01: S/PDIF Right | ||
| 1170 | * 0x03, 0x00: DAC Left | ||
| 1171 | * 0x03, 0x01: DAC Right | ||
| 1172 | * 0x04-0x07: Not used | ||
| 1173 | * | ||
| 1174 | * HanaLiteLite, rev2 0404 using Alice2 | ||
| 1175 | * Destiniations for SRATEX = 1X rates: 44.1 kHz or 48 kHz | ||
| 1176 | * 0x00, 0x00-0x0f: 16 EMU32 channels to Alice2 | ||
| 1177 | * 0x01: Not used | 1170 | * 0x01: Not used |
| 1178 | * 0x02, 0x00: S/PDIF Left | 1171 | * 0x02, 0x00: S/PDIF Left |
| 1179 | * 0x02, 0x01: S/PDIF Right | 1172 | * 0x02, 0x01: S/PDIF Right |
| @@ -1182,35 +1175,21 @@ · 2 unmodified lines | |||
| 1182 | * 0x04-0x07: Not used | 1175 | * 0x04-0x07: Not used |
| 1183 | * | 1176 | * |
| 1184 | * Mana, Cardbus 1616 using Tina2 | 1177 | * Mana, Cardbus 1616 using Tina2 |
| 1185 | * Destinations for SRATEX = 1X rates: 44.1 kHz or 48 kHz | ||
| 1186 | * 0x00, 0x00-0x0f: 16 EMU32A channels to Tina2 | 1178 | * 0x00, 0x00-0x0f: 16 EMU32A channels to Tina2 |
| 1187 | * 0x01, 0x10-0x1f: 32 EDI channels to Micro Dock | 1179 | * 0x01, 0x00-0x1f: 32 EDI channels to Micro Dock |
| 1188 | * 0x01, 0x00: Dock DAC 1 Left | 1180 | * (same as rev2 1010) |
| 1189 | * 0x01, 0x04: Dock DAC 1 Right | ||
| 1190 | * 0x01, 0x08: Dock DAC 2 Left | ||
| 1191 | * 0x01, 0x0c: Dock DAC 2 Right | ||
| 1192 | * 0x01, 0x10: Dock DAC 3 Left | ||
| 1193 | * 0x01, 0x12: Dock S/PDIF Left | ||
| 1194 | * 0x01, 0x14: Dock DAC 3 Right | ||
| 1195 | * 0x01, 0x16: Dock S/PDIF Right | ||
| 1196 | * 0x01, 0x18-0x1f: Dock ADAT 0-7 | ||
| 1197 | * 0x02: Not used | 1181 | * 0x02: Not used |
| 1198 | * 0x03, 0x00: Mana DAC Left | 1182 | * 0x03, 0x00: Mana DAC Left |
| 1199 | * 0x03, 0x01: Mana DAC Right | 1183 | * 0x03, 0x01: Mana DAC Right |
| 1200 | * 0x04, 0x00-0x0f: 16 EMU32B channels to Tina2 | 1184 | * 0x04, 0x00-0x0f: 16 EMU32B channels to Tina2 |
| 1201 | * 0x05-0x07: Not used | 1185 | * 0x05-0x07: Not used |
| 1202 | * | ||
| 1203 | * | ||
| 1204 | */ | 1186 | */ |
| 1187 | |||
| 1205 | /* 32-bit destinations of signal in the Hana FPGA. Destinations are either | 1188 | /* 32-bit destinations of signal in the Hana FPGA. Destinations are either |
| 1206 | * physical outputs of Hana, or outputs going to Alice2 (audigy) for capture | 1189 | * physical outputs of Hana, or outputs going to Alice2/Tina for capture - |
| 1207 | * - 16 x EMU_DST_ALICE2_EMU32_X. | 1190 | * 16 x EMU_DST_ALICE2_EMU32_X (2x on rev2 boards). Which data is fed into |
| 1208 | */ | 1191 | * a channel depends on the mixer control setting for each destination - see |
| 1209 | /* EMU32 = 32-bit serial channel between Alice2 (audigy) and Hana (FPGA) */ | 1192 | * emumixer.c - snd_emu1010_output_enum_ctls[], snd_emu1010_input_enum_ctls[] |
| 1210 | /* EMU_DST_ALICE2_EMU32_X - data channels from Hana to Alice2 used for capture. | ||
| 1211 | * Which data is fed into a EMU_DST_ALICE2_EMU32_X channel in Hana depends on | ||
| 1212 | * setup of mixer control for each destination - see emumixer.c - | ||
| 1213 | * snd_emu1010_output_enum_ctls[], snd_emu1010_input_enum_ctls[] | ||
| 1214 | */ | 1193 | */ |
| 1215 | #define EMU_DST_ALICE2_EMU32_0 0x000f /* 16 EMU32 channels to Alice2 +0 to +0xf */ | 1194 | #define EMU_DST_ALICE2_EMU32_0 0x000f /* 16 EMU32 channels to Alice2 +0 to +0xf */ |
| 1216 | #define EMU_DST_ALICE2_EMU32_1 0x0000 /* 16 EMU32 channels to Alice2 +0 to +0xf */ | 1195 | #define EMU_DST_ALICE2_EMU32_1 0x0000 /* 16 EMU32 channels to Alice2 +0 to +0xf */ |
| @@ -1270,8 +1249,12 @@ · 53 unmodified lines | |||
| 1270 | #define EMU_DST_DOCK_SPDIF_RIGHT2 0x011f /* Audio Dock SPDIF Right, 2nd or 96kHz */ | 1249 | #define EMU_DST_DOCK_SPDIF_RIGHT2 0x011f /* Audio Dock SPDIF Right, 2nd or 96kHz */ |
| 1271 | #define EMU_DST_HANA_SPDIF_LEFT1 0x0200 /* Hana SPDIF Left, 1st or 48kHz only */ | 1250 | #define EMU_DST_HANA_SPDIF_LEFT1 0x0200 /* Hana SPDIF Left, 1st or 48kHz only */ |
| 1272 | #define EMU_DST_HANA_SPDIF_LEFT2 0x0202 /* Hana SPDIF Left, 2nd or 96kHz */ | 1251 | #define EMU_DST_HANA_SPDIF_LEFT2 0x0202 /* Hana SPDIF Left, 2nd or 96kHz */ |
| 1252 | #define EMU_DST_HANA_SPDIF_LEFT3 0x0204 /* Hana SPDIF Left, 3rd or 192kHz */ | ||
| 1253 | #define EMU_DST_HANA_SPDIF_LEFT4 0x0206 /* Hana SPDIF Left, 4th or 192kHz */ | ||
| 1273 | #define EMU_DST_HANA_SPDIF_RIGHT1 0x0201 /* Hana SPDIF Right, 1st or 48kHz only */ | 1254 | #define EMU_DST_HANA_SPDIF_RIGHT1 0x0201 /* Hana SPDIF Right, 1st or 48kHz only */ |
| 1274 | #define EMU_DST_HANA_SPDIF_RIGHT2 0x0203 /* Hana SPDIF Right, 2nd or 96kHz */ | 1255 | #define EMU_DST_HANA_SPDIF_RIGHT2 0x0203 /* Hana SPDIF Right, 2nd or 96kHz */ |
| 1256 | #define EMU_DST_HANA_SPDIF_RIGHT3 0x0205 /* Hana SPDIF Right, 3rd or 192kHz */ | ||
| 1257 | #define EMU_DST_HANA_SPDIF_RIGHT4 0x0207 /* Hana SPDIF Right, 4th or 192kHz */ | ||
| 1275 | #define EMU_DST_HAMOA_DAC_LEFT1 0x0300 /* Hamoa DAC Left, 1st or 48kHz only */ | 1258 | #define EMU_DST_HAMOA_DAC_LEFT1 0x0300 /* Hamoa DAC Left, 1st or 48kHz only */ |
| 1276 | #define EMU_DST_HAMOA_DAC_LEFT2 0x0302 /* Hamoa DAC Left, 2nd or 96kHz */ | 1259 | #define EMU_DST_HAMOA_DAC_LEFT2 0x0302 /* Hamoa DAC Left, 2nd or 96kHz */ |
| 1277 | #define EMU_DST_HAMOA_DAC_LEFT3 0x0304 /* Hamoa DAC Left, 3rd or 192kHz */ | 1260 | #define EMU_DST_HAMOA_DAC_LEFT3 0x0304 /* Hamoa DAC Left, 3rd or 192kHz */ |
| @@ -1280,6 +1263,7 @@ · 2 unmodified lines | |||
| 1280 | #define EMU_DST_HAMOA_DAC_RIGHT2 0x0303 /* Hamoa DAC Right, 2nd or 96kHz */ | 1263 | #define EMU_DST_HAMOA_DAC_RIGHT2 0x0303 /* Hamoa DAC Right, 2nd or 96kHz */ |
| 1281 | #define EMU_DST_HAMOA_DAC_RIGHT3 0x0305 /* Hamoa DAC Right, 3rd or 192kHz */ | 1264 | #define EMU_DST_HAMOA_DAC_RIGHT3 0x0305 /* Hamoa DAC Right, 3rd or 192kHz */ |
| 1282 | #define EMU_DST_HAMOA_DAC_RIGHT4 0x0307 /* Hamoa DAC Right, 4th or 192kHz */ | 1265 | #define EMU_DST_HAMOA_DAC_RIGHT4 0x0307 /* Hamoa DAC Right, 4th or 192kHz */ |
| 1266 | // In S/MUX mode, the samples of one channel are adjacent. | ||
| 1283 | #define EMU_DST_HANA_ADAT 0x0400 /* Hana ADAT 8 channel out +0 to +7 */ | 1267 | #define EMU_DST_HANA_ADAT 0x0400 /* Hana ADAT 8 channel out +0 to +7 */ |
| 1284 | #define EMU_DST_ALICE_I2S0_LEFT 0x0500 /* Alice2 I2S0 Left */ | 1268 | #define EMU_DST_ALICE_I2S0_LEFT 0x0500 /* Alice2 I2S0 Left */ |
| 1285 | #define EMU_DST_ALICE_I2S0_RIGHT 0x0501 /* Alice2 I2S0 Right */ | 1269 | #define EMU_DST_ALICE_I2S0_RIGHT 0x0501 /* Alice2 I2S0 Right */ |
| @@ -1289,39 +1273,32 @@ · 3 unmodified lines | |||
| 1289 | #define EMU_DST_ALICE_I2S2_RIGHT 0x0701 /* Alice2 I2S2 Right */ | 1273 | #define EMU_DST_ALICE_I2S2_RIGHT 0x0701 /* Alice2 I2S2 Right */ |
| 1290 | 1274 | ||
| 1291 | /* Additional destinations for 1616(M)/Microdock */ | 1275 | /* Additional destinations for 1616(M)/Microdock */ |
| 1292 | /* Microdock S/PDIF OUT Left, 1st or 48kHz only */ | 1276 | |
| 1293 | #define EMU_DST_MDOCK_SPDIF_LEFT1 0x0112 | 1277 | #define EMU_DST_MDOCK_SPDIF_LEFT1 0x0112 /* Microdock S/PDIF OUT Left, 1st or 48kHz only */ |
| 1294 | /* Microdock S/PDIF OUT Left, 2nd or 96kHz */ | 1278 | #define EMU_DST_MDOCK_SPDIF_LEFT2 0x0113 /* Microdock S/PDIF OUT Left, 2nd or 96kHz */ |
| 1295 | #define EMU_DST_MDOCK_SPDIF_LEFT2 0x0113 | 1279 | #define EMU_DST_MDOCK_SPDIF_RIGHT1 0x0116 /* Microdock S/PDIF OUT Right, 1st or 48kHz only */ |
| 1296 | /* Microdock S/PDIF OUT Right, 1st or 48kHz only */ | 1280 | #define EMU_DST_MDOCK_SPDIF_RIGHT2 0x0117 /* Microdock S/PDIF OUT Right, 2nd or 96kHz */ |
| 1297 | #define EMU_DST_MDOCK_SPDIF_RIGHT1 0x0116 | 1281 | #define EMU_DST_MDOCK_ADAT 0x0118 /* Microdock S/PDIF ADAT 8 channel out +8 to +f */ |
| 1298 | /* Microdock S/PDIF OUT Right, 2nd or 96kHz */ | 1282 | |
| 1299 | #define EMU_DST_MDOCK_SPDIF_RIGHT2 0x0117 | 1283 | #define EMU_DST_MANA_DAC_LEFT 0x0300 /* Headphone jack on 1010 cardbus? 44.1/48kHz only? */ |
| 1300 | /* Microdock S/PDIF ADAT 8 channel out +8 to +f */ | 1284 | #define EMU_DST_MANA_DAC_RIGHT 0x0301 /* Headphone jack on 1010 cardbus? 44.1/48kHz only? */ |
| 1301 | #define EMU_DST_MDOCK_ADAT 0x0118 | ||
| 1302 | |||
| 1303 | /* Headphone jack on 1010 cardbus? 44.1/48kHz only? */ | ||
| 1304 | #define EMU_DST_MANA_DAC_LEFT 0x0300 | ||
| 1305 | /* Headphone jack on 1010 cardbus? 44.1/48kHz only? */ | ||
| 1306 | #define EMU_DST_MANA_DAC_RIGHT 0x0301 | ||
| 1307 | 1285 | ||
| 1308 | /************************************************************************************************/ | 1286 | /************************************************************************************************/ |
| 1309 | /* EMU1010m HANA Sources */ | 1287 | /* EMU1010 Audio Sources */ |
| 1310 | /************************************************************************************************/ | 1288 | /************************************************************************************************/ |
| 1311 | /* Hana, original 1010,1212,1820 using Alice2 | 1289 | /* Hana, original 1010,1212m,1820[m] using Alice2 |
| 1312 | * Sources SRATEX = 1X rates: 44.1 kHz or 48 kHz | 1290 | * 0x00, 0x00-0x1f: Silence |
| 1313 | * 0x00,0x00-0x1f: Silence | 1291 | * 0x01, 0x00-0x1f: 32 EDI channels from Audio Dock |
| 1314 | * 0x01, 0x10-0x1f: 32 Elink channels from Audio Dock | 1292 | * 0x00: Dock Mic A |
| 1315 | * 0x01, 0x00: Dock Mic A | 1293 | * 0x04: Dock Mic B |
| 1316 | * 0x01, 0x04: Dock Mic B | 1294 | * 0x08: Dock ADC 1 Left |
| 1317 | * 0x01, 0x08: Dock ADC 1 Left | 1295 | * 0x0c: Dock ADC 1 Right |
| 1318 | * 0x01, 0x0c: Dock ADC 1 Right | 1296 | * 0x10: Dock ADC 2 Left |
| 1319 | * 0x01, 0x10: Dock ADC 2 Left | 1297 | * 0x14: Dock ADC 2 Right |
| 1320 | * 0x01, 0x14: Dock ADC 2 Right | 1298 | * 0x18: Dock ADC 3 Left |
| 1321 | * 0x01, 0x18: Dock ADC 3 Left | 1299 | * 0x1c: Dock ADC 3 Right |
| 1322 | * 0x01, 0x1c: Dock ADC 3 Right | 1300 | * 0x02, 0x00: Hamoa ADC Left |
| 1323 | * 0x02, 0x00: Hana ADC Left | 1301 | * 0x02, 0x01: Hamoa ADC Right |
| 1324 | * 0x02, 0x01: Hana ADC Right | ||
| 1325 | * 0x03, 0x00-0x0f: 16 inputs from Alice2 Emu32A output | 1302 | * 0x03, 0x00-0x0f: 16 inputs from Alice2 Emu32A output |
| 1326 | * 0x03, 0x10-0x1f: 16 inputs from Alice2 Emu32B output | 1303 | * 0x03, 0x10-0x1f: 16 inputs from Alice2 Emu32B output |
| 1327 | * 0x04, 0x00-0x07: Hana ADAT | 1304 | * 0x04, 0x00-0x07: Hana ADAT |
| @@ -1332,23 +1309,20 @@ · 4 unmodified lines | |||
| 1332 | * Hana2 never released, but used Tina | 1309 | * Hana2 never released, but used Tina |
| 1333 | * Not needed. | 1310 | * Not needed. |
| 1334 | * | 1311 | * |
| 1335 | * Hana3, rev2 1010,1212,1616 using Tina | 1312 | * Hana3, rev2 1010,1212m,1616[m] using Tina |
| 1336 | * Sources SRATEX = 1X rates: 44.1 kHz or 48 kHz | 1313 | * 0x00, 0x00-0x1f: Silence |
| 1337 | * 0x00,0x00-0x1f: Silence | 1314 | * 0x01, 0x00-0x1f: 32 EDI channels from Micro Dock |
| 1338 | * 0x01, 0x10-0x1f: 32 Elink channels from Audio Dock | 1315 | * 0x00: Dock Mic A |
| 1339 | * 0x01, 0x00: Dock Mic A | 1316 | * 0x04: Dock Mic B |
| 1340 | * 0x01, 0x04: Dock Mic B | 1317 | * 0x08: Dock ADC 1 Left |
| 1341 | * 0x01, 0x08: Dock ADC 1 Left | 1318 | * 0x0c: Dock ADC 1 Right |
| 1342 | * 0x01, 0x0c: Dock ADC 1 Right | 1319 | * 0x10: Dock ADC 2 Left |
| 1343 | * 0x01, 0x10: Dock ADC 2 Left | 1320 | * 0x12: Dock S/PDIF Left |
| 1344 | * 0x01, 0x12: Dock S/PDIF Left | 1321 | * 0x14: Dock ADC 2 Right |
| 1345 | * 0x01, 0x14: Dock ADC 2 Right | 1322 | * 0x16: Dock S/PDIF Right |
| 1346 | * 0x01, 0x16: Dock S/PDIF Right | 1323 | * 0x18-0x1f: Dock ADAT 0-7 |
| 1347 | * 0x01, 0x18-0x1f: Dock ADAT 0-7 | 1324 | * 0x02, 0x00: Hamoa ADC Left |
| 1348 | * 0x01, 0x18: Dock ADC 3 Left | 1325 | * 0x02, 0x01: Hamoa ADC Right |
| 1349 | * 0x01, 0x1c: Dock ADC 3 Right | ||
| 1350 | * 0x02, 0x00: Hanoa ADC Left | ||
| 1351 | * 0x02, 0x01: Hanoa ADC Right | ||
| 1352 | * 0x03, 0x00-0x0f: 16 inputs from Tina Emu32A output | 1326 | * 0x03, 0x00-0x0f: 16 inputs from Tina Emu32A output |
| 1353 | * 0x03, 0x10-0x1f: 16 inputs from Tina Emu32B output | 1327 | * 0x03, 0x10-0x1f: 16 inputs from Tina Emu32B output |
| 1354 | * 0x04, 0x00-0x07: Hana3 ADAT | 1328 | * 0x04, 0x00-0x07: Hana3 ADAT |
| @@ -1357,58 +1331,32 @@ · 2 unmodified lines | |||
| 1357 | * 0x06-0x07: Not used | 1331 | * 0x06-0x07: Not used |
| 1358 | * | 1332 | * |
| 1359 | * HanaLite, rev1 0404 using Alice2 | 1333 | * HanaLite, rev1 0404 using Alice2 |
| 1360 | * Sources SRATEX = 1X rates: 44.1 kHz or 48 kHz | 1334 | * HanaLiteLite, rev2 0404 using Tina |
| 1361 | * 0x00,0x00-0x1f: Silence | 1335 | * 0x00, 0x00-0x1f: Silence |
| 1362 | * 0x01: Not used | ||
| 1363 | * 0x02, 0x00: ADC Left | ||
| 1364 | * 0x02, 0x01: ADC Right | ||
| 1365 | * 0x03, 0x00-0x0f: 16 inputs from Alice2 Emu32A output | ||
| 1366 | * 0x03, 0x10-0x1f: 16 inputs from Alice2 Emu32B output | ||
| 1367 | * 0x04: Not used | ||
| 1368 | * 0x05, 0x00: S/PDIF Left | ||
| 1369 | * 0x05, 0x01: S/PDIF Right | ||
| 1370 | * 0x06-0x07: Not used | ||
| 1371 | * | ||
| 1372 | * HanaLiteLite, rev2 0404 using Alice2 | ||
| 1373 | * Sources SRATEX = 1X rates: 44.1 kHz or 48 kHz | ||
| 1374 | * 0x00,0x00-0x1f: Silence | ||
| 1375 | * 0x01: Not used | 1336 | * 0x01: Not used |
| 1376 | * 0x02, 0x00: ADC Left | 1337 | * 0x02, 0x00: ADC Left |
| 1377 | * 0x02, 0x01: ADC Right | 1338 | * 0x02, 0x01: ADC Right |
| 1378 | * 0x03, 0x00-0x0f: 16 inputs from Alice2 Emu32A output | 1339 | * 0x03, 0x00-0x0f: 16 inputs from Alice2/Tina Emu32A output |
| 1379 | * 0x03, 0x10-0x1f: 16 inputs from Alice2 Emu32B output | 1340 | * 0x03, 0x10-0x1f: 16 inputs from Alice2/Tina Emu32B output |
| 1380 | * 0x04: Not used | 1341 | * 0x04: Not used |
| 1381 | * 0x05, 0x00: S/PDIF Left | 1342 | * 0x05, 0x00: S/PDIF Left |
| 1382 | * 0x05, 0x01: S/PDIF Right | 1343 | * 0x05, 0x01: S/PDIF Right |
| 1383 | * 0x06-0x07: Not used | 1344 | * 0x06-0x07: Not used |
| 1384 | * | 1345 | * |
| 1385 | * Mana, Cardbus 1616 using Tina2 | 1346 | * Mana, Cardbus 1616 using Tina2 |
| 1386 | * Sources SRATEX = 1X rates: 44.1 kHz or 48 kHz | 1347 | * 0x00, 0x00-0x1f: Silence |
| 1387 | * 0x00,0x00-0x1f: Silence | 1348 | * 0x01, 0x00-0x1f: 32 EDI channels from Micro Dock |
| 1388 | * 0x01, 0x10-0x1f: 32 Elink channels from Audio Dock | 1349 | * (same as rev2 1010) |
| 1389 | * 0x01, 0x00: Dock Mic A | ||
| 1390 | * 0x01, 0x04: Dock Mic B | ||
| 1391 | * 0x01, 0x08: Dock ADC 1 Left | ||
| 1392 | * 0x01, 0x0c: Dock ADC 1 Right | ||
| 1393 | * 0x01, 0x10: Dock ADC 2 Left | ||
| 1394 | * 0x01, 0x12: Dock S/PDIF Left | ||
| 1395 | * 0x01, 0x14: Dock ADC 2 Right | ||
| 1396 | * 0x01, 0x16: Dock S/PDIF Right | ||
| 1397 | * 0x01, 0x18-0x1f: Dock ADAT 0-7 | ||
| 1398 | * 0x01, 0x18: Dock ADC 3 Left | ||
| 1399 | * 0x01, 0x1c: Dock ADC 3 Right | ||
| 1400 | * 0x02: Not used | 1350 | * 0x02: Not used |
| 1401 | * 0x03, 0x00-0x0f: 16 inputs from Tina Emu32A output | 1351 | * 0x03, 0x00-0x0f: 16 inputs from Tina2 Emu32A output |
| 1402 | * 0x03, 0x10-0x1f: 16 inputs from Tina Emu32B output | 1352 | * 0x03, 0x10-0x1f: 16 inputs from Tina2 Emu32B output |
| 1403 | * 0x04-0x07: Not used | 1353 | * 0x04-0x07: Not used |
| 1404 | * | ||
| 1405 | */ | 1354 | */ |
| 1406 | 1355 | ||
| 1407 | /* 32-bit sources of signal in the Hana FPGA. The sources are routed to | 1356 | /* 32-bit sources of signal in the Hana FPGA. The sources are routed to |
| 1408 | * destinations using mixer control for each destination - see emumixer.c | 1357 | * destinations using a mixer control for each destination - see emumixer.c. |
| 1409 | * Sources are either physical inputs of FPGA, | 1358 | * Sources are either physical inputs of Hana, or inputs from Alice2/Tina - |
| 1410 | * or outputs from Alice (audigy) - 16 x EMU_SRC_ALICE_EMU32A + | 1359 | * 16 x EMU_SRC_ALICE_EMU32A + 16 x EMU_SRC_ALICE_EMU32B. |
| 1411 | * 16 x EMU_SRC_ALICE_EMU32B | ||
| 1412 | */ | 1360 | */ |
| 1413 | #define EMU_SRC_SILENCE 0x0000 /* Silence */ | 1361 | #define EMU_SRC_SILENCE 0x0000 /* Silence */ |
| 1414 | #define EMU_SRC_DOCK_MIC_A1 0x0100 /* Audio Dock Mic A, 1st or 48kHz only */ | 1362 | #define EMU_SRC_DOCK_MIC_A1 0x0100 /* Audio Dock Mic A, 1st or 48kHz only */ |
| @@ -1453,23 +1401,24 @@ · 38 unmodified lines | |||
| 1453 | #define EMU_SRC_HAMOA_ADC_RIGHT4 0x0207 /* Hamoa ADC Right, 4th or 192kHz */ | 1401 | #define EMU_SRC_HAMOA_ADC_RIGHT4 0x0207 /* Hamoa ADC Right, 4th or 192kHz */ |
| 1454 | #define EMU_SRC_ALICE_EMU32A 0x0300 /* Alice2 EMU32a 16 outputs. +0 to +0xf */ | 1402 | #define EMU_SRC_ALICE_EMU32A 0x0300 /* Alice2 EMU32a 16 outputs. +0 to +0xf */ |
| 1455 | #define EMU_SRC_ALICE_EMU32B 0x0310 /* Alice2 EMU32b 16 outputs. +0 to +0xf */ | 1403 | #define EMU_SRC_ALICE_EMU32B 0x0310 /* Alice2 EMU32b 16 outputs. +0 to +0xf */ |
| 1404 | // In S/MUX mode, the samples of one channel are adjacent. | ||
| 1456 | #define EMU_SRC_HANA_ADAT 0x0400 /* Hana ADAT 8 channel in +0 to +7 */ | 1405 | #define EMU_SRC_HANA_ADAT 0x0400 /* Hana ADAT 8 channel in +0 to +7 */ |
| 1457 | #define EMU_SRC_HANA_SPDIF_LEFT1 0x0500 /* Hana SPDIF Left, 1st or 48kHz only */ | 1406 | #define EMU_SRC_HANA_SPDIF_LEFT1 0x0500 /* Hana SPDIF Left, 1st or 48kHz only */ |
| 1458 | #define EMU_SRC_HANA_SPDIF_LEFT2 0x0502 /* Hana SPDIF Left, 2nd or 96kHz */ | 1407 | #define EMU_SRC_HANA_SPDIF_LEFT2 0x0502 /* Hana SPDIF Left, 2nd or 96kHz */ |
| 1408 | #define EMU_SRC_HANA_SPDIF_LEFT3 0x0504 /* Hana SPDIF Left, 3rd or 192kHz */ | ||
| 1409 | #define EMU_SRC_HANA_SPDIF_LEFT4 0x0506 /* Hana SPDIF Left, 4th or 192kHz */ | ||
| 1459 | #define EMU_SRC_HANA_SPDIF_RIGHT1 0x0501 /* Hana SPDIF Right, 1st or 48kHz only */ | 1410 | #define EMU_SRC_HANA_SPDIF_RIGHT1 0x0501 /* Hana SPDIF Right, 1st or 48kHz only */ |
| 1460 | #define EMU_SRC_HANA_SPDIF_RIGHT2 0x0503 /* Hana SPDIF Right, 2nd or 96kHz */ | 1411 | #define EMU_SRC_HANA_SPDIF_RIGHT2 0x0503 /* Hana SPDIF Right, 2nd or 96kHz */ |
| 1412 | #define EMU_SRC_HANA_SPDIF_RIGHT3 0x0505 /* Hana SPDIF Right, 3rd or 192kHz */ | ||
| 1413 | #define EMU_SRC_HANA_SPDIF_RIGHT4 0x0507 /* Hana SPDIF Right, 4th or 192kHz */ | ||
| 1461 | 1414 | ||
| 1462 | /* Additional inputs for 1616(M)/Microdock */ | 1415 | /* Additional inputs for 1616(M)/Microdock */ |
| 1463 | /* Microdock S/PDIF Left, 1st or 48kHz only */ | 1416 | |
| 1464 | #define EMU_SRC_MDOCK_SPDIF_LEFT1 0x0112 | 1417 | #define EMU_SRC_MDOCK_SPDIF_LEFT1 0x0112 /* Microdock S/PDIF Left, 1st or 48kHz only */ |
| 1465 | /* Microdock S/PDIF Left, 2nd or 96kHz */ | 1418 | #define EMU_SRC_MDOCK_SPDIF_LEFT2 0x0113 /* Microdock S/PDIF Left, 2nd or 96kHz */ |
| 1466 | #define EMU_SRC_MDOCK_SPDIF_LEFT2 0x0113 | 1419 | #define EMU_SRC_MDOCK_SPDIF_RIGHT1 0x0116 /* Microdock S/PDIF Right, 1st or 48kHz only */ |
| 1467 | /* Microdock S/PDIF Right, 1st or 48kHz only */ | 1420 | #define EMU_SRC_MDOCK_SPDIF_RIGHT2 0x0117 /* Microdock S/PDIF Right, 2nd or 96kHz */ |
| 1468 | #define EMU_SRC_MDOCK_SPDIF_RIGHT1 0x0116 | 1421 | #define EMU_SRC_MDOCK_ADAT 0x0118 /* Microdock ADAT 8 channel in +8 to +f */ |
| 1469 | /* Microdock S/PDIF Right, 2nd or 96kHz */ | ||
| 1470 | #define EMU_SRC_MDOCK_SPDIF_RIGHT2 0x0117 | ||
| 1471 | /* Microdock ADAT 8 channel in +8 to +f */ | ||
| 1472 | #define EMU_SRC_MDOCK_ADAT 0x0118 | ||
| 1473 | 1422 | ||
| 1474 | /* 0x600 and 0x700 no used */ | 1423 | /* 0x600 and 0x700 no used */ |
| 1475 | 1424 | ||
| @@ -1485,7 +1434,6 @@ enum { · 9 unmodified lines | |||
| 1485 | struct snd_emu10k1; | 1434 | struct snd_emu10k1; |
| 1486 | 1435 | ||
| 1487 | struct snd_emu10k1_voice { | 1436 | struct snd_emu10k1_voice { |
| 1488 | struct snd_emu10k1 *emu; | ||
| 1489 | int number; | 1437 | int number; |
| 1490 | unsigned int use: 1, | 1438 | unsigned int use: 1, |
| 1491 | pcm: 1, | 1439 | pcm: 1, |
| @@ -1599,10 +1547,8 @@ struct snd_emu10k1_fx8010_pcm { · 107 unmodified lines | |||
| 1599 | }; | 1547 | }; |
| 1600 | 1548 | ||
| 1601 | struct snd_emu10k1_fx8010 { | 1549 | struct snd_emu10k1_fx8010 { |
| 1602 | unsigned short fxbus_mask; /* used FX buses (bitmask) */ | 1550 | unsigned short extin_mask; /* used external inputs (bitmask); not used for Audigy */ |
| 1603 | unsigned short extin_mask; /* used external inputs (bitmask) */ | 1551 | unsigned short extout_mask; /* used external outputs (bitmask); not used for Audigy */ |
| 1604 | unsigned short extout_mask; /* used external outputs (bitmask) */ | ||
| 1605 | unsigned short pad1; | ||
| 1606 | unsigned int itram_size; /* internal TRAM size in samples */ | 1552 | unsigned int itram_size; /* internal TRAM size in samples */ |
| 1607 | struct snd_dma_buffer etram_pages; /* external TRAM pages and size */ | 1553 | struct snd_dma_buffer etram_pages; /* external TRAM pages and size */ |
| 1608 | unsigned int dbg; /* FX debugger register */ | 1554 | unsigned int dbg; /* FX debugger register */ |
| @@ -1639,14 +1585,26 @@ enum { · 30 unmodified lines | |||
| 1639 | EMU_MODEL_EMU0404, | 1585 | EMU_MODEL_EMU0404, |
| 1640 | }; | 1586 | }; |
| 1641 | 1587 | ||
| 1588 | // Chip-o-logy: | ||
| 1589 | // - All SB Live! cards use EMU10K1 chips | ||
| 1590 | // - All SB Audigy cards use CA* chips, termed "emu10k2" by the driver | ||
| 1591 | // - Original Audigy uses CA0100 "Alice" | ||
| 1592 | // - Audigy 2 uses CA0102/CA10200 "Alice2" | ||
| 1593 | // - Has an interface for CA0151 (P16V) "Alice3" | ||
| 1594 | // - Audigy 2 Value uses CA0108/CA10300 "Tina" | ||
| 1595 | // - Approximately a CA0102 with an on-chip CA0151 (P17V) | ||
| 1596 | // - Audigy 2 ZS NB uses CA0109 "Tina2" | ||
| 1597 | // - Cardbus version of CA0108 | ||
| 1642 | struct snd_emu_chip_details { | 1598 | struct snd_emu_chip_details { |
| 1643 | u32 vendor; | 1599 | u32 vendor; |
| 1644 | u32 device; | 1600 | u32 device; |
| 1645 | u32 subsystem; | 1601 | u32 subsystem; |
| 1646 | unsigned char revision; | 1602 | unsigned char revision; |
| 1647 | unsigned char emu10k1_chip; /* Original SB Live. Not SB Live 24bit. */ | 1603 | unsigned char emu10k1_chip; /* Original SB Live. Not SB Live 24bit. */ |
| 1604 | /* Redundant with emu10k2_chip being unset. */ | ||
| 1648 | unsigned char emu10k2_chip; /* Audigy 1 or Audigy 2. */ | 1605 | unsigned char emu10k2_chip; /* Audigy 1 or Audigy 2. */ |
| 1649 | unsigned char ca0102_chip; /* Audigy 1 or Audigy 2. Not SB Audigy 2 Value. */ | 1606 | unsigned char ca0102_chip; /* Audigy 1 or Audigy 2. Not SB Audigy 2 Value. */ |
| 1607 | /* Redundant with ca0108_chip being unset. */ | ||
| 1650 | unsigned char ca0108_chip; /* Audigy 2 Value */ | 1608 | unsigned char ca0108_chip; /* Audigy 2 Value */ |
| 1651 | unsigned char ca_cardbus_chip; /* Audigy 2 ZS Notebook */ | 1609 | unsigned char ca_cardbus_chip; /* Audigy 2 ZS Notebook */ |
| 1652 | unsigned char ca0151_chip; /* P16V */ | 1610 | unsigned char ca0151_chip; /* P16V */ |
| @@ -1656,8 +1614,8 @@ struct snd_emu_chip_details { · 3 unmodified lines | |||
| 1656 | unsigned char ac97_chip; /* Has an AC97 chip: 1 = mandatory, 2 = optional */ | 1614 | unsigned char ac97_chip; /* Has an AC97 chip: 1 = mandatory, 2 = optional */ |
| 1657 | unsigned char ecard; /* APS EEPROM */ | 1615 | unsigned char ecard; /* APS EEPROM */ |
| 1658 | unsigned char emu_model; /* EMU model type */ | 1616 | unsigned char emu_model; /* EMU model type */ |
| 1659 | unsigned char spi_dac; /* SPI interface for DAC */ | 1617 | unsigned char spi_dac; /* SPI interface for DAC; requires ca0108_chip */ |
| 1660 | unsigned char i2c_adc; /* I2C interface for ADC */ | 1618 | unsigned char i2c_adc; /* I2C interface for ADC; requires ca0108_chip */ |
| 1661 | unsigned char adc_1361t; /* Use Philips 1361T ADC */ | 1619 | unsigned char adc_1361t; /* Use Philips 1361T ADC */ |
| 1662 | unsigned char invert_shared_spdif; /* analog/digital switch inverted */ | 1620 | unsigned char invert_shared_spdif; /* analog/digital switch inverted */ |
| 1663 | const char *driver; | 1621 | const char *driver; |
| @@ -1691,7 +1649,6 @@ struct snd_emu10k1 { · 27 unmodified lines | |||
| 1691 | unsigned int revision; /* chip revision */ | 1649 | unsigned int revision; /* chip revision */ |
| 1692 | unsigned int serial; /* serial number */ | 1650 | unsigned int serial; /* serial number */ |
| 1693 | unsigned short model; /* subsystem id */ | 1651 | unsigned short model; /* subsystem id */ |
| 1694 | unsigned int card_type; /* EMU10K1_CARD_* */ | ||
| 1695 | unsigned int ecard_ctrl; /* ecard control bits */ | 1652 | unsigned int ecard_ctrl; /* ecard control bits */ |
| 1696 | unsigned int address_mode; /* address mode */ | 1653 | unsigned int address_mode; /* address mode */ |
| 1697 | unsigned long dma_mask; /* PCI DMA mask */ | 1654 | unsigned long dma_mask; /* PCI DMA mask */ |
| @@ -1732,15 +1689,13 @@ struct snd_emu10k1 { · 34 unmodified lines | |||
| 1732 | void *synth; | 1689 | void *synth; |
| 1733 | int (*get_synth_voice)(struct snd_emu10k1 *emu); | 1690 | int (*get_synth_voice)(struct snd_emu10k1 *emu); |
| 1734 | 1691 | ||
| 1735 | spinlock_t reg_lock; | 1692 | spinlock_t reg_lock; // high-level driver lock |
| 1736 | spinlock_t emu_lock; | 1693 | spinlock_t emu_lock; // low-level i/o lock |
| 1737 | spinlock_t voice_lock; | 1694 | spinlock_t voice_lock; // voice allocator lock |
| 1738 | spinlock_t spi_lock; /* serialises access to spi port */ | 1695 | spinlock_t spi_lock; /* serialises access to spi port */ |
| 1739 | spinlock_t i2c_lock; /* serialises access to i2c port */ | 1696 | spinlock_t i2c_lock; /* serialises access to i2c port */ |
| 1740 | 1697 | ||
| 1741 | struct snd_emu10k1_voice voices[NUM_G]; | 1698 | struct snd_emu10k1_voice voices[NUM_G]; |
| 1742 | struct snd_emu10k1_voice p16v_voices[4]; | ||
| 1743 | struct snd_emu10k1_voice p16v_capture_voice; | ||
| 1744 | int p16v_device_offset; | 1699 | int p16v_device_offset; |
| 1745 | u32 p16v_capture_source; | 1700 | u32 p16v_capture_source; |
| 1746 | u32 p16v_capture_channel; | 1701 | u32 p16v_capture_channel; |
| @@ -1760,11 +1715,11 @@ struct snd_emu10k1 { · 13 unmodified lines | |||
| 1760 | void (*capture_efx_interrupt)(struct snd_emu10k1 *emu, unsigned int status); | 1715 | void (*capture_efx_interrupt)(struct snd_emu10k1 *emu, unsigned int status); |
| 1761 | void (*spdif_interrupt)(struct snd_emu10k1 *emu, unsigned int status); | 1716 | void (*spdif_interrupt)(struct snd_emu10k1 *emu, unsigned int status); |
| 1762 | void (*dsp_interrupt)(struct snd_emu10k1 *emu); | 1717 | void (*dsp_interrupt)(struct snd_emu10k1 *emu); |
| 1718 | void (*p16v_interrupt)(struct snd_emu10k1 *emu); | ||
| 1763 | 1719 | ||
| 1764 | struct snd_pcm_substream *pcm_capture_substream; | 1720 | struct snd_pcm_substream *pcm_capture_substream; |
| 1765 | struct snd_pcm_substream *pcm_capture_mic_substream; | 1721 | struct snd_pcm_substream *pcm_capture_mic_substream; |
| 1766 | struct snd_pcm_substream *pcm_capture_efx_substream; | 1722 | struct snd_pcm_substream *pcm_capture_efx_substream; |
| 1767 | struct snd_pcm_substream *pcm_playback_efx_substream; | ||
| 1768 | 1723 | ||
| 1769 | struct snd_timer *timer; | 1724 | struct snd_timer *timer; |
| 1770 | 1725 | ||
| @@ -1824,9 +1779,9 @@ unsigned int snd_emu10k1_ptr20_read(struct snd_emu10k1 * emu, unsigned int reg, · 53 unmodified lines | |||
| 1824 | void snd_emu10k1_ptr20_write(struct snd_emu10k1 *emu, unsigned int reg, unsigned int chn, unsigned int data); | 1779 | void snd_emu10k1_ptr20_write(struct snd_emu10k1 *emu, unsigned int reg, unsigned int chn, unsigned int data); |
| 1825 | int snd_emu10k1_spi_write(struct snd_emu10k1 * emu, unsigned int data); | 1780 | int snd_emu10k1_spi_write(struct snd_emu10k1 * emu, unsigned int data); |
| 1826 | int snd_emu10k1_i2c_write(struct snd_emu10k1 *emu, u32 reg, u32 value); | 1781 | int snd_emu10k1_i2c_write(struct snd_emu10k1 *emu, u32 reg, u32 value); |
| 1827 | int snd_emu1010_fpga_write(struct snd_emu10k1 * emu, u32 reg, u32 value); | 1782 | void snd_emu1010_fpga_write(struct snd_emu10k1 *emu, u32 reg, u32 value); |
| 1828 | int snd_emu1010_fpga_read(struct snd_emu10k1 * emu, u32 reg, u32 *value); | 1783 | void snd_emu1010_fpga_read(struct snd_emu10k1 *emu, u32 reg, u32 *value); |
| 1829 | int snd_emu1010_fpga_link_dst_src_write(struct snd_emu10k1 * emu, u32 dst, u32 src); | 1784 | void snd_emu1010_fpga_link_dst_src_write(struct snd_emu10k1 *emu, u32 dst, u32 src); |
| 1830 | unsigned int snd_emu10k1_efx_read(struct snd_emu10k1 *emu, unsigned int pc); | 1785 | unsigned int snd_emu10k1_efx_read(struct snd_emu10k1 *emu, unsigned int pc); |
| 1831 | void snd_emu10k1_intr_enable(struct snd_emu10k1 *emu, unsigned int intrenb); | 1786 | void snd_emu10k1_intr_enable(struct snd_emu10k1 *emu, unsigned int intrenb); |
| 1832 | void snd_emu10k1_intr_disable(struct snd_emu10k1 *emu, unsigned int intrenb); | 1787 | void snd_emu10k1_intr_disable(struct snd_emu10k1 *emu, unsigned int intrenb); |
| @@ -0,0 +1,166 @@ | |||
| 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) 2022-2023 Intel Corporation. All rights reserved. | ||
| 7 | */ | ||
| 8 | |||
| 9 | struct hdac_bus; | ||
| 10 | struct hdac_ext_link; | ||
| 11 | |||
| 12 | #if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA_MLINK) | ||
| 13 | |||
| 14 | int hda_bus_ml_init(struct hdac_bus *bus); | ||
| 15 | void hda_bus_ml_free(struct hdac_bus *bus); | ||
| 16 | |||
| 17 | int hdac_bus_eml_get_count(struct hdac_bus *bus, bool alt, int elid); | ||
| 18 | void hdac_bus_eml_enable_interrupt(struct hdac_bus *bus, bool alt, int elid, bool enable); | ||
| 19 | bool hdac_bus_eml_check_interrupt(struct hdac_bus *bus, bool alt, int elid); | ||
| 20 | |||
| 21 | int hdac_bus_eml_set_syncprd_unlocked(struct hdac_bus *bus, bool alt, int elid, u32 syncprd); | ||
| 22 | int hdac_bus_eml_sdw_set_syncprd_unlocked(struct hdac_bus *bus, u32 syncprd); | ||
| 23 | |||
| 24 | int hdac_bus_eml_wait_syncpu_unlocked(struct hdac_bus *bus, bool alt, int elid); | ||
| 25 | int hdac_bus_eml_sdw_wait_syncpu_unlocked(struct hdac_bus *bus); | ||
| 26 | |||
| 27 | void hdac_bus_eml_sync_arm_unlocked(struct hdac_bus *bus, bool alt, int elid, int sublink); | ||
| 28 | void hdac_bus_eml_sdw_sync_arm_unlocked(struct hdac_bus *bus, int sublink); | ||
| 29 | |||
| 30 | int hdac_bus_eml_sync_go_unlocked(struct hdac_bus *bus, bool alt, int elid); | ||
| 31 | int hdac_bus_eml_sdw_sync_go_unlocked(struct hdac_bus *bus); | ||
| 32 | |||
| 33 | bool hdac_bus_eml_check_cmdsync_unlocked(struct hdac_bus *bus, bool alt, int elid); | ||
| 34 | bool hdac_bus_eml_sdw_check_cmdsync_unlocked(struct hdac_bus *bus); | ||
| 35 | |||
| 36 | int hdac_bus_eml_power_up(struct hdac_bus *bus, bool alt, int elid, int sublink); | ||
| 37 | int hdac_bus_eml_power_up_unlocked(struct hdac_bus *bus, bool alt, int elid, int sublink); | ||
| 38 | |||
| 39 | int hdac_bus_eml_power_down(struct hdac_bus *bus, bool alt, int elid, int sublink); | ||
| 40 | int hdac_bus_eml_power_down_unlocked(struct hdac_bus *bus, bool alt, int elid, int sublink); | ||
| 41 | |||
| 42 | int hdac_bus_eml_sdw_power_up_unlocked(struct hdac_bus *bus, int sublink); | ||
| 43 | int hdac_bus_eml_sdw_power_down_unlocked(struct hdac_bus *bus, int sublink); | ||
| 44 | |||
| 45 | int hdac_bus_eml_sdw_set_lsdiid(struct hdac_bus *bus, int sublink, int dev_num); | ||
| 46 | |||
| 47 | void hda_bus_ml_put_all(struct hdac_bus *bus); | ||
| 48 | void hda_bus_ml_reset_losidv(struct hdac_bus *bus); | ||
| 49 | int hda_bus_ml_resume(struct hdac_bus *bus); | ||
| 50 | int hda_bus_ml_suspend(struct hdac_bus *bus); | ||
| 51 | |||
| 52 | struct hdac_ext_link *hdac_bus_eml_ssp_get_hlink(struct hdac_bus *bus); | ||
| 53 | struct hdac_ext_link *hdac_bus_eml_dmic_get_hlink(struct hdac_bus *bus); | ||
| 54 | |||
| 55 | struct mutex *hdac_bus_eml_get_mutex(struct hdac_bus *bus, bool alt, int elid); | ||
| 56 | |||
| 57 | int hdac_bus_eml_enable_offload(struct hdac_bus *bus, bool alt, int elid, bool enable); | ||
| 58 | |||
| 59 | #else | ||
| 60 | |||
| 61 | static inline int | ||
| 62 | hda_bus_ml_init(struct hdac_bus *bus) { return 0; } | ||
| 63 | |||
| 64 | static inline void hda_bus_ml_free(struct hdac_bus *bus) { } | ||
| 65 | |||
| 66 | static inline int | ||
| 67 | hdac_bus_eml_get_count(struct hdac_bus *bus, bool alt, int elid) { return 0; } | ||
| 68 | |||
| 69 | static inline void | ||
| 70 | hdac_bus_eml_enable_interrupt(struct hdac_bus *bus, bool alt, int elid, bool enable) { } | ||
| 71 | |||
| 72 | static inline bool | ||
| 73 | hdac_bus_eml_check_interrupt(struct hdac_bus *bus, bool alt, int elid) { return false; } | ||
| 74 | |||
| 75 | static inline int | ||
| 76 | hdac_bus_eml_set_syncprd_unlocked(struct hdac_bus *bus, bool alt, int elid, u32 syncprd) | ||
| 77 | { | ||
| 78 | return 0; | ||
| 79 | } | ||
| 80 | |||
| 81 | static inline int | ||
| 82 | hdac_bus_eml_sdw_set_syncprd_unlocked(struct hdac_bus *bus, u32 syncprd) | ||
| 83 | { | ||
| 84 | return 0; | ||
| 85 | } | ||
| 86 | |||
| 87 | static inline int | ||
| 88 | hdac_bus_eml_wait_syncpu_unlocked(struct hdac_bus *bus, bool alt, int elid) | ||
| 89 | { | ||
| 90 | return 0; | ||
| 91 | } | ||
| 92 | |||
| 93 | static inline int | ||
| 94 | hdac_bus_eml_sdw_wait_syncpu_unlocked(struct hdac_bus *bus) { return 0; } | ||
| 95 | |||
| 96 | static inline void | ||
| 97 | hdac_bus_eml_sync_arm_unlocked(struct hdac_bus *bus, bool alt, int elid, int sublink) { } | ||
| 98 | |||
| 99 | static inline void | ||
| 100 | hdac_bus_eml_sdw_sync_arm_unlocked(struct hdac_bus *bus, int sublink) { } | ||
| 101 | |||
| 102 | static inline int | ||
| 103 | hdac_bus_eml_sync_go_unlocked(struct hdac_bus *bus, bool alt, int elid) { return 0; } | ||
| 104 | |||
| 105 | static inline int | ||
| 106 | hdac_bus_eml_sdw_sync_go_unlocked(struct hdac_bus *bus) { return 0; } | ||
| 107 | |||
| 108 | static inline bool | ||
| 109 | hdac_bus_eml_check_cmdsync_unlocked(struct hdac_bus *bus, bool alt, int elid) { return false; } | ||
| 110 | |||
| 111 | static inline bool | ||
| 112 | hdac_bus_eml_sdw_check_cmdsync_unlocked(struct hdac_bus *bus) { return false; } | ||
| 113 | |||
| 114 | static inline int | ||
| 115 | hdac_bus_eml_power_up(struct hdac_bus *bus, bool alt, int elid, int sublink) | ||
| 116 | { | ||
| 117 | return 0; | ||
| 118 | } | ||
| 119 | |||
| 120 | static inline int | ||
| 121 | hdac_bus_eml_power_up_unlocked(struct hdac_bus *bus, bool alt, int elid, int sublink) | ||
| 122 | { | ||
| 123 | return 0; | ||
| 124 | } | ||
| 125 | |||
| 126 | static inline int | ||
| 127 | hdac_bus_eml_power_down(struct hdac_bus *bus, bool alt, int elid, int sublink) | ||
| 128 | { | ||
| 129 | return 0; | ||
| 130 | } | ||
| 131 | |||
| 132 | static inline int | ||
| 133 | hdac_bus_eml_power_down_unlocked(struct hdac_bus *bus, bool alt, int elid, int sublink) | ||
| 134 | { | ||
| 135 | return 0; | ||
| 136 | } | ||
| 137 | |||
| 138 | static inline int | ||
| 139 | hdac_bus_eml_sdw_power_up_unlocked(struct hdac_bus *bus, int sublink) { return 0; } | ||
| 140 | |||
| 141 | static inline int | ||
| 142 | hdac_bus_eml_sdw_power_down_unlocked(struct hdac_bus *bus, int sublink) { return 0; } | ||
| 143 | |||
| 144 | static inline int | ||
| 145 | hdac_bus_eml_sdw_set_lsdiid(struct hdac_bus *bus, int sublink, int dev_num) { return 0; } | ||
| 146 | |||
| 147 | static inline void hda_bus_ml_put_all(struct hdac_bus *bus) { } | ||
| 148 | static inline void hda_bus_ml_reset_losidv(struct hdac_bus *bus) { } | ||
| 149 | static inline int hda_bus_ml_resume(struct hdac_bus *bus) { return 0; } | ||
| 150 | static inline int hda_bus_ml_suspend(struct hdac_bus *bus) { return 0; } | ||
| 151 | |||
| 152 | static inline struct hdac_ext_link * | ||
| 153 | hdac_bus_eml_ssp_get_hlink(struct hdac_bus *bus) { return NULL; } | ||
| 154 | |||
| 155 | static inline struct hdac_ext_link * | ||
| 156 | hdac_bus_eml_dmic_get_hlink(struct hdac_bus *bus) { return NULL; } | ||
| 157 | |||
| 158 | static inline struct mutex * | ||
| 159 | hdac_bus_eml_get_mutex(struct hdac_bus *bus, bool alt, int elid) { return NULL; } | ||
| 160 | |||
| 161 | static inline int | ||
| 162 | hdac_bus_eml_enable_offload(struct hdac_bus *bus, bool alt, int elid, bool enable) | ||
| 163 | { | ||
| 164 | return 0; | ||
| 165 | } | ||
| 166 | #endif /* CONFIG_SND_SOC_SOF_HDA */ | ||
| @@ -258,14 +258,27 @@ enum { SDI0, SDI1, SDI2, SDI3, SDO0, SDO1, SDO2, SDO3 }; · 257 unmodified lines | |||
| 258 | #define AZX_ML_BASE 0x40 | 258 | #define AZX_ML_BASE 0x40 |
| 259 | #define AZX_ML_INTERVAL 0x40 | 259 | #define AZX_ML_INTERVAL 0x40 |
| 260 | 260 | ||
| 261 | /* HDaudio registers valid for HDaudio and HDaudio extended links */ | ||
| 261 | #define AZX_REG_ML_LCAP 0x00 | 262 | #define AZX_REG_ML_LCAP 0x00 |
| 262 | #define AZX_REG_ML_LCTL 0x04 | ||
| 263 | 263 | ||
| 264 | #define AZX_ML_HDA_LCAP_ALT BIT(28) | ||
| 265 | #define AZX_ML_HDA_LCAP_ALT_HDA 0x0 | ||
| 266 | #define AZX_ML_HDA_LCAP_ALT_HDA_EXT 0x1 | ||
| 267 | |||
| 268 | #define AZX_ML_HDA_LCAP_INTC BIT(27) /* only used if ALT == 1 */ | ||
| 269 | #define AZX_ML_HDA_LCAP_OFLS BIT(26) /* only used if ALT == 1 */ | ||
| 270 | #define AZX_ML_HDA_LCAP_LSS BIT(23) /* only used if ALT == 1 */ | ||
| 271 | #define AZX_ML_HDA_LCAP_SLCOUNT GENMASK(22, 20) /* only used if ALT == 1 */ | ||
| 272 | |||
| 273 | #define AZX_REG_ML_LCTL 0x04 | ||
| 274 | #define AZX_ML_LCTL_INTSTS BIT(31) /* only used if ALT == 1 */ | ||
| 264 | #define AZX_ML_LCTL_CPA BIT(23) | 275 | #define AZX_ML_LCTL_CPA BIT(23) |
| 265 | #define AZX_ML_LCTL_CPA_SHIFT 23 | 276 | #define AZX_ML_LCTL_CPA_SHIFT 23 |
| 266 | #define AZX_ML_LCTL_SPA BIT(16) | 277 | #define AZX_ML_LCTL_SPA BIT(16) |
| 267 | #define AZX_ML_LCTL_SPA_SHIFT 16 | 278 | #define AZX_ML_LCTL_SPA_SHIFT 16 |
| 268 | #define AZX_ML_LCTL_SCF GENMASK(3, 0) | 279 | #define AZX_ML_LCTL_INTEN BIT(5) /* only used if ALT == 1 */ |
| 280 | #define AZX_ML_LCTL_OFLEN BIT(4) /* only used if ALT == 1 */ | ||
| 281 | #define AZX_ML_LCTL_SCF GENMASK(3, 0) /* only used if ALT == 0 */ | ||
| 269 | 282 | ||
| 270 | #define AZX_REG_ML_LOSIDV 0x08 | 283 | #define AZX_REG_ML_LOSIDV 0x08 |
| 271 | 284 | ||
| @@ -273,12 +286,35 @@ enum { SDI0, SDI1, SDI2, SDI3, SDO0, SDO1, SDO2, SDO3 }; · 1 unmodified line | |||
| 273 | #define AZX_ML_LOSIDV_STREAM_MASK 0xFFFE | 286 | #define AZX_ML_LOSIDV_STREAM_MASK 0xFFFE |
| 274 | 287 | ||
| 275 | #define AZX_REG_ML_LSDIID 0x0C | 288 | #define AZX_REG_ML_LSDIID 0x0C |
| 289 | #define AZX_REG_ML_LSDIID_OFFSET(x) (0x0C + (x) * 0x02) /* only used if ALT == 1 */ | ||
| 290 | |||
| 291 | /* HDaudio registers only valid if LCAP.ALT == 0 */ | ||
| 276 | #define AZX_REG_ML_LPSOO 0x10 | 292 | #define AZX_REG_ML_LPSOO 0x10 |
| 277 | #define AZX_REG_ML_LPSIO 0x12 | 293 | #define AZX_REG_ML_LPSIO 0x12 |
| 278 | #define AZX_REG_ML_LWALFC 0x18 | 294 | #define AZX_REG_ML_LWALFC 0x18 |
| 279 | #define AZX_REG_ML_LOUTPAY 0x20 | 295 | #define AZX_REG_ML_LOUTPAY 0x20 |
| 280 | #define AZX_REG_ML_LINPAY 0x30 | 296 | #define AZX_REG_ML_LINPAY 0x30 |
| 281 | 297 | ||
| 298 | /* HDaudio Extended link registers only valid if LCAP.ALT == 1 */ | ||
| 299 | #define AZX_REG_ML_LSYNC 0x1C | ||
| 300 | |||
| 301 | #define AZX_REG_ML_LSYNC_CMDSYNC BIT(24) | ||
| 302 | #define AZX_REG_ML_LSYNC_CMDSYNC_SHIFT 24 | ||
| 303 | #define AZX_REG_ML_LSYNC_SYNCGO BIT(23) | ||
| 304 | #define AZX_REG_ML_LSYNC_SYNCPU BIT(20) | ||
| 305 | #define AZX_REG_ML_LSYNC_SYNCPRD GENMASK(19, 0) | ||
| 306 | |||
| 307 | #define AZX_REG_ML_LEPTR 0x20 | ||
| 308 | |||
| 309 | #define AZX_REG_ML_LEPTR_ID GENMASK(31, 24) | ||
| 310 | #define AZX_REG_ML_LEPTR_ID_SHIFT 24 | ||
| 311 | #define AZX_REG_ML_LEPTR_ID_SDW 0x00 | ||
| 312 | #define AZX_REG_ML_LEPTR_ID_INTEL_SSP 0xC0 | ||
| 313 | #define AZX_REG_ML_LEPTR_ID_INTEL_DMIC 0xC1 | ||
| 314 | #define AZX_REG_ML_LEPTR_ID_INTEL_UAOL 0xC2 | ||
| 315 | #define AZX_REG_ML_LEPTR_VER GENMASK(23, 20) | ||
| 316 | #define AZX_REG_ML_LEPTR_PTR GENMASK(19, 0) | ||
| 317 | |||
| 282 | /* registers for DMA Resume Capability Structure */ | 318 | /* registers for DMA Resume Capability Structure */ |
| 283 | #define AZX_DRSM_CAP_ID 0x5 | 319 | #define AZX_DRSM_CAP_ID 0x5 |
| 284 | #define AZX_REG_DRSM_CTL 0x4 | 320 | #define AZX_REG_DRSM_CTL 0x4 |
| @@ -44,7 +44,7 @@ snd_pcm_indirect_playback_transfer(struct snd_pcm_substream *substream, · 43 unmodified lines | |||
| 44 | if (diff < -(snd_pcm_sframes_t) (runtime->boundary / 2)) | 44 | if (diff < -(snd_pcm_sframes_t) (runtime->boundary / 2)) |
| 45 | diff += runtime->boundary; | 45 | diff += runtime->boundary; |
| 46 | if (diff < 0) | 46 | if (diff < 0) |
| 47 | return -EINVAL; | 47 | return -EPIPE; |
| 48 | rec->sw_ready += (int)frames_to_bytes(runtime, diff); | 48 | rec->sw_ready += (int)frames_to_bytes(runtime, diff); |
| 49 | rec->appl_ptr = appl_ptr; | 49 | rec->appl_ptr = appl_ptr; |
| 50 | } | 50 | } |
| @@ -83,6 +83,8 @@ snd_pcm_indirect_playback_pointer(struct snd_pcm_substream *substream, · 32 unmodified lines | |||
| 83 | struct snd_pcm_indirect *rec, unsigned int ptr) | 83 | struct snd_pcm_indirect *rec, unsigned int ptr) |
| 84 | { | 84 | { |
| 85 | int bytes = ptr - rec->hw_io; | 85 | int bytes = ptr - rec->hw_io; |
| 86 | int err; | ||
| 87 | |||
| 86 | if (bytes < 0) | 88 | if (bytes < 0) |
| 87 | bytes += rec->hw_buffer_size; | 89 | bytes += rec->hw_buffer_size; |
| 88 | rec->hw_io = ptr; | 90 | rec->hw_io = ptr; |
| @@ -90,8 +92,11 @@ snd_pcm_indirect_playback_pointer(struct snd_pcm_substream *substream, · 1 unmodified line | |||
| 90 | rec->sw_io += bytes; | 92 | rec->sw_io += bytes; |
| 91 | if (rec->sw_io >= rec->sw_buffer_size) | 93 | if (rec->sw_io >= rec->sw_buffer_size) |
| 92 | rec->sw_io -= rec->sw_buffer_size; | 94 | rec->sw_io -= rec->sw_buffer_size; |
| 93 | if (substream->ops->ack) | 95 | if (substream->ops->ack) { |
| 94 | substream->ops->ack(substream); | 96 | err = substream->ops->ack(substream); |
| 97 | if (err == -EPIPE) | ||
| 98 | return SNDRV_PCM_POS_XRUN; | ||
| 99 | } | ||
| 95 | return bytes_to_frames(substream->runtime, rec->sw_io); | 100 | return bytes_to_frames(substream->runtime, rec->sw_io); |
| 96 | } | 101 | } |
| 97 | 102 | ||
| @@ -112,7 +117,7 @@ snd_pcm_indirect_capture_transfer(struct snd_pcm_substream *substream, · 14 unmodified lines | |||
| 112 | if (diff < -(snd_pcm_sframes_t) (runtime->boundary / 2)) | 117 | if (diff < -(snd_pcm_sframes_t) (runtime->boundary / 2)) |
| 113 | diff += runtime->boundary; | 118 | diff += runtime->boundary; |
| 114 | if (diff < 0) | 119 | if (diff < 0) |
| 115 | return -EINVAL; | 120 | return -EPIPE; |
| 116 | rec->sw_ready -= frames_to_bytes(runtime, diff); | 121 | rec->sw_ready -= frames_to_bytes(runtime, diff); |
| 117 | rec->appl_ptr = appl_ptr; | 122 | rec->appl_ptr = appl_ptr; |
| 118 | } | 123 | } |
| @@ -152,6 +157,8 @@ snd_pcm_indirect_capture_pointer(struct snd_pcm_substream *substream, · 33 unmodified lines | |||
| 152 | { | 157 | { |
| 153 | int qsize; | 158 | int qsize; |
| 154 | int bytes = ptr - rec->hw_io; | 159 | int bytes = ptr - rec->hw_io; |
| 160 | int err; | ||
| 161 | |||
| 155 | if (bytes < 0) | 162 | if (bytes < 0) |
| 156 | bytes += rec->hw_buffer_size; | 163 | bytes += rec->hw_buffer_size; |
| 157 | rec->hw_io = ptr; | 164 | rec->hw_io = ptr; |
| @@ -162,8 +169,11 @@ snd_pcm_indirect_capture_pointer(struct snd_pcm_substream *substream, · 4 unmodified lines | |||
| 162 | rec->sw_io += bytes; | 169 | rec->sw_io += bytes; |
| 163 | if (rec->sw_io >= rec->sw_buffer_size) | 170 | if (rec->sw_io >= rec->sw_buffer_size) |
| 164 | rec->sw_io -= rec->sw_buffer_size; | 171 | rec->sw_io -= rec->sw_buffer_size; |
| 165 | if (substream->ops->ack) | 172 | if (substream->ops->ack) { |
| 166 | substream->ops->ack(substream); | 173 | err = substream->ops->ack(substream); |
| 174 | if (err == -EPIPE) | ||
| 175 | return SNDRV_PCM_POS_XRUN; | ||
| 176 | } | ||
| 167 | return bytes_to_frames(substream->runtime, rec->sw_io); | 177 | return bytes_to_frames(substream->runtime, rec->sw_io); |
| 168 | } | 178 | } |
| 169 | 179 | ||
| @@ -378,18 +378,18 @@ struct snd_pcm_runtime { · 377 unmodified lines | |||
| 378 | unsigned int rate_den; | 378 | unsigned int rate_den; |
| 379 | unsigned int no_period_wakeup: 1; | 379 | unsigned int no_period_wakeup: 1; |
| 380 | 380 | ||
| 381 | /* -- SW params -- */ | 381 | /* -- SW params; see struct snd_pcm_sw_params for comments -- */ |
| 382 | int tstamp_mode; /* mmap timestamp is updated */ | 382 | int tstamp_mode; |
| 383 | unsigned int period_step; | 383 | unsigned int period_step; |
| 384 | snd_pcm_uframes_t start_threshold; | 384 | snd_pcm_uframes_t start_threshold; |
| 385 | snd_pcm_uframes_t stop_threshold; | 385 | snd_pcm_uframes_t stop_threshold; |
| 386 | snd_pcm_uframes_t silence_threshold; /* Silence filling happens when | 386 | snd_pcm_uframes_t silence_threshold; |
| 387 | noise is nearest than this */ | 387 | snd_pcm_uframes_t silence_size; |
| 388 | snd_pcm_uframes_t silence_size; /* Silence filling size */ | 388 | snd_pcm_uframes_t boundary; |
| 389 | snd_pcm_uframes_t boundary; /* pointers wrap point */ | ||
| 390 | 389 | ||
| 390 | /* internal data of auto-silencer */ | ||
| 391 | snd_pcm_uframes_t silence_start; /* starting pointer to silence area */ | 391 | snd_pcm_uframes_t silence_start; /* starting pointer to silence area */ |
| 392 | snd_pcm_uframes_t silence_filled; /* size filled with silence */ | 392 | snd_pcm_uframes_t silence_filled; /* already filled part of silence area */ |
| 393 | 393 | ||
| 394 | union snd_pcm_sync_id sync; /* hardware synchronization ID */ | 394 | union snd_pcm_sync_id sync; /* hardware synchronization ID */ |
| 395 | 395 | ||
| @@ -9,10 +9,25 @@ · 8 unmodified lines | |||
| 9 | #define __SOC_CARD_H | 9 | #define __SOC_CARD_H |
| 10 | 10 | ||
| 11 | enum snd_soc_card_subclass { | 11 | enum snd_soc_card_subclass { |
| 12 | SND_SOC_CARD_CLASS_INIT = 0, | 12 | SND_SOC_CARD_CLASS_ROOT = 0, |
| 13 | SND_SOC_CARD_CLASS_RUNTIME = 1, | 13 | SND_SOC_CARD_CLASS_RUNTIME = 1, |
| 14 | }; | 14 | }; |
| 15 | 15 | ||
| 16 | static inline void snd_soc_card_mutex_lock_root(struct snd_soc_card *card) | ||
| 17 | { | ||
| 18 | mutex_lock_nested(&card->mutex, SND_SOC_CARD_CLASS_ROOT); | ||
| 19 | } | ||
| 20 | |||
| 21 | static inline void snd_soc_card_mutex_lock(struct snd_soc_card *card) | ||
| 22 | { | ||
| 23 | mutex_lock_nested(&card->mutex, SND_SOC_CARD_CLASS_RUNTIME); | ||
| 24 | } | ||
| 25 | |||
| 26 | static inline void snd_soc_card_mutex_unlock(struct snd_soc_card *card) | ||
| 27 | { | ||
| 28 | mutex_unlock(&card->mutex); | ||
| 29 | } | ||
| 30 | |||
| 16 | struct snd_kcontrol *snd_soc_card_get_kcontrol(struct snd_soc_card *soc_card, | 31 | struct snd_kcontrol *snd_soc_card_get_kcontrol(struct snd_soc_card *soc_card, |
| 17 | const char *name); | 32 | const char *name); |
| 18 | int snd_soc_card_jack_new(struct snd_soc_card *card, const char *id, int type, | 33 | int snd_soc_card_jack_new(struct snd_soc_card *card, const char *id, int type, |
| @@ -527,11 +527,6 @@ enum snd_soc_dapm_type { · 526 unmodified lines | |||
| 527 | SND_SOC_DAPM_TYPE_COUNT | 527 | SND_SOC_DAPM_TYPE_COUNT |
| 528 | }; | 528 | }; |
| 529 | 529 | ||
| 530 | enum snd_soc_dapm_subclass { | ||
| 531 | SND_SOC_DAPM_CLASS_INIT = 0, | ||
| 532 | SND_SOC_DAPM_CLASS_RUNTIME = 1, | ||
| 533 | }; | ||
| 534 | |||
| 535 | /* | 530 | /* |
| 536 | * DAPM audio route definition. | 531 | * DAPM audio route definition. |
| 537 | * | 532 | * |
| @@ -91,7 +91,6 @@ struct snd_soc_dpcm_runtime { · 90 unmodified lines | |||
| 91 | struct list_head fe_clients; | 91 | struct list_head fe_clients; |
| 92 | 92 | ||
| 93 | int users; | 93 | int users; |
| 94 | struct snd_pcm_runtime *runtime; | ||
| 95 | struct snd_pcm_hw_params hw_params; | 94 | struct snd_pcm_hw_params hw_params; |
| 96 | 95 | ||
| 97 | /* state and update */ | 96 | /* state and update */ |
| @@ -684,8 +684,11 @@ struct snd_soc_dai_link { · 683 unmodified lines | |||
| 684 | 684 | ||
| 685 | int id; /* optional ID for machine driver link identification */ | 685 | int id; /* optional ID for machine driver link identification */ |
| 686 | 686 | ||
| 687 | const struct snd_soc_pcm_stream *params; | 687 | /* |
| 688 | unsigned int num_params; | 688 | * for Codec2Codec |
| 689 | */ | ||
| 690 | const struct snd_soc_pcm_stream *c2c_params; | ||
| 691 | unsigned int num_c2c_params; | ||
| 689 | 692 | ||
| 690 | unsigned int dai_fmt; /* format to set on init */ | 693 | unsigned int dai_fmt; /* format to set on init */ |
| 691 | 694 | ||
| @@ -1065,7 +1068,7 @@ struct snd_soc_pcm_runtime { · 373 unmodified lines | |||
| 1065 | struct snd_soc_dai_link *dai_link; | 1068 | struct snd_soc_dai_link *dai_link; |
| 1066 | struct snd_pcm_ops ops; | 1069 | struct snd_pcm_ops ops; |
| 1067 | 1070 | ||
| 1068 | unsigned int params_select; /* currently selected param for dai link */ | 1071 | unsigned int c2c_params_select; /* currently selected c2c_param for dai link */ |
| 1069 | 1072 | ||
| 1070 | /* Dynamic PCM BE runtime data */ | 1073 | /* Dynamic PCM BE runtime data */ |
| 1071 | struct snd_soc_dpcm_runtime dpcm[SNDRV_PCM_STREAM_LAST + 1]; | 1074 | struct snd_soc_dpcm_runtime dpcm[SNDRV_PCM_STREAM_LAST + 1]; |
| @@ -1302,8 +1305,9 @@ int snd_soc_of_get_dai_link_cpus(struct device *dev, · 230 unmodified lines | |||
| 1302 | struct snd_soc_dai_link *dai_link); | 1305 | struct snd_soc_dai_link *dai_link); |
| 1303 | void snd_soc_of_put_dai_link_cpus(struct snd_soc_dai_link *dai_link); | 1306 | void snd_soc_of_put_dai_link_cpus(struct snd_soc_dai_link *dai_link); |
| 1304 | 1307 | ||
| 1305 | int snd_soc_add_pcm_runtime(struct snd_soc_card *card, | 1308 | int snd_soc_add_pcm_runtimes(struct snd_soc_card *card, |
| 1306 | struct snd_soc_dai_link *dai_link); | 1309 | struct snd_soc_dai_link *dai_link, |
| 1310 | int num_dai_link); | ||
| 1307 | void snd_soc_remove_pcm_runtime(struct snd_soc_card *card, | 1311 | void snd_soc_remove_pcm_runtime(struct snd_soc_card *card, |
| 1308 | struct snd_soc_pcm_runtime *rtd); | 1312 | struct snd_soc_pcm_runtime *rtd); |
| 1309 | 1313 | ||
| @@ -1360,17 +1364,112 @@ extern struct dentry *snd_soc_debugfs_root; · 50 unmodified lines | |||
| 1360 | 1364 | ||
| 1361 | extern const struct dev_pm_ops snd_soc_pm_ops; | 1365 | extern const struct dev_pm_ops snd_soc_pm_ops; |
| 1362 | 1366 | ||
| 1363 | /* Helper functions */ | 1367 | /* |
| 1364 | static inline void snd_soc_dapm_mutex_lock(struct snd_soc_dapm_context *dapm) | 1368 | * DAPM helper functions |
| 1369 | */ | ||
| 1370 | enum snd_soc_dapm_subclass { | ||
| 1371 | SND_SOC_DAPM_CLASS_ROOT = 0, | ||
| 1372 | SND_SOC_DAPM_CLASS_RUNTIME = 1, | ||
| 1373 | }; | ||
| 1374 | |||
| 1375 | static inline void _snd_soc_dapm_mutex_lock_root_c(struct snd_soc_card *card) | ||
| 1376 | { | ||
| 1377 | mutex_lock_nested(&card->dapm_mutex, SND_SOC_DAPM_CLASS_ROOT); | ||
| 1378 | } | ||
| 1379 | |||
| 1380 | static inline void _snd_soc_dapm_mutex_lock_c(struct snd_soc_card *card) | ||
| 1381 | { | ||
| 1382 | mutex_lock_nested(&card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME); | ||
| 1383 | } | ||
| 1384 | |||
| 1385 | static inline void _snd_soc_dapm_mutex_unlock_c(struct snd_soc_card *card) | ||
| 1386 | { | ||
| 1387 | mutex_unlock(&card->dapm_mutex); | ||
| 1388 | } | ||
| 1389 | |||
| 1390 | static inline void _snd_soc_dapm_mutex_assert_held_c(struct snd_soc_card *card) | ||
| 1391 | { | ||
| 1392 | lockdep_assert_held(&card->dapm_mutex); | ||
| 1393 | } | ||
| 1394 | |||
| 1395 | static inline void _snd_soc_dapm_mutex_lock_root_d(struct snd_soc_dapm_context *dapm) | ||
| 1396 | { | ||
| 1397 | _snd_soc_dapm_mutex_lock_root_c(dapm->card); | ||
| 1398 | } | ||
| 1399 | |||
| 1400 | static inline void _snd_soc_dapm_mutex_lock_d(struct snd_soc_dapm_context *dapm) | ||
| 1401 | { | ||
| 1402 | _snd_soc_dapm_mutex_lock_c(dapm->card); | ||
| 1403 | } | ||
| 1404 | |||
| 1405 | static inline void _snd_soc_dapm_mutex_unlock_d(struct snd_soc_dapm_context *dapm) | ||
| 1365 | { | 1406 | { |
| 1366 | mutex_lock_nested(&dapm->card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME); | 1407 | _snd_soc_dapm_mutex_unlock_c(dapm->card); |
| 1367 | } | 1408 | } |
| 1368 | 1409 | ||
| 1369 | static inline void snd_soc_dapm_mutex_unlock(struct snd_soc_dapm_context *dapm) | 1410 | static inline void _snd_soc_dapm_mutex_assert_held_d(struct snd_soc_dapm_context *dapm) |
| 1370 | { | 1411 | { |
| 1371 | mutex_unlock(&dapm->card->dapm_mutex); | 1412 | _snd_soc_dapm_mutex_assert_held_c(dapm->card); |
| 1372 | } | 1413 | } |
| 1373 | 1414 | ||
| 1415 | #define snd_soc_dapm_mutex_lock_root(x) _Generic((x), \ | ||
| 1416 | struct snd_soc_card * : _snd_soc_dapm_mutex_lock_root_c, \ | ||
| 1417 | struct snd_soc_dapm_context * : _snd_soc_dapm_mutex_lock_root_d)(x) | ||
| 1418 | #define snd_soc_dapm_mutex_lock(x) _Generic((x), \ | ||
| 1419 | struct snd_soc_card * : _snd_soc_dapm_mutex_lock_c, \ | ||
| 1420 | struct snd_soc_dapm_context * : _snd_soc_dapm_mutex_lock_d)(x) | ||
| 1421 | #define snd_soc_dapm_mutex_unlock(x) _Generic((x), \ | ||
| 1422 | struct snd_soc_card * : _snd_soc_dapm_mutex_unlock_c, \ | ||
| 1423 | struct snd_soc_dapm_context * : _snd_soc_dapm_mutex_unlock_d)(x) | ||
| 1424 | #define snd_soc_dapm_mutex_assert_held(x) _Generic((x), \ | ||
| 1425 | struct snd_soc_card * : _snd_soc_dapm_mutex_assert_held_c, \ | ||
| 1426 | struct snd_soc_dapm_context * : _snd_soc_dapm_mutex_assert_held_d)(x) | ||
| 1427 | |||
| 1428 | /* | ||
| 1429 | * PCM helper functions | ||
| 1430 | */ | ||
| 1431 | static inline void _snd_soc_dpcm_mutex_lock_c(struct snd_soc_card *card) | ||
| 1432 | { | ||
| 1433 | mutex_lock_nested(&card->pcm_mutex, card->pcm_subclass); | ||
| 1434 | } | ||
| 1435 | |||
| 1436 | static inline void _snd_soc_dpcm_mutex_unlock_c(struct snd_soc_card *card) | ||
| 1437 | { | ||
| 1438 | mutex_unlock(&card->pcm_mutex); | ||
| 1439 | } | ||
| 1440 | |||
| 1441 | static inline void _snd_soc_dpcm_mutex_assert_held_c(struct snd_soc_card *card) | ||
| 1442 | { | ||
| 1443 | lockdep_assert_held(&card->pcm_mutex); | ||
| 1444 | } | ||
| 1445 | |||
| 1446 | static inline void _snd_soc_dpcm_mutex_lock_r(struct snd_soc_pcm_runtime *rtd) | ||
| 1447 | { | ||
| 1448 | _snd_soc_dpcm_mutex_lock_c(rtd->card); | ||
| 1449 | } | ||
| 1450 | |||
| 1451 | static inline void _snd_soc_dpcm_mutex_unlock_r(struct snd_soc_pcm_runtime *rtd) | ||
| 1452 | { | ||
| 1453 | _snd_soc_dpcm_mutex_unlock_c(rtd->card); | ||
| 1454 | } | ||
| 1455 | |||
| 1456 | static inline void _snd_soc_dpcm_mutex_assert_held_r(struct snd_soc_pcm_runtime *rtd) | ||
| 1457 | { | ||
| 1458 | _snd_soc_dpcm_mutex_assert_held_c(rtd->card); | ||
| 1459 | } | ||
| 1460 | |||
| 1461 | #define snd_soc_dpcm_mutex_lock(x) _Generic((x), \ | ||
| 1462 | struct snd_soc_card * : _snd_soc_dpcm_mutex_lock_c, \ | ||
| 1463 | struct snd_soc_pcm_runtime * : _snd_soc_dpcm_mutex_lock_r)(x) | ||
| 1464 | |||
| 1465 | #define snd_soc_dpcm_mutex_unlock(x) _Generic((x), \ | ||
| 1466 | struct snd_soc_card * : _snd_soc_dpcm_mutex_unlock_c, \ | ||
| 1467 | struct snd_soc_pcm_runtime * : _snd_soc_dpcm_mutex_unlock_r)(x) | ||
| 1468 | |||
| 1469 | #define snd_soc_dpcm_mutex_assert_held(x) _Generic((x), \ | ||
| 1470 | struct snd_soc_card * : _snd_soc_dpcm_mutex_assert_held_c, \ | ||
| 1471 | struct snd_soc_pcm_runtime * : _snd_soc_dpcm_mutex_assert_held_r)(x) | ||
| 1472 | |||
| 1374 | #include <sound/soc-component.h> | 1473 | #include <sound/soc-component.h> |
| 1375 | #include <sound/soc-card.h> | 1474 | #include <sound/soc-card.h> |
| 1376 | #include <sound/soc-jack.h> | 1475 | #include <sound/soc-jack.h> |
| @@ -21,6 +21,7 @@ struct snd_sof_dev; · 20 unmodified lines | |||
| 21 | /** | 21 | /** |
| 22 | * enum sof_fw_state - DSP firmware state definitions | 22 | * enum sof_fw_state - DSP firmware state definitions |
| 23 | * @SOF_FW_BOOT_NOT_STARTED: firmware boot is not yet started | 23 | * @SOF_FW_BOOT_NOT_STARTED: firmware boot is not yet started |
| 24 | * @SOF_DSPLESS_MODE: DSP is not used | ||
| 24 | * @SOF_FW_BOOT_PREPARE: preparing for boot (firmware loading for exaqmple) | 25 | * @SOF_FW_BOOT_PREPARE: preparing for boot (firmware loading for exaqmple) |
| 25 | * @SOF_FW_BOOT_IN_PROGRESS: firmware boot is in progress | 26 | * @SOF_FW_BOOT_IN_PROGRESS: firmware boot is in progress |
| 26 | * @SOF_FW_BOOT_FAILED: firmware boot failed | 27 | * @SOF_FW_BOOT_FAILED: firmware boot failed |
| @@ -31,6 +32,7 @@ struct snd_sof_dev; · 4 unmodified lines | |||
| 31 | */ | 32 | */ |
| 32 | enum sof_fw_state { | 33 | enum sof_fw_state { |
| 33 | SOF_FW_BOOT_NOT_STARTED = 0, | 34 | SOF_FW_BOOT_NOT_STARTED = 0, |
| 35 | SOF_DSPLESS_MODE, | ||
| 34 | SOF_FW_BOOT_PREPARE, | 36 | SOF_FW_BOOT_PREPARE, |
| 35 | SOF_FW_BOOT_IN_PROGRESS, | 37 | SOF_FW_BOOT_IN_PROGRESS, |
| 36 | SOF_FW_BOOT_FAILED, | 38 | SOF_FW_BOOT_FAILED, |
| @@ -130,6 +132,9 @@ struct sof_dev_desc { · 93 unmodified lines | |||
| 130 | unsigned int ipc_supported_mask; | 132 | unsigned int ipc_supported_mask; |
| 131 | enum sof_ipc_type ipc_default; | 133 | enum sof_ipc_type ipc_default; |
| 132 | 134 | ||
| 135 | /* The platform supports DSPless mode */ | ||
| 136 | bool dspless_mode_supported; | ||
| 137 | |||
| 133 | /* defaults paths for firmware, library and topology files */ | 138 | /* defaults paths for firmware, library and topology files */ |
| 134 | const char *default_fw_path[SOF_IPC_TYPE_COUNT]; | 139 | const char *default_fw_path[SOF_IPC_TYPE_COUNT]; |
| 135 | const char *default_lib_path[SOF_IPC_TYPE_COUNT]; | 140 | const char *default_lib_path[SOF_IPC_TYPE_COUNT]; |
| @@ -176,6 +176,10 @@ enum sof_ipc4_pipeline_state { · 175 unmodified lines | |||
| 176 | #define SOF_IPC4_GLB_PIPE_EXT_LP_MASK BIT(0) | 176 | #define SOF_IPC4_GLB_PIPE_EXT_LP_MASK BIT(0) |
| 177 | #define SOF_IPC4_GLB_PIPE_EXT_LP(x) ((x) << SOF_IPC4_GLB_PIPE_EXT_LP_SHIFT) | 177 | #define SOF_IPC4_GLB_PIPE_EXT_LP(x) ((x) << SOF_IPC4_GLB_PIPE_EXT_LP_SHIFT) |
| 178 | 178 | ||
| 179 | #define SOF_IPC4_GLB_PIPE_EXT_CORE_ID_SHIFT 20 | ||
| 180 | #define SOF_IPC4_GLB_PIPE_EXT_CORE_ID_MASK GENMASK(23, 20) | ||
| 181 | #define SOF_IPC4_GLB_PIPE_EXT_CORE_ID(x) ((x) << SOF_IPC4_GLB_PIPE_EXT_CORE_ID_SHIFT) | ||
| 182 | |||
| 179 | /* pipeline set state ipc msg */ | 183 | /* pipeline set state ipc msg */ |
| 180 | #define SOF_IPC4_GLB_PIPE_STATE_ID_SHIFT 16 | 184 | #define SOF_IPC4_GLB_PIPE_STATE_ID_SHIFT 16 |
| 181 | #define SOF_IPC4_GLB_PIPE_STATE_ID_MASK GENMASK(23, 16) | 185 | #define SOF_IPC4_GLB_PIPE_STATE_ID_MASK GENMASK(23, 16) |
| @@ -192,6 +196,35 @@ enum sof_ipc4_pipeline_state { · 10 unmodified lines | |||
| 192 | #define SOF_IPC4_GLB_LOAD_LIBRARY_LIB_ID_SHIFT 16 | 196 | #define SOF_IPC4_GLB_LOAD_LIBRARY_LIB_ID_SHIFT 16 |
| 193 | #define SOF_IPC4_GLB_LOAD_LIBRARY_LIB_ID(x) ((x) << SOF_IPC4_GLB_LOAD_LIBRARY_LIB_ID_SHIFT) | 197 | #define SOF_IPC4_GLB_LOAD_LIBRARY_LIB_ID(x) ((x) << SOF_IPC4_GLB_LOAD_LIBRARY_LIB_ID_SHIFT) |
| 194 | 198 | ||
| 199 | /* chain dma ipc message */ | ||
| 200 | #define SOF_IPC4_GLB_CHAIN_DMA_HOST_ID_SHIFT 0 | ||
| 201 | #define SOF_IPC4_GLB_CHAIN_DMA_HOST_ID_MASK GENMASK(4, 0) | ||
| 202 | #define SOF_IPC4_GLB_CHAIN_DMA_HOST_ID(x) (((x) << SOF_IPC4_GLB_CHAIN_DMA_HOST_ID_SHIFT) & \ | ||
| 203 | SOF_IPC4_GLB_CHAIN_DMA_HOST_ID_MASK) | ||
| 204 | |||
| 205 | #define SOF_IPC4_GLB_CHAIN_DMA_LINK_ID_SHIFT 8 | ||
| 206 | #define SOF_IPC4_GLB_CHAIN_DMA_LINK_ID_MASK GENMASK(12, 8) | ||
| 207 | #define SOF_IPC4_GLB_CHAIN_DMA_LINK_ID(x) (((x) << SOF_IPC4_GLB_CHAIN_DMA_LINK_ID_SHIFT) & \ | ||
| 208 | SOF_IPC4_GLB_CHAIN_DMA_LINK_ID_MASK) | ||
| 209 | |||
| 210 | #define SOF_IPC4_GLB_CHAIN_DMA_ALLOCATE_SHIFT 16 | ||
| 211 | #define SOF_IPC4_GLB_CHAIN_DMA_ALLOCATE_MASK BIT(16) | ||
| 212 | #define SOF_IPC4_GLB_CHAIN_DMA_ALLOCATE(x) (((x) & 1) << SOF_IPC4_GLB_CHAIN_DMA_ALLOCATE_SHIFT) | ||
| 213 | |||
| 214 | #define SOF_IPC4_GLB_CHAIN_DMA_ENABLE_SHIFT 17 | ||
| 215 | #define SOF_IPC4_GLB_CHAIN_DMA_ENABLE_MASK BIT(17) | ||
| 216 | #define SOF_IPC4_GLB_CHAIN_DMA_ENABLE(x) (((x) & 1) << SOF_IPC4_GLB_CHAIN_DMA_ENABLE_SHIFT) | ||
| 217 | |||
| 218 | #define SOF_IPC4_GLB_CHAIN_DMA_SCS_SHIFT 18 | ||
| 219 | #define SOF_IPC4_GLB_CHAIN_DMA_SCS_MASK BIT(18) | ||
| 220 | #define SOF_IPC4_GLB_CHAIN_DMA_SCS(x) (((x) & 1) << SOF_IPC4_GLB_CHAIN_DMA_SCS_SHIFT) | ||
| 221 | |||
| 222 | #define SOF_IPC4_GLB_EXT_CHAIN_DMA_FIFO_SIZE_SHIFT 0 | ||
| 223 | #define SOF_IPC4_GLB_EXT_CHAIN_DMA_FIFO_SIZE_MASK GENMASK(24, 0) | ||
| 224 | #define SOF_IPC4_GLB_EXT_CHAIN_DMA_FIFO_SIZE(x) (((x) << \ | ||
| 225 | SOF_IPC4_GLB_EXT_CHAIN_DMA_FIFO_SIZE_SHIFT) & \ | ||
| 226 | SOF_IPC4_GLB_EXT_CHAIN_DMA_FIFO_SIZE_MASK) | ||
| 227 | |||
| 195 | enum sof_ipc4_channel_config { | 228 | enum sof_ipc4_channel_config { |
| 196 | /* one channel only. */ | 229 | /* one channel only. */ |
| 197 | SOF_IPC4_CHANNEL_CONFIG_MONO, | 230 | SOF_IPC4_CHANNEL_CONFIG_MONO, |
| @@ -429,9 +429,14 @@ struct snd_pcm_sw_params { · 428 unmodified lines | |||
| 429 | snd_pcm_uframes_t avail_min; /* min avail frames for wakeup */ | 429 | snd_pcm_uframes_t avail_min; /* min avail frames for wakeup */ |
| 430 | snd_pcm_uframes_t xfer_align; /* obsolete: xfer size need to be a multiple */ | 430 | snd_pcm_uframes_t xfer_align; /* obsolete: xfer size need to be a multiple */ |
| 431 | snd_pcm_uframes_t start_threshold; /* min hw_avail frames for automatic start */ | 431 | snd_pcm_uframes_t start_threshold; /* min hw_avail frames for automatic start */ |
| 432 | snd_pcm_uframes_t stop_threshold; /* min avail frames for automatic stop */ | 432 | /* |
| 433 | snd_pcm_uframes_t silence_threshold; /* min distance from noise for silence filling */ | 433 | * The following two thresholds alleviate playback buffer underruns; when |
| 434 | snd_pcm_uframes_t silence_size; /* silence block size */ | 434 | * hw_avail drops below the threshold, the respective action is triggered: |
| 435 | */ | ||
| 436 | snd_pcm_uframes_t stop_threshold; /* - stop playback */ | ||
| 437 | snd_pcm_uframes_t silence_threshold; /* - pre-fill buffer with silence */ | ||
| 438 | snd_pcm_uframes_t silence_size; /* max size of silence pre-fill; when >= boundary, | ||
| 439 | * fill played area with silence immediately */ | ||
| 435 | snd_pcm_uframes_t boundary; /* pointers wrap point */ | 440 | snd_pcm_uframes_t boundary; /* pointers wrap point */ |
| 436 | unsigned int proto; /* protocol version */ | 441 | unsigned int proto; /* protocol version */ |
| 437 | unsigned int tstamp_type; /* timestamp type (req. proto >= 2.0.12) */ | 442 | unsigned int tstamp_type; /* timestamp type (req. proto >= 2.0.12) */ |
| @@ -570,7 +575,8 @@ struct __snd_pcm_mmap_status64 { · 132 unmodified lines | |||
| 570 | struct __snd_pcm_mmap_control64 { | 575 | struct __snd_pcm_mmap_control64 { |
| 571 | __pad_before_uframe __pad1; | 576 | __pad_before_uframe __pad1; |
| 572 | snd_pcm_uframes_t appl_ptr; /* RW: appl ptr (0...boundary-1) */ | 577 | snd_pcm_uframes_t appl_ptr; /* RW: appl ptr (0...boundary-1) */ |
| 573 | __pad_before_uframe __pad2; | 578 | __pad_before_uframe __pad2; // This should be __pad_after_uframe, but binary |
| 579 | // backwards compatibility constraints prevent a fix. | ||
| 574 | 580 | ||
| 575 | __pad_before_uframe __pad3; | 581 | __pad_before_uframe __pad3; |
| 576 | snd_pcm_uframes_t avail_min; /* RW: min available frames for wakeup */ | 582 | snd_pcm_uframes_t avail_min; /* RW: min available frames for wakeup */ |
| @@ -15,9 +15,6 @@ · 14 unmodified lines | |||
| 15 | * ---- FX8010 ---- | 15 | * ---- FX8010 ---- |
| 16 | */ | 16 | */ |
| 17 | 17 | ||
| 18 | #define EMU10K1_CARD_CREATIVE 0x00000000 | ||
| 19 | #define EMU10K1_CARD_EMUAPS 0x00000001 | ||
| 20 | |||
| 21 | #define EMU10K1_FX8010_PCM_COUNT 8 | 18 | #define EMU10K1_FX8010_PCM_COUNT 8 |
| 22 | 19 | ||
| 23 | /* | 20 | /* |
| @@ -46,6 +43,19 @@ · 22 unmodified lines | |||
| 46 | #define iINTERP 0x0e /* R = A + (X * (Y - A) >> 31) ; saturation */ | 43 | #define iINTERP 0x0e /* R = A + (X * (Y - A) >> 31) ; saturation */ |
| 47 | #define iSKIP 0x0f /* R = A (cc_reg), X (count), Y (cc_test) */ | 44 | #define iSKIP 0x0f /* R = A (cc_reg), X (count), Y (cc_test) */ |
| 48 | 45 | ||
| 46 | #define LOWORD_OPX_MASK 0x000ffc00 /* Instruction operand X */ | ||
| 47 | #define LOWORD_OPY_MASK 0x000003ff /* Instruction operand Y */ | ||
| 48 | #define HIWORD_OPCODE_MASK 0x00f00000 /* Instruction opcode */ | ||
| 49 | #define HIWORD_RESULT_MASK 0x000ffc00 /* Instruction result */ | ||
| 50 | #define HIWORD_OPA_MASK 0x000003ff /* Instruction operand A */ | ||
| 51 | |||
| 52 | /* Audigy Soundcards have a different instruction format */ | ||
| 53 | #define A_LOWORD_OPX_MASK 0x007ff000 | ||
| 54 | #define A_LOWORD_OPY_MASK 0x000007ff | ||
| 55 | #define A_HIWORD_OPCODE_MASK 0x0f000000 | ||
| 56 | #define A_HIWORD_RESULT_MASK 0x007ff000 | ||
| 57 | #define A_HIWORD_OPA_MASK 0x000007ff | ||
| 58 | |||
| 49 | /* GPRs */ | 59 | /* GPRs */ |
| 50 | #define FXBUS(x) (0x00 + (x)) /* x = 0x00 - 0x0f */ | 60 | #define FXBUS(x) (0x00 + (x)) /* x = 0x00 - 0x0f */ |
| 51 | #define EXTIN(x) (0x10 + (x)) /* x = 0x00 - 0x0f */ | 61 | #define EXTIN(x) (0x10 + (x)) /* x = 0x00 - 0x0f */ |
| @@ -53,6 +63,16 @@ · 1 unmodified line | |||
| 53 | #define FXBUS2(x) (0x30 + (x)) /* x = 0x00 - 0x0f copies of fx buses for capture -> FXWC high 16 bits */ | 63 | #define FXBUS2(x) (0x30 + (x)) /* x = 0x00 - 0x0f copies of fx buses for capture -> FXWC high 16 bits */ |
| 54 | /* NB: 0x31 and 0x32 are shared with Center/LFE on SB live 5.1 */ | 64 | /* NB: 0x31 and 0x32 are shared with Center/LFE on SB live 5.1 */ |
| 55 | 65 | ||
| 66 | #define A_FXBUS(x) (0x00 + (x)) /* x = 0x00 - 0x3f FX buses */ | ||
| 67 | #define A_EXTIN(x) (0x40 + (x)) /* x = 0x00 - 0x0f physical ins */ | ||
| 68 | #define A_P16VIN(x) (0x50 + (x)) /* x = 0x00 - 0x0f p16v ins (A2 only) "EMU32 inputs" */ | ||
| 69 | #define A_EXTOUT(x) (0x60 + (x)) /* x = 0x00 - 0x1f physical outs -> A_FXWC1 0x79-7f unknown */ | ||
| 70 | #define A_FXBUS2(x) (0x80 + (x)) /* x = 0x00 - 0x1f extra outs used for EFX capture -> A_FXWC2 */ | ||
| 71 | #define A_EMU32OUTH(x) (0xa0 + (x)) /* x = 0x00 - 0x0f "EMU32_OUT_10 - _1F" */ | ||
| 72 | #define A_EMU32OUTL(x) (0xb0 + (x)) /* x = 0x00 - 0x0f "EMU32_OUT_01 - _0F" */ | ||
| 73 | #define A3_EMU32IN(x) (0x160 + (x)) /* x = 0x00 - 0x1f "EMU32_IN_00 - _1F" - Only when .device = 0x0008 */ | ||
| 74 | #define A3_EMU32OUT(x) (0x1E0 + (x)) /* x = 0x00 - 0x1f "EMU32_OUT_00 - _1F" - Only when .device = 0x0008 */ | ||
| 75 | |||
| 56 | #define C_00000000 0x40 | 76 | #define C_00000000 0x40 |
| 57 | #define C_00000001 0x41 | 77 | #define C_00000001 0x41 |
| 58 | #define C_00000002 0x42 | 78 | #define C_00000002 0x42 |
| @@ -81,12 +101,66 @@ · 22 unmodified lines | |||
| 81 | #define GPR_NOISE1 0x59 /* noise source */ | 101 | #define GPR_NOISE1 0x59 /* noise source */ |
| 82 | #define GPR_IRQ 0x5a /* IRQ register */ | 102 | #define GPR_IRQ 0x5a /* IRQ register */ |
| 83 | #define GPR_DBAC 0x5b /* TRAM Delay Base Address Counter */ | 103 | #define GPR_DBAC 0x5b /* TRAM Delay Base Address Counter */ |
| 104 | |||
| 105 | /* Audigy constants */ | ||
| 106 | #define A_C_00000000 0xc0 | ||
| 107 | #define A_C_00000001 0xc1 | ||
| 108 | #define A_C_00000002 0xc2 | ||
| 109 | #define A_C_00000003 0xc3 | ||
| 110 | #define A_C_00000004 0xc4 | ||
| 111 | #define A_C_00000008 0xc5 | ||
| 112 | #define A_C_00000010 0xc6 | ||
| 113 | #define A_C_00000020 0xc7 | ||
| 114 | #define A_C_00000100 0xc8 | ||
| 115 | #define A_C_00010000 0xc9 | ||
| 116 | #define A_C_00000800 0xca | ||
| 117 | #define A_C_10000000 0xcb | ||
| 118 | #define A_C_20000000 0xcc | ||
| 119 | #define A_C_40000000 0xcd | ||
| 120 | #define A_C_80000000 0xce | ||
| 121 | #define A_C_7fffffff 0xcf | ||
| 122 | #define A_C_ffffffff 0xd0 | ||
| 123 | #define A_C_fffffffe 0xd1 | ||
| 124 | #define A_C_c0000000 0xd2 | ||
| 125 | #define A_C_4f1bbcdc 0xd3 | ||
| 126 | #define A_C_5a7ef9db 0xd4 | ||
| 127 | #define A_C_00100000 0xd5 | ||
| 128 | #define A_GPR_ACCU 0xd6 /* ACCUM, accumulator */ | ||
| 129 | #define A_GPR_COND 0xd7 /* CCR, condition register */ | ||
| 130 | #define A_GPR_NOISE0 0xd8 /* noise source */ | ||
| 131 | #define A_GPR_NOISE1 0xd9 /* noise source */ | ||
| 132 | #define A_GPR_IRQ 0xda /* IRQ register */ | ||
| 133 | #define A_GPR_DBAC 0xdb /* TRAM Delay Base Address Counter - internal */ | ||
| 134 | #define A_GPR_DBACE 0xde /* TRAM Delay Base Address Counter - external */ | ||
| 135 | |||
| 136 | /* Each FX general purpose register is 32 bits in length, all bits are used */ | ||
| 137 | #define FXGPREGBASE 0x100 /* FX general purpose registers base */ | ||
| 138 | #define A_FXGPREGBASE 0x400 /* Audigy GPRs, 0x400 to 0x5ff */ | ||
| 139 | |||
| 140 | #define A_TANKMEMCTLREGBASE 0x100 /* Tank memory control registers base - only for Audigy */ | ||
| 141 | #define A_TANKMEMCTLREG_MASK 0x1f /* only 5 bits used - only for Audigy */ | ||
| 142 | |||
| 143 | /* Tank audio data is logarithmically compressed down to 16 bits before writing to TRAM and is */ | ||
| 144 | /* decompressed back to 20 bits on a read. There are a total of 160 locations, the last 32 */ | ||
| 145 | /* locations are for external TRAM. */ | ||
| 146 | #define TANKMEMDATAREGBASE 0x200 /* Tank memory data registers base */ | ||
| 147 | #define TANKMEMDATAREG_MASK 0x000fffff /* 20 bit tank audio data field */ | ||
| 148 | |||
| 149 | /* Combined address field and memory opcode or flag field. 160 locations, last 32 are external */ | ||
| 150 | #define TANKMEMADDRREGBASE 0x300 /* Tank memory address registers base */ | ||
| 151 | #define TANKMEMADDRREG_ADDR_MASK 0x000fffff /* 20 bit tank address field */ | ||
| 152 | #define TANKMEMADDRREG_CLEAR 0x00800000 /* Clear tank memory */ | ||
| 153 | #define TANKMEMADDRREG_ALIGN 0x00400000 /* Align read or write relative to tank access */ | ||
| 154 | #define TANKMEMADDRREG_WRITE 0x00200000 /* Write to tank memory */ | ||
| 155 | #define TANKMEMADDRREG_READ 0x00100000 /* Read from tank memory */ | ||
| 156 | |||
| 84 | #define GPR(x) (FXGPREGBASE + (x)) /* free GPRs: x = 0x00 - 0xff */ | 157 | #define GPR(x) (FXGPREGBASE + (x)) /* free GPRs: x = 0x00 - 0xff */ |
| 85 | #define ITRAM_DATA(x) (TANKMEMDATAREGBASE + 0x00 + (x)) /* x = 0x00 - 0x7f */ | 158 | #define ITRAM_DATA(x) (TANKMEMDATAREGBASE + 0x00 + (x)) /* x = 0x00 - 0x7f */ |
| 86 | #define ETRAM_DATA(x) (TANKMEMDATAREGBASE + 0x80 + (x)) /* x = 0x00 - 0x1f */ | 159 | #define ETRAM_DATA(x) (TANKMEMDATAREGBASE + 0x80 + (x)) /* x = 0x00 - 0x1f */ |
| 87 | #define ITRAM_ADDR(x) (TANKMEMADDRREGBASE + 0x00 + (x)) /* x = 0x00 - 0x7f */ | 160 | #define ITRAM_ADDR(x) (TANKMEMADDRREGBASE + 0x00 + (x)) /* x = 0x00 - 0x7f */ |
| 88 | #define ETRAM_ADDR(x) (TANKMEMADDRREGBASE + 0x80 + (x)) /* x = 0x00 - 0x1f */ | 161 | #define ETRAM_ADDR(x) (TANKMEMADDRREGBASE + 0x80 + (x)) /* x = 0x00 - 0x1f */ |
| 89 | 162 | ||
| 163 | #define A_GPR(x) (A_FXGPREGBASE + (x)) | ||
| 90 | #define A_ITRAM_DATA(x) (TANKMEMDATAREGBASE + 0x00 + (x)) /* x = 0x00 - 0xbf */ | 164 | #define A_ITRAM_DATA(x) (TANKMEMDATAREGBASE + 0x00 + (x)) /* x = 0x00 - 0xbf */ |
| 91 | #define A_ETRAM_DATA(x) (TANKMEMDATAREGBASE + 0xc0 + (x)) /* x = 0x00 - 0x3f */ | 165 | #define A_ETRAM_DATA(x) (TANKMEMDATAREGBASE + 0xc0 + (x)) /* x = 0x00 - 0x3f */ |
| 92 | #define A_ITRAM_ADDR(x) (TANKMEMADDRREGBASE + 0x00 + (x)) /* x = 0x00 - 0xbf */ | 166 | #define A_ITRAM_ADDR(x) (TANKMEMADDRREGBASE + 0x00 + (x)) /* x = 0x00 - 0xbf */ |
| @@ -94,17 +168,6 @@ · 1 unmodified line | |||
| 94 | #define A_ITRAM_CTL(x) (A_TANKMEMCTLREGBASE + 0x00 + (x)) /* x = 0x00 - 0xbf */ | 168 | #define A_ITRAM_CTL(x) (A_TANKMEMCTLREGBASE + 0x00 + (x)) /* x = 0x00 - 0xbf */ |
| 95 | #define A_ETRAM_CTL(x) (A_TANKMEMCTLREGBASE + 0xc0 + (x)) /* x = 0x00 - 0x3f */ | 169 | #define A_ETRAM_CTL(x) (A_TANKMEMCTLREGBASE + 0xc0 + (x)) /* x = 0x00 - 0x3f */ |
| 96 | 170 | ||
| 97 | #define A_FXBUS(x) (0x00 + (x)) /* x = 0x00 - 0x3f FX buses */ | ||
| 98 | #define A_EXTIN(x) (0x40 + (x)) /* x = 0x00 - 0x0f physical ins */ | ||
| 99 | #define A_P16VIN(x) (0x50 + (x)) /* x = 0x00 - 0x0f p16v ins (A2 only) "EMU32 inputs" */ | ||
| 100 | #define A_EXTOUT(x) (0x60 + (x)) /* x = 0x00 - 0x1f physical outs -> A_FXWC1 0x79-7f unknown */ | ||
| 101 | #define A_FXBUS2(x) (0x80 + (x)) /* x = 0x00 - 0x1f extra outs used for EFX capture -> A_FXWC2 */ | ||
| 102 | #define A_EMU32OUTH(x) (0xa0 + (x)) /* x = 0x00 - 0x0f "EMU32_OUT_10 - _1F" - ??? */ | ||
| 103 | #define A_EMU32OUTL(x) (0xb0 + (x)) /* x = 0x00 - 0x0f "EMU32_OUT_1 - _F" - ??? */ | ||
| 104 | #define A3_EMU32IN(x) (0x160 + (x)) /* x = 0x00 - 0x3f "EMU32_IN_00 - _3F" - Only when .device = 0x0008 */ | ||
| 105 | #define A3_EMU32OUT(x) (0x1E0 + (x)) /* x = 0x00 - 0x0f "EMU32_OUT_00 - _3F" - Only when .device = 0x0008 */ | ||
| 106 | #define A_GPR(x) (A_FXGPREGBASE + (x)) | ||
| 107 | |||
| 108 | /* cc_reg constants */ | 171 | /* cc_reg constants */ |
| 109 | #define CC_REG_NORMALIZED C_00000001 | 172 | #define CC_REG_NORMALIZED C_00000001 |
| 110 | #define CC_REG_BORROW C_00000002 | 173 | #define CC_REG_BORROW C_00000002 |
| @@ -113,7 +176,17 @@ · 2 unmodified lines | |||
| 113 | #define CC_REG_SATURATE C_00000010 | 176 | #define CC_REG_SATURATE C_00000010 |
| 114 | #define CC_REG_NONZERO C_00000100 | 177 | #define CC_REG_NONZERO C_00000100 |
| 115 | 178 | ||
| 179 | #define A_CC_REG_NORMALIZED A_C_00000001 | ||
| 180 | #define A_CC_REG_BORROW A_C_00000002 | ||
| 181 | #define A_CC_REG_MINUS A_C_00000004 | ||
| 182 | #define A_CC_REG_ZERO A_C_00000008 | ||
| 183 | #define A_CC_REG_SATURATE A_C_00000010 | ||
| 184 | #define A_CC_REG_NONZERO A_C_00000100 | ||
| 185 | |||
| 116 | /* FX buses */ | 186 | /* FX buses */ |
| 187 | // These are arbitrary mappings; our DSP code simply expects | ||
| 188 | // the config files to route the channels this way. | ||
| 189 | // The numbers are documented in {audigy,sb-live}-mixer.rst. | ||
| 117 | #define FXBUS_PCM_LEFT 0x00 | 190 | #define FXBUS_PCM_LEFT 0x00 |
| 118 | #define FXBUS_PCM_RIGHT 0x01 | 191 | #define FXBUS_PCM_RIGHT 0x01 |
| 119 | #define FXBUS_PCM_LEFT_REAR 0x02 | 192 | #define FXBUS_PCM_LEFT_REAR 0x02 |
| @@ -203,38 +276,7 @@ · 83 unmodified lines | |||
| 203 | #define A_EXTOUT_ADC_CAP_R 0x17 /* right */ | 276 | #define A_EXTOUT_ADC_CAP_R 0x17 /* right */ |
| 204 | #define A_EXTOUT_MIC_CAP 0x18 /* Mic capture buffer */ | 277 | #define A_EXTOUT_MIC_CAP 0x18 /* Mic capture buffer */ |
| 205 | 278 | ||
| 206 | /* Audigy constants */ | 279 | /* Definitions for debug register. Note that these are for emu10k1 ONLY. */ |
| 207 | #define A_C_00000000 0xc0 | ||
| 208 | #define A_C_00000001 0xc1 | ||
| 209 | #define A_C_00000002 0xc2 | ||
| 210 | #define A_C_00000003 0xc3 | ||
| 211 | #define A_C_00000004 0xc4 | ||
| 212 | #define A_C_00000008 0xc5 | ||
| 213 | #define A_C_00000010 0xc6 | ||
| 214 | #define A_C_00000020 0xc7 | ||
| 215 | #define A_C_00000100 0xc8 | ||
| 216 | #define A_C_00010000 0xc9 | ||
| 217 | #define A_C_00000800 0xca | ||
| 218 | #define A_C_10000000 0xcb | ||
| 219 | #define A_C_20000000 0xcc | ||
| 220 | #define A_C_40000000 0xcd | ||
| 221 | #define A_C_80000000 0xce | ||
| 222 | #define A_C_7fffffff 0xcf | ||
| 223 | #define A_C_ffffffff 0xd0 | ||
| 224 | #define A_C_fffffffe 0xd1 | ||
| 225 | #define A_C_c0000000 0xd2 | ||
| 226 | #define A_C_4f1bbcdc 0xd3 | ||
| 227 | #define A_C_5a7ef9db 0xd4 | ||
| 228 | #define A_C_00100000 0xd5 | ||
| 229 | #define A_GPR_ACCU 0xd6 /* ACCUM, accumulator */ | ||
| 230 | #define A_GPR_COND 0xd7 /* CCR, condition register */ | ||
| 231 | #define A_GPR_NOISE0 0xd8 /* noise source */ | ||
| 232 | #define A_GPR_NOISE1 0xd9 /* noise source */ | ||
| 233 | #define A_GPR_IRQ 0xda /* IRQ register */ | ||
| 234 | #define A_GPR_DBAC 0xdb /* TRAM Delay Base Address Counter - internal */ | ||
| 235 | #define A_GPR_DBACE 0xde /* TRAM Delay Base Address Counter - external */ | ||
| 236 | |||
| 237 | /* definitions for debug register */ | ||
| 238 | #define EMU10K1_DBG_ZC 0x80000000 /* zero tram counter */ | 280 | #define EMU10K1_DBG_ZC 0x80000000 /* zero tram counter */ |
| 239 | #define EMU10K1_DBG_SATURATION_OCCURED 0x02000000 /* saturation control */ | 281 | #define EMU10K1_DBG_SATURATION_OCCURED 0x02000000 /* saturation control */ |
| 240 | #define EMU10K1_DBG_SATURATION_ADDR 0x01ff0000 /* saturation address */ | 282 | #define EMU10K1_DBG_SATURATION_ADDR 0x01ff0000 /* saturation address */ |
| @@ -243,14 +285,14 @@ · 2 unmodified lines | |||
| 243 | #define EMU10K1_DBG_CONDITION_CODE 0x00003e00 /* condition code */ | 285 | #define EMU10K1_DBG_CONDITION_CODE 0x00003e00 /* condition code */ |
| 244 | #define EMU10K1_DBG_SINGLE_STEP_ADDR 0x000001ff /* single step address */ | 286 | #define EMU10K1_DBG_SINGLE_STEP_ADDR 0x000001ff /* single step address */ |
| 245 | 287 | ||
| 246 | /* tank memory address line */ | 288 | /* Definitions for emu10k2 debug register. */ |
| 247 | #ifndef __KERNEL__ | 289 | #define A_DBG_ZC 0x40000000 /* zero tram counter */ |
| 248 | #define TANKMEMADDRREG_ADDR_MASK 0x000fffff /* 20 bit tank address field */ | 290 | #define A_DBG_SATURATION_OCCURED 0x20000000 |
| 249 | #define TANKMEMADDRREG_CLEAR 0x00800000 /* Clear tank memory */ | 291 | #define A_DBG_SATURATION_ADDR 0x0ffc0000 |
| 250 | #define TANKMEMADDRREG_ALIGN 0x00400000 /* Align read or write relative to tank access */ | 292 | #define A_DBG_SINGLE_STEP 0x00020000 /* Set to zero to start dsp */ |
| 251 | #define TANKMEMADDRREG_WRITE 0x00200000 /* Write to tank memory */ | 293 | #define A_DBG_STEP 0x00010000 |
| 252 | #define TANKMEMADDRREG_READ 0x00100000 /* Read from tank memory */ | 294 | #define A_DBG_CONDITION_CODE 0x0000f800 |
| 253 | #endif | 295 | #define A_DBG_STEP_ADDR 0x000003ff |
| 254 | 296 | ||
| 255 | struct snd_emu10k1_fx8010_info { | 297 | struct snd_emu10k1_fx8010_info { |
| 256 | unsigned int internal_tram_size; /* in samples */ | 298 | unsigned int internal_tram_size; /* in samples */ |
| @@ -60,5 +60,7 @@ · 59 unmodified lines | |||
| 60 | 60 | ||
| 61 | /* SOF ABI magic number "SOF\0". */ | 61 | /* SOF ABI magic number "SOF\0". */ |
| 62 | #define SOF_ABI_MAGIC 0x00464F53 | 62 | #define SOF_ABI_MAGIC 0x00464F53 |
| 63 | /* SOF IPC4 ABI magic number "SOF4". */ | ||
| 64 | #define SOF_IPC4_ABI_MAGIC 0x34464F53 | ||
| 63 | 65 | ||
| 64 | #endif | 66 | #endif |
| @@ -11,19 +11,30 @@ · 10 unmodified lines | |||
| 11 | 11 | ||
| 12 | #include <linux/types.h> | 12 | #include <linux/types.h> |
| 13 | 13 | ||
| 14 | /* | 14 | /** |
| 15 | * Header for all non IPC ABI data. | 15 | * struct sof_abi_hdr - Header for all non IPC ABI data. |
| 16 | * @magic: Magic number for validation | ||
| 17 | * for IPC3 data: 0x00464F53 ('S', 'O', 'F', '\0') | ||
| 18 | * for IPC4 data: 0x34464F53 ('S', 'O', 'F', '4') | ||
| 19 | * @type: module specific parameter | ||
| 20 | * for IPC3: Component specific type | ||
| 21 | * for IPC4: parameter ID (param_id) of the data | ||
| 22 | * @size: The size in bytes of the data, excluding this struct | ||
| 23 | * @abi: SOF ABI version. The version is valid in scope of the 'magic', IPC3 and | ||
| 24 | * IPC4 ABI version numbers have no relationship. | ||
| 25 | * @reserved: Reserved for future use | ||
| 26 | * @data: Component data - opaque to core | ||
| 16 | * | 27 | * |
| 17 | * Identifies data type, size and ABI. | 28 | * Identifies data type, size and ABI. |
| 18 | * Used by any bespoke component data structures or binary blobs. | 29 | * Used by any bespoke component data structures or binary blobs. |
| 19 | */ | 30 | */ |
| 20 | struct sof_abi_hdr { | 31 | struct sof_abi_hdr { |
| 21 | __u32 magic; /**< 'S', 'O', 'F', '\0' */ | 32 | __u32 magic; |
| 22 | __u32 type; /**< component specific type */ | 33 | __u32 type; |
| 23 | __u32 size; /**< size in bytes of data excl. this struct */ | 34 | __u32 size; |
| 24 | __u32 abi; /**< SOF ABI version */ | 35 | __u32 abi; |
| 25 | __u32 reserved[4]; /**< reserved for future use */ | 36 | __u32 reserved[4]; |
| 26 | __u32 data[]; /**< Component data - opaque to core */ | 37 | __u32 data[]; |
| 27 | } __packed; | 38 | } __packed; |
| 28 | 39 | ||
| 29 | #define SOF_MANIFEST_DATA_TYPE_NHLT 1 | 40 | #define SOF_MANIFEST_DATA_TYPE_NHLT 1 |
| @@ -54,6 +54,7 @@ · 53 unmodified lines | |||
| 54 | #define SOF_TKN_SCHED_DYNAMIC_PIPELINE 206 | 54 | #define SOF_TKN_SCHED_DYNAMIC_PIPELINE 206 |
| 55 | #define SOF_TKN_SCHED_LP_MODE 207 | 55 | #define SOF_TKN_SCHED_LP_MODE 207 |
| 56 | #define SOF_TKN_SCHED_MEM_USAGE 208 | 56 | #define SOF_TKN_SCHED_MEM_USAGE 208 |
| 57 | #define SOF_TKN_SCHED_USE_CHAIN_DMA 209 | ||
| 57 | 58 | ||
| 58 | /* volume */ | 59 | /* volume */ |
| 59 | #define SOF_TKN_VOLUME_RAMP_STEP_TYPE 250 | 60 | #define SOF_TKN_VOLUME_RAMP_STEP_TYPE 250 |
| @@ -88,14 +89,16 @@ · 28 unmodified lines | |||
| 88 | #define SOF_TKN_COMP_CPC 406 | 89 | #define SOF_TKN_COMP_CPC 406 |
| 89 | #define SOF_TKN_COMP_IS_PAGES 409 | 90 | #define SOF_TKN_COMP_IS_PAGES 409 |
| 90 | #define SOF_TKN_COMP_NUM_AUDIO_FORMATS 410 | 91 | #define SOF_TKN_COMP_NUM_AUDIO_FORMATS 410 |
| 91 | #define SOF_TKN_COMP_NUM_SINK_PINS 411 | 92 | #define SOF_TKN_COMP_NUM_INPUT_PINS 411 |
| 92 | #define SOF_TKN_COMP_NUM_SOURCE_PINS 412 | 93 | #define SOF_TKN_COMP_NUM_OUTPUT_PINS 412 |
| 93 | /* | 94 | /* |
| 94 | * The token for sink/source pin binding, it specifies the widget | 95 | * The token for input/output pin binding, it specifies the widget |
| 95 | * name that the sink/source pin is connected from/to. | 96 | * name that the input/output pin is connected from/to. |
| 96 | */ | 97 | */ |
| 97 | #define SOF_TKN_COMP_SINK_PIN_BINDING_WNAME 413 | 98 | #define SOF_TKN_COMP_INPUT_PIN_BINDING_WNAME 413 |
| 98 | #define SOF_TKN_COMP_SRC_PIN_BINDING_WNAME 414 | 99 | #define SOF_TKN_COMP_OUTPUT_PIN_BINDING_WNAME 414 |
| 100 | #define SOF_TKN_COMP_NUM_INPUT_AUDIO_FORMATS 415 | ||
| 101 | #define SOF_TKN_COMP_NUM_OUTPUT_AUDIO_FORMATS 416 | ||
| 99 | 102 | ||
| 100 | 103 | ||
| 101 | /* SSP */ | 104 | /* SSP */ |
| @@ -173,17 +176,18 @@ · 71 unmodified lines | |||
| 173 | /* CAVS AUDIO FORMAT */ | 176 | /* CAVS AUDIO FORMAT */ |
| 174 | #define SOF_TKN_CAVS_AUDIO_FORMAT_IN_RATE 1900 | 177 | #define SOF_TKN_CAVS_AUDIO_FORMAT_IN_RATE 1900 |
| 175 | #define SOF_TKN_CAVS_AUDIO_FORMAT_IN_BIT_DEPTH 1901 | 178 | #define SOF_TKN_CAVS_AUDIO_FORMAT_IN_BIT_DEPTH 1901 |
| 176 | #define SOF_TKN_CAVS_AUDIO_FORMAT_IN_VALID_BIT 1902 | 179 | #define SOF_TKN_CAVS_AUDIO_FORMAT_IN_VALID_BIT_DEPTH 1902 |
| 177 | #define SOF_TKN_CAVS_AUDIO_FORMAT_IN_CHANNELS 1903 | 180 | #define SOF_TKN_CAVS_AUDIO_FORMAT_IN_CHANNELS 1903 |
| 178 | #define SOF_TKN_CAVS_AUDIO_FORMAT_IN_CH_MAP 1904 | 181 | #define SOF_TKN_CAVS_AUDIO_FORMAT_IN_CH_MAP 1904 |
| 179 | #define SOF_TKN_CAVS_AUDIO_FORMAT_IN_CH_CFG 1905 | 182 | #define SOF_TKN_CAVS_AUDIO_FORMAT_IN_CH_CFG 1905 |
| 180 | #define SOF_TKN_CAVS_AUDIO_FORMAT_IN_INTERLEAVING_STYLE 1906 | 183 | #define SOF_TKN_CAVS_AUDIO_FORMAT_IN_INTERLEAVING_STYLE 1906 |
| 181 | #define SOF_TKN_CAVS_AUDIO_FORMAT_IN_FMT_CFG 1907 | 184 | #define SOF_TKN_CAVS_AUDIO_FORMAT_IN_FMT_CFG 1907 |
| 182 | #define SOF_TKN_CAVS_AUDIO_FORMAT_IN_SAMPLE_TYPE 1908 | 185 | #define SOF_TKN_CAVS_AUDIO_FORMAT_IN_SAMPLE_TYPE 1908 |
| 186 | #define SOF_TKN_CAVS_AUDIO_FORMAT_PIN_INDEX 1909 | ||
| 183 | /* intentional token numbering discontinuity, reserved for future use */ | 187 | /* intentional token numbering discontinuity, reserved for future use */ |
| 184 | #define SOF_TKN_CAVS_AUDIO_FORMAT_OUT_RATE 1930 | 188 | #define SOF_TKN_CAVS_AUDIO_FORMAT_OUT_RATE 1930 |
| 185 | #define SOF_TKN_CAVS_AUDIO_FORMAT_OUT_BIT_DEPTH 1931 | 189 | #define SOF_TKN_CAVS_AUDIO_FORMAT_OUT_BIT_DEPTH 1931 |
| 186 | #define SOF_TKN_CAVS_AUDIO_FORMAT_OUT_VALID_BIT 1932 | 190 | #define SOF_TKN_CAVS_AUDIO_FORMAT_OUT_VALID_BIT_DEPTH 1932 |
| 187 | #define SOF_TKN_CAVS_AUDIO_FORMAT_OUT_CHANNELS 1933 | 191 | #define SOF_TKN_CAVS_AUDIO_FORMAT_OUT_CHANNELS 1933 |
| 188 | #define SOF_TKN_CAVS_AUDIO_FORMAT_OUT_CH_MAP 1934 | 192 | #define SOF_TKN_CAVS_AUDIO_FORMAT_OUT_CH_MAP 1934 |
| 189 | #define SOF_TKN_CAVS_AUDIO_FORMAT_OUT_CH_CFG 1935 | 193 | #define SOF_TKN_CAVS_AUDIO_FORMAT_OUT_CH_CFG 1935 |
| @@ -197,6 +201,7 @@ · 7 unmodified lines | |||
| 197 | 201 | ||
| 198 | /* COPIER */ | 202 | /* COPIER */ |
| 199 | #define SOF_TKN_INTEL_COPIER_NODE_TYPE 1980 | 203 | #define SOF_TKN_INTEL_COPIER_NODE_TYPE 1980 |
| 204 | #define SOF_TKN_INTEL_COPIER_DEEP_BUFFER_DMA_MS 1981 | ||
| 200 | 205 | ||
| 201 | /* ACP I2S */ | 206 | /* ACP I2S */ |
| 202 | #define SOF_TKN_AMD_ACPI2S_RATE 1700 | 207 | #define SOF_TKN_AMD_ACPI2S_RATE 1700 |
| @@ -75,19 +75,8 @@ int snd_ac97_reset(struct snd_ac97 *ac97, bool try_warm, unsigned int id, · 74 unmodified lines | |||
| 75 | } | 75 | } |
| 76 | EXPORT_SYMBOL_GPL(snd_ac97_reset); | 76 | EXPORT_SYMBOL_GPL(snd_ac97_reset); |
| 77 | 77 | ||
| 78 | /* | ||
| 79 | * Let drivers decide whether they want to support given codec from their | ||
| 80 | * probe method. Drivers have direct access to the struct snd_ac97 | ||
| 81 | * structure and may decide based on the id field amongst other things. | ||
| 82 | */ | ||
| 83 | static int ac97_bus_match(struct device *dev, struct device_driver *drv) | ||
| 84 | { | ||
| 85 | return 1; | ||
| 86 | } | ||
| 87 | |||
| 88 | struct bus_type ac97_bus_type = { | 78 | struct bus_type ac97_bus_type = { |
| 89 | .name = "ac97", | 79 | .name = "ac97", |
| 90 | .match = ac97_bus_match, | ||
| 91 | }; | 80 | }; |
| 92 | 81 | ||
| 93 | static int __init ac97_bus_init(void) | 82 | static int __init ac97_bus_init(void) |
| @@ -262,7 +262,7 @@ err_dev: · 261 unmodified lines | |||
| 262 | return ret; | 262 | return ret; |
| 263 | } | 263 | } |
| 264 | 264 | ||
| 265 | static int pxa2xx_ac97_remove(struct platform_device *dev) | 265 | static void pxa2xx_ac97_remove(struct platform_device *dev) |
| 266 | { | 266 | { |
| 267 | struct snd_card *card = platform_get_drvdata(dev); | 267 | struct snd_card *card = platform_get_drvdata(dev); |
| 268 | 268 | ||
| @@ -270,13 +270,11 @@ static int pxa2xx_ac97_remove(struct platform_device *dev) · 1 unmodified line | |||
| 270 | snd_card_free(card); | 270 | snd_card_free(card); |
| 271 | pxa2xx_ac97_hw_remove(dev); | 271 | pxa2xx_ac97_hw_remove(dev); |
| 272 | } | 272 | } |
| 273 | |||
| 274 | return 0; | ||
| 275 | } | 273 | } |
| 276 | 274 | ||
| 277 | static struct platform_driver pxa2xx_ac97_driver = { | 275 | static struct platform_driver pxa2xx_ac97_driver = { |
| 278 | .probe = pxa2xx_ac97_probe, | 276 | .probe = pxa2xx_ac97_probe, |
| 279 | .remove = pxa2xx_ac97_remove, | 277 | .remove_new = pxa2xx_ac97_remove, |
| 280 | .driver = { | 278 | .driver = { |
| 281 | .name = "pxa2xx-ac97", | 279 | .name = "pxa2xx-ac97", |
| 282 | #ifdef CONFIG_PM_SLEEP | 280 | #ifdef CONFIG_PM_SLEEP |
| @@ -843,7 +843,7 @@ static SIMPLE_DEV_PM_OPS(atmel_ac97c_pm, atmel_ac97c_suspend, atmel_ac97c_resume · 842 unmodified lines | |||
| 843 | #define ATMEL_AC97C_PM_OPS NULL | 843 | #define ATMEL_AC97C_PM_OPS NULL |
| 844 | #endif | 844 | #endif |
| 845 | 845 | ||
| 846 | static int atmel_ac97c_remove(struct platform_device *pdev) | 846 | static void atmel_ac97c_remove(struct platform_device *pdev) |
| 847 | { | 847 | { |
| 848 | struct snd_card *card = platform_get_drvdata(pdev); | 848 | struct snd_card *card = platform_get_drvdata(pdev); |
| 849 | struct atmel_ac97c *chip = get_chip(card); | 849 | struct atmel_ac97c *chip = get_chip(card); |
| @@ -858,13 +858,11 @@ static int atmel_ac97c_remove(struct platform_device *pdev) · 8 unmodified lines | |||
| 858 | free_irq(chip->irq, chip); | 858 | free_irq(chip->irq, chip); |
| 859 | 859 | ||
| 860 | snd_card_free(card); | 860 | snd_card_free(card); |
| 861 | |||
| 862 | return 0; | ||
| 863 | } | 861 | } |
| 864 | 862 | ||
| 865 | static struct platform_driver atmel_ac97c_driver = { | 863 | static struct platform_driver atmel_ac97c_driver = { |
| 866 | .probe = atmel_ac97c_probe, | 864 | .probe = atmel_ac97c_probe, |
| 867 | .remove = atmel_ac97c_remove, | 865 | .remove_new = atmel_ac97c_remove, |
| 868 | .driver = { | 866 | .driver = { |
| 869 | .name = "atmel_ac97c", | 867 | .name = "atmel_ac97c", |
| 870 | .pm = ATMEL_AC97C_PM_OPS, | 868 | .pm = ATMEL_AC97C_PM_OPS, |
| @@ -42,70 +42,56 @@ static int fill_silence_frames(struct snd_pcm_substream *substream, · 41 unmodified lines | |||
| 42 | * | 42 | * |
| 43 | * when runtime->silence_size >= runtime->boundary - fill processed area with silence immediately | 43 | * when runtime->silence_size >= runtime->boundary - fill processed area with silence immediately |
| 44 | */ | 44 | */ |
| 45 | void snd_pcm_playback_silence(struct snd_pcm_substream *substream, snd_pcm_uframes_t new_hw_ptr) | 45 | void snd_pcm_playback_silence(struct snd_pcm_substream *substream) |
| 46 | { | 46 | { |
| 47 | struct snd_pcm_runtime *runtime = substream->runtime; | 47 | struct snd_pcm_runtime *runtime = substream->runtime; |
| 48 | snd_pcm_uframes_t frames, ofs, transfer; | 48 | snd_pcm_uframes_t appl_ptr = READ_ONCE(runtime->control->appl_ptr); |
| 49 | snd_pcm_sframes_t added, hw_avail, frames; | ||
| 50 | snd_pcm_uframes_t noise_dist, ofs, transfer; | ||
| 49 | int err; | 51 | int err; |
| 50 | 52 | ||
| 53 | added = appl_ptr - runtime->silence_start; | ||
| 54 | if (added) { | ||
| 55 | if (added < 0) | ||
| 56 | added += runtime->boundary; | ||
| 57 | if (added < runtime->silence_filled) | ||
| 58 | runtime->silence_filled -= added; | ||
| 59 | else | ||
| 60 | runtime->silence_filled = 0; | ||
| 61 | runtime->silence_start = appl_ptr; | ||
| 62 | } | ||
| 63 | |||
| 64 | // This will "legitimately" turn negative on underrun, and will be mangled | ||
| 65 | // into a huge number by the boundary crossing handling. The initial state | ||
| 66 | // might also be not quite sane. The code below MUST account for these cases. | ||
| 67 | hw_avail = appl_ptr - runtime->status->hw_ptr; | ||
| 68 | if (hw_avail < 0) | ||
| 69 | hw_avail += runtime->boundary; | ||
| 70 | |||
| 71 | noise_dist = hw_avail + runtime->silence_filled; | ||
| 51 | if (runtime->silence_size < runtime->boundary) { | 72 | if (runtime->silence_size < runtime->boundary) { |
| 52 | snd_pcm_sframes_t noise_dist, n; | ||
| 53 | snd_pcm_uframes_t appl_ptr = READ_ONCE(runtime->control->appl_ptr); | ||
| 54 | if (runtime->silence_start != appl_ptr) { | ||
| 55 | n = appl_ptr - runtime->silence_start; | ||
| 56 | if (n < 0) | ||
| 57 | n += runtime->boundary; | ||
| 58 | if ((snd_pcm_uframes_t)n < runtime->silence_filled) | ||
| 59 | runtime->silence_filled -= n; | ||
| 60 | else | ||
| 61 | runtime->silence_filled = 0; | ||
| 62 | runtime->silence_start = appl_ptr; | ||
| 63 | } | ||
| 64 | if (runtime->silence_filled >= runtime->buffer_size) | ||
| 65 | return; | ||
| 66 | noise_dist = snd_pcm_playback_hw_avail(runtime) + runtime->silence_filled; | ||
| 67 | if (noise_dist >= (snd_pcm_sframes_t) runtime->silence_threshold) | ||
| 68 | return; | ||
| 69 | frames = runtime->silence_threshold - noise_dist; | 73 | frames = runtime->silence_threshold - noise_dist; |
| 74 | if (frames <= 0) | ||
| 75 | return; | ||
| 70 | if (frames > runtime->silence_size) | 76 | if (frames > runtime->silence_size) |
| 71 | frames = runtime->silence_size; | 77 | frames = runtime->silence_size; |
| 72 | } else { | 78 | } else { |
| 73 | if (new_hw_ptr == ULONG_MAX) { /* initialization */ | 79 | frames = runtime->buffer_size - noise_dist; |
| 74 | snd_pcm_sframes_t avail = snd_pcm_playback_hw_avail(runtime); | 80 | if (frames <= 0) |
| 75 | if (avail > runtime->buffer_size) | 81 | return; |
| 76 | avail = runtime->buffer_size; | ||
| 77 | runtime->silence_filled = avail > 0 ? avail : 0; | ||
| 78 | runtime->silence_start = (runtime->status->hw_ptr + | ||
| 79 | runtime->silence_filled) % | ||
| 80 | runtime->boundary; | ||
| 81 | } else { | ||
| 82 | ofs = runtime->status->hw_ptr; | ||
| 83 | frames = new_hw_ptr - ofs; | ||
| 84 | if ((snd_pcm_sframes_t)frames < 0) | ||
| 85 | frames += runtime->boundary; | ||
| 86 | runtime->silence_filled -= frames; | ||
| 87 | if ((snd_pcm_sframes_t)runtime->silence_filled < 0) { | ||
| 88 | runtime->silence_filled = 0; | ||
| 89 | runtime->silence_start = new_hw_ptr; | ||
| 90 | } else { | ||
| 91 | runtime->silence_start = ofs; | ||
| 92 | } | ||
| 93 | } | ||
| 94 | frames = runtime->buffer_size - runtime->silence_filled; | ||
| 95 | } | 82 | } |
| 83 | |||
| 96 | if (snd_BUG_ON(frames > runtime->buffer_size)) | 84 | if (snd_BUG_ON(frames > runtime->buffer_size)) |
| 97 | return; | 85 | return; |
| 98 | if (frames == 0) | 86 | ofs = (runtime->silence_start + runtime->silence_filled) % runtime->buffer_size; |
| 99 | return; | 87 | do { |
| 100 | ofs = runtime->silence_start % runtime->buffer_size; | ||
| 101 | while (frames > 0) { | ||
| 102 | transfer = ofs + frames > runtime->buffer_size ? runtime->buffer_size - ofs : frames; | 88 | transfer = ofs + frames > runtime->buffer_size ? runtime->buffer_size - ofs : frames; |
| 103 | err = fill_silence_frames(substream, ofs, transfer); | 89 | err = fill_silence_frames(substream, ofs, transfer); |
| 104 | snd_BUG_ON(err < 0); | 90 | snd_BUG_ON(err < 0); |
| 105 | runtime->silence_filled += transfer; | 91 | runtime->silence_filled += transfer; |
| 106 | frames -= transfer; | 92 | frames -= transfer; |
| 107 | ofs = 0; | 93 | ofs = 0; |
| 108 | } | 94 | } while (frames > 0); |
| 109 | snd_pcm_dma_buffer_sync(substream, SNDRV_DMA_SYNC_DEVICE); | 95 | snd_pcm_dma_buffer_sync(substream, SNDRV_DMA_SYNC_DEVICE); |
| 110 | } | 96 | } |
| 111 | 97 | ||
| @@ -439,10 +425,6 @@ static int snd_pcm_update_hw_ptr0(struct snd_pcm_substream *substream, · 327 unmodified lines | |||
| 439 | return 0; | 425 | return 0; |
| 440 | } | 426 | } |
| 441 | 427 | ||
| 442 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK && | ||
| 443 | runtime->silence_size > 0) | ||
| 444 | snd_pcm_playback_silence(substream, new_hw_ptr); | ||
| 445 | |||
| 446 | if (in_interrupt) { | 428 | if (in_interrupt) { |
| 447 | delta = new_hw_ptr - runtime->hw_ptr_interrupt; | 429 | delta = new_hw_ptr - runtime->hw_ptr_interrupt; |
| 448 | if (delta < 0) | 430 | if (delta < 0) |
| @@ -460,6 +442,10 @@ static int snd_pcm_update_hw_ptr0(struct snd_pcm_substream *substream, · 11 unmodified lines | |||
| 460 | runtime->hw_ptr_wrap += runtime->boundary; | 442 | runtime->hw_ptr_wrap += runtime->boundary; |
| 461 | } | 443 | } |
| 462 | 444 | ||
| 445 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK && | ||
| 446 | runtime->silence_size > 0) | ||
| 447 | snd_pcm_playback_silence(substream); | ||
| 448 | |||
| 463 | update_audio_tstamp(substream, &curr_tstamp, &audio_tstamp); | 449 | update_audio_tstamp(substream, &curr_tstamp, &audio_tstamp); |
| 464 | 450 | ||
| 465 | return snd_pcm_update_state(substream, runtime); | 451 | return snd_pcm_update_state(substream, runtime); |
| @@ -1878,15 +1864,14 @@ static int wait_for_avail(struct snd_pcm_substream *substream, · 1412 unmodified lines | |||
| 1878 | if (substream->wait_time) { | 1864 | if (substream->wait_time) { |
| 1879 | wait_time = substream->wait_time; | 1865 | wait_time = substream->wait_time; |
| 1880 | } else { | 1866 | } else { |
| 1881 | wait_time = 10; | 1867 | wait_time = 100; |
| 1882 | 1868 | ||
| 1883 | if (runtime->rate) { | 1869 | if (runtime->rate) { |
| 1884 | long t = runtime->period_size * 2 / | 1870 | long t = runtime->buffer_size * 1100 / runtime->rate; |
| 1885 | runtime->rate; | ||
| 1886 | wait_time = max(t, wait_time); | 1871 | wait_time = max(t, wait_time); |
| 1887 | } | 1872 | } |
| 1888 | wait_time = msecs_to_jiffies(wait_time * 1000); | ||
| 1889 | } | 1873 | } |
| 1874 | wait_time = msecs_to_jiffies(wait_time); | ||
| 1890 | } | 1875 | } |
| 1891 | 1876 | ||
| 1892 | for (;;) { | 1877 | for (;;) { |
| @@ -1934,8 +1919,8 @@ static int wait_for_avail(struct snd_pcm_substream *substream, · 41 unmodified lines | |||
| 1934 | } | 1919 | } |
| 1935 | if (!tout) { | 1920 | if (!tout) { |
| 1936 | pcm_dbg(substream->pcm, | 1921 | pcm_dbg(substream->pcm, |
| 1937 | "%s write error (DMA or IRQ trouble?)\n", | 1922 | "%s timeout (DMA or IRQ trouble?)\n", |
| 1938 | is_playback ? "playback" : "capture"); | 1923 | is_playback ? "playback write" : "capture read"); |
| 1939 | err = -EIO; | 1924 | err = -EIO; |
| 1940 | break; | 1925 | break; |
| 1941 | } | 1926 | } |
| @@ -29,8 +29,7 @@ int snd_pcm_update_state(struct snd_pcm_substream *substream, · 28 unmodified lines | |||
| 29 | struct snd_pcm_runtime *runtime); | 29 | struct snd_pcm_runtime *runtime); |
| 30 | int snd_pcm_update_hw_ptr(struct snd_pcm_substream *substream); | 30 | int snd_pcm_update_hw_ptr(struct snd_pcm_substream *substream); |
| 31 | 31 | ||
| 32 | void snd_pcm_playback_silence(struct snd_pcm_substream *substream, | 32 | void snd_pcm_playback_silence(struct snd_pcm_substream *substream); |
| 33 | snd_pcm_uframes_t new_hw_ptr); | ||
| 34 | 33 | ||
| 35 | static inline snd_pcm_uframes_t | 34 | static inline snd_pcm_uframes_t |
| 36 | snd_pcm_avail(struct snd_pcm_substream *substream) | 35 | snd_pcm_avail(struct snd_pcm_substream *substream) |
| @@ -958,7 +958,7 @@ static int snd_pcm_sw_params(struct snd_pcm_substream *substream, · 957 unmodified lines | |||
| 958 | if (snd_pcm_running(substream)) { | 958 | if (snd_pcm_running(substream)) { |
| 959 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK && | 959 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK && |
| 960 | runtime->silence_size > 0) | 960 | runtime->silence_size > 0) |
| 961 | snd_pcm_playback_silence(substream, ULONG_MAX); | 961 | snd_pcm_playback_silence(substream); |
| 962 | err = snd_pcm_update_state(substream, runtime); | 962 | err = snd_pcm_update_state(substream, runtime); |
| 963 | } | 963 | } |
| 964 | snd_pcm_stream_unlock_irq(substream); | 964 | snd_pcm_stream_unlock_irq(substream); |
| @@ -1455,7 +1455,7 @@ static void snd_pcm_post_start(struct snd_pcm_substream *substream, · 490 unmodified lines | |||
| 1455 | __snd_pcm_set_state(runtime, state); | 1455 | __snd_pcm_set_state(runtime, state); |
| 1456 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK && | 1456 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK && |
| 1457 | runtime->silence_size > 0) | 1457 | runtime->silence_size > 0) |
| 1458 | snd_pcm_playback_silence(substream, ULONG_MAX); | 1458 | snd_pcm_playback_silence(substream); |
| 1459 | snd_pcm_timer_notify(substream, SNDRV_TIMER_EVENT_MSTART); | 1459 | snd_pcm_timer_notify(substream, SNDRV_TIMER_EVENT_MSTART); |
| 1460 | } | 1460 | } |
| 1461 | 1461 | ||
| @@ -1916,7 +1916,7 @@ static void snd_pcm_post_reset(struct snd_pcm_substream *substream, · 454 unmodified lines | |||
| 1916 | runtime->control->appl_ptr = runtime->status->hw_ptr; | 1916 | runtime->control->appl_ptr = runtime->status->hw_ptr; |
| 1917 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK && | 1917 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK && |
| 1918 | runtime->silence_size > 0) | 1918 | runtime->silence_size > 0) |
| 1919 | snd_pcm_playback_silence(substream, ULONG_MAX); | 1919 | snd_pcm_playback_silence(substream); |
| 1920 | snd_pcm_stream_unlock_irq(substream); | 1920 | snd_pcm_stream_unlock_irq(substream); |
| 1921 | } | 1921 | } |
| 1922 | 1922 | ||
| @@ -2159,12 +2159,12 @@ static int snd_pcm_drain(struct snd_pcm_substream *substream, · 236 unmodified lines | |||
| 2159 | if (runtime->no_period_wakeup) | 2159 | if (runtime->no_period_wakeup) |
| 2160 | tout = MAX_SCHEDULE_TIMEOUT; | 2160 | tout = MAX_SCHEDULE_TIMEOUT; |
| 2161 | else { | 2161 | else { |
| 2162 | tout = 10; | 2162 | tout = 100; |
| 2163 | if (runtime->rate) { | 2163 | if (runtime->rate) { |
| 2164 | long t = runtime->period_size * 2 / runtime->rate; | 2164 | long t = runtime->buffer_size * 1100 / runtime->rate; |
| 2165 | tout = max(t, tout); | 2165 | tout = max(t, tout); |
| 2166 | } | 2166 | } |
| 2167 | tout = msecs_to_jiffies(tout * 1000); | 2167 | tout = msecs_to_jiffies(tout); |
| 2168 | } | 2168 | } |
| 2169 | tout = schedule_timeout(tout); | 2169 | tout = schedule_timeout(tout); |
| 2170 | 2170 | ||
| @@ -2187,7 +2187,7 @@ static int snd_pcm_drain(struct snd_pcm_substream *substream, · 16 unmodified lines | |||
| 2187 | result = -ESTRPIPE; | 2187 | result = -ESTRPIPE; |
| 2188 | else { | 2188 | else { |
| 2189 | dev_dbg(substream->pcm->card->dev, | 2189 | dev_dbg(substream->pcm->card->dev, |
| 2190 | "playback drain error (DMA or IRQ trouble?)\n"); | 2190 | "playback drain timeout (DMA or IRQ trouble?)\n"); |
| 2191 | snd_pcm_stop(substream, SNDRV_PCM_STATE_SETUP); | 2191 | snd_pcm_stop(substream, SNDRV_PCM_STATE_SETUP); |
| 2192 | result = -EIO; | 2192 | result = -EIO; |
| 2193 | } | 2193 | } |
| @@ -999,19 +999,17 @@ __err: · 998 unmodified lines | |||
| 999 | return err; | 999 | return err; |
| 1000 | } | 1000 | } |
| 1001 | 1001 | ||
| 1002 | static int snd_mts64_remove(struct platform_device *pdev) | 1002 | static void snd_mts64_remove(struct platform_device *pdev) |
| 1003 | { | 1003 | { |
| 1004 | struct snd_card *card = platform_get_drvdata(pdev); | 1004 | struct snd_card *card = platform_get_drvdata(pdev); |
| 1005 | 1005 | ||
| 1006 | if (card) | 1006 | if (card) |
| 1007 | snd_card_free(card); | 1007 | snd_card_free(card); |
| 1008 | |||
| 1009 | return 0; | ||
| 1010 | } | 1008 | } |
| 1011 | 1009 | ||
| 1012 | static struct platform_driver snd_mts64_driver = { | 1010 | static struct platform_driver snd_mts64_driver = { |
| 1013 | .probe = snd_mts64_probe, | 1011 | .probe = snd_mts64_probe, |
| 1014 | .remove = snd_mts64_remove, | 1012 | .remove_new = snd_mts64_remove, |
| 1015 | .driver = { | 1013 | .driver = { |
| 1016 | .name = PLATFORM_DRIVER, | 1014 | .name = PLATFORM_DRIVER, |
| 1017 | } | 1015 | } |
| @@ -182,21 +182,11 @@ static inline void portman_write_command(struct portman *pm, u8 value) · 181 unmodified lines | |||
| 182 | parport_write_control(pm->pardev->port, value); | 182 | parport_write_control(pm->pardev->port, value); |
| 183 | } | 183 | } |
| 184 | 184 | ||
| 185 | static inline u8 portman_read_command(struct portman *pm) | ||
| 186 | { | ||
| 187 | return parport_read_control(pm->pardev->port); | ||
| 188 | } | ||
| 189 | |||
| 190 | static inline u8 portman_read_status(struct portman *pm) | 185 | static inline u8 portman_read_status(struct portman *pm) |
| 191 | { | 186 | { |
| 192 | return parport_read_status(pm->pardev->port); | 187 | return parport_read_status(pm->pardev->port); |
| 193 | } | 188 | } |
| 194 | 189 | ||
| 195 | static inline u8 portman_read_data(struct portman *pm) | ||
| 196 | { | ||
| 197 | return parport_read_data(pm->pardev->port); | ||
| 198 | } | ||
| 199 | |||
| 200 | static inline void portman_write_data(struct portman *pm, u8 value) | 190 | static inline void portman_write_data(struct portman *pm, u8 value) |
| 201 | { | 191 | { |
| 202 | parport_write_data(pm->pardev->port, value); | 192 | parport_write_data(pm->pardev->port, value); |
| @@ -795,20 +785,18 @@ __err: · 592 unmodified lines | |||
| 795 | return err; | 785 | return err; |
| 796 | } | 786 | } |
| 797 | 787 | ||
| 798 | static int snd_portman_remove(struct platform_device *pdev) | 788 | static void snd_portman_remove(struct platform_device *pdev) |
| 799 | { | 789 | { |
| 800 | struct snd_card *card = platform_get_drvdata(pdev); | 790 | struct snd_card *card = platform_get_drvdata(pdev); |
| 801 | 791 | ||
| 802 | if (card) | 792 | if (card) |
| 803 | snd_card_free(card); | 793 | snd_card_free(card); |
| 804 | |||
| 805 | return 0; | ||
| 806 | } | 794 | } |
| 807 | 795 | ||
| 808 | 796 | ||
| 809 | static struct platform_driver snd_portman_driver = { | 797 | static struct platform_driver snd_portman_driver = { |
| 810 | .probe = snd_portman_probe, | 798 | .probe = snd_portman_probe, |
| 811 | .remove = snd_portman_remove, | 799 | .remove_new = snd_portman_remove, |
| 812 | .driver = { | 800 | .driver = { |
| 813 | .name = PLATFORM_DRIVER, | 801 | .name = PLATFORM_DRIVER, |
| 814 | } | 802 | } |
| @@ -877,17 +877,16 @@ static int hal2_probe(struct platform_device *pdev) · 876 unmodified lines | |||
| 877 | return 0; | 877 | return 0; |
| 878 | } | 878 | } |
| 879 | 879 | ||
| 880 | static int hal2_remove(struct platform_device *pdev) | 880 | static void hal2_remove(struct platform_device *pdev) |
| 881 | { | 881 | { |
| 882 | struct snd_card *card = platform_get_drvdata(pdev); | 882 | struct snd_card *card = platform_get_drvdata(pdev); |
| 883 | 883 | ||
| 884 | snd_card_free(card); | 884 | snd_card_free(card); |
| 885 | return 0; | ||
| 886 | } | 885 | } |
| 887 | 886 | ||
| 888 | static struct platform_driver hal2_driver = { | 887 | static struct platform_driver hal2_driver = { |
| 889 | .probe = hal2_probe, | 888 | .probe = hal2_probe, |
| 890 | .remove = hal2_remove, | 889 | .remove_new = hal2_remove, |
| 891 | .driver = { | 890 | .driver = { |
| 892 | .name = "sgihal2", | 891 | .name = "sgihal2", |
| 893 | } | 892 | } |
| @@ -908,17 +908,16 @@ static int snd_sgio2audio_probe(struct platform_device *pdev) · 907 unmodified lines | |||
| 908 | return 0; | 908 | return 0; |
| 909 | } | 909 | } |
| 910 | 910 | ||
| 911 | static int snd_sgio2audio_remove(struct platform_device *pdev) | 911 | static void snd_sgio2audio_remove(struct platform_device *pdev) |
| 912 | { | 912 | { |
| 913 | struct snd_card *card = platform_get_drvdata(pdev); | 913 | struct snd_card *card = platform_get_drvdata(pdev); |
| 914 | 914 | ||
| 915 | snd_card_free(card); | 915 | snd_card_free(card); |
| 916 | return 0; | ||
| 917 | } | 916 | } |
| 918 | 917 | ||
| 919 | static struct platform_driver sgio2audio_driver = { | 918 | static struct platform_driver sgio2audio_driver = { |
| 920 | .probe = snd_sgio2audio_probe, | 919 | .probe = snd_sgio2audio_probe, |
| 921 | .remove = snd_sgio2audio_remove, | 920 | .remove_new = snd_sgio2audio_remove, |
| 922 | .driver = { | 921 | .driver = { |
| 923 | .name = "sgio2audio", | 922 | .name = "sgio2audio", |
| 924 | } | 923 | } |
| @@ -461,7 +461,7 @@ config SND_INDIGODJX · 460 unmodified lines | |||
| 461 | will be called snd-indigodjx | 461 | will be called snd-indigodjx |
| 462 | 462 | ||
| 463 | config SND_EMU10K1 | 463 | config SND_EMU10K1 |
| 464 | tristate "Emu10k1 (SB Live!, Audigy, E-mu APS)" | 464 | tristate "Emu10k1 (SB Live!, Audigy, E-MU APS/0404/1010/1212/1616/1820)" |
| 465 | select FW_LOADER | 465 | select FW_LOADER |
| 466 | select SND_HWDEP | 466 | select SND_HWDEP |
| 467 | select SND_RAWMIDI | 467 | select SND_RAWMIDI |
| @@ -471,7 +471,7 @@ config SND_EMU10K1 · 3 unmodified lines | |||
| 471 | depends on ZONE_DMA | 471 | depends on ZONE_DMA |
| 472 | help | 472 | help |
| 473 | Say Y to include support for Sound Blaster PCI 512, Live!, | 473 | Say Y to include support for Sound Blaster PCI 512, Live!, |
| 474 | Audigy and E-mu APS (partially supported) soundcards. | 474 | Audigy and E-MU APS/0404/1010/1212/1616/1820 soundcards. |
| 475 | 475 | ||
| 476 | The confusing multitude of mixer controls is documented in | 476 | The confusing multitude of mixer controls is documented in |
| 477 | <file:Documentation/sound/cards/sb-live-mixer.rst> and | 477 | <file:Documentation/sound/cards/sb-live-mixer.rst> and |
| @@ -1253,7 +1253,6 @@ static u16 hpi6000_dsp_block_read32(struct hpi_adapter_obj *pao, · 1252 unmodified lines | |||
| 1253 | int local_count = count; | 1253 | int local_count = count; |
| 1254 | int xfer_size; | 1254 | int xfer_size; |
| 1255 | u32 *pdata = dest; | 1255 | u32 *pdata = dest; |
| 1256 | u32 loop_count = 0; | ||
| 1257 | 1256 | ||
| 1258 | while (local_count) { | 1257 | while (local_count) { |
| 1259 | if (local_count > c6711_burst_size) | 1258 | if (local_count > c6711_burst_size) |
| @@ -1273,7 +1272,6 @@ static u16 hpi6000_dsp_block_read32(struct hpi_adapter_obj *pao, · 13 unmodified lines | |||
| 1273 | pdata += xfer_size; | 1272 | pdata += xfer_size; |
| 1274 | local_hpi_address += sizeof(u32) * xfer_size; | 1273 | local_hpi_address += sizeof(u32) * xfer_size; |
| 1275 | local_count -= xfer_size; | 1274 | local_count -= xfer_size; |
| 1276 | loop_count++; | ||
| 1277 | } | 1275 | } |
| 1278 | 1276 | ||
| 1279 | if (time_out) | 1277 | if (time_out) |
| @@ -68,17 +68,6 @@ static const struct pci_device_id snd_emu10k1_ids[] = { · 67 unmodified lines | |||
| 68 | { 0, } | 68 | { 0, } |
| 69 | }; | 69 | }; |
| 70 | 70 | ||
| 71 | /* | ||
| 72 | * Audigy 2 Value notes: | ||
| 73 | * A_IOCFG Input (GPIO) | ||
| 74 | * 0x400 = Front analog jack plugged in. (Green socket) | ||
| 75 | * 0x1000 = Read analog jack plugged in. (Black socket) | ||
| 76 | * 0x2000 = Center/LFE analog jack plugged in. (Orange socket) | ||
| 77 | * A_IOCFG Output (GPIO) | ||
| 78 | * 0x60 = Sound out of front Left. | ||
| 79 | * Win sets it to 0xXX61 | ||
| 80 | */ | ||
| 81 | |||
| 82 | MODULE_DEVICE_TABLE(pci, snd_emu10k1_ids); | 71 | MODULE_DEVICE_TABLE(pci, snd_emu10k1_ids); |
| 83 | 72 | ||
| 84 | static int snd_card_emu10k1_probe(struct pci_dev *pci, | 73 | static int snd_card_emu10k1_probe(struct pci_dev *pci, |
| @@ -531,8 +531,5 @@ set_fm2frq2(struct snd_emu10k1 *hw, struct snd_emux_voice *vp) · 530 unmodified lines | |||
| 531 | static void | 531 | static void |
| 532 | set_filterQ(struct snd_emu10k1 *hw, struct snd_emux_voice *vp) | 532 | set_filterQ(struct snd_emu10k1 *hw, struct snd_emux_voice *vp) |
| 533 | { | 533 | { |
| 534 | unsigned int val; | 534 | snd_emu10k1_ptr_write(hw, CCCA_RESONANCE, vp->ch, vp->reg.parm.filterQ); |
| 535 | val = snd_emu10k1_ptr_read(hw, CCCA, vp->ch) & ~CCCA_RESONANCE; | ||
| 536 | val |= (vp->reg.parm.filterQ << 28); | ||
| 537 | snd_emu10k1_ptr_write(hw, CCCA, vp->ch, val); | ||
| 538 | } | 535 | } |
| @@ -140,7 +140,7 @@ static const unsigned int i2c_adc_init[][2] = { · 139 unmodified lines | |||
| 140 | { 0x15, ADC_MUX_2 }, /* ADC Mixer control. Mic for A2ZS Notebook */ | 140 | { 0x15, ADC_MUX_2 }, /* ADC Mixer control. Mic for A2ZS Notebook */ |
| 141 | }; | 141 | }; |
| 142 | 142 | ||
| 143 | static int snd_emu10k1_init(struct snd_emu10k1 *emu, int enable_ir, int resume) | 143 | static int snd_emu10k1_init(struct snd_emu10k1 *emu, int enable_ir) |
| 144 | { | 144 | { |
| 145 | unsigned int silent_page; | 145 | unsigned int silent_page; |
| 146 | int ch; | 146 | int ch; |
| @@ -162,6 +162,8 @@ static int snd_emu10k1_init(struct snd_emu10k1 *emu, int enable_ir, int resume) · 15 unmodified lines | |||
| 162 | outl(0, emu->port + INTE); | 162 | outl(0, emu->port + INTE); |
| 163 | snd_emu10k1_ptr_write(emu, CLIEL, 0, 0); | 163 | snd_emu10k1_ptr_write(emu, CLIEL, 0, 0); |
| 164 | snd_emu10k1_ptr_write(emu, CLIEH, 0, 0); | 164 | snd_emu10k1_ptr_write(emu, CLIEH, 0, 0); |
| 165 | |||
| 166 | /* disable stop on loop end */ | ||
| 165 | snd_emu10k1_ptr_write(emu, SOLEL, 0, 0); | 167 | snd_emu10k1_ptr_write(emu, SOLEL, 0, 0); |
| 166 | snd_emu10k1_ptr_write(emu, SOLEH, 0, 0); | 168 | snd_emu10k1_ptr_write(emu, SOLEH, 0, 0); |
| 167 | 169 | ||
| @@ -181,13 +183,11 @@ static int snd_emu10k1_init(struct snd_emu10k1 *emu, int enable_ir, int resume) · 13 unmodified lines | |||
| 181 | snd_emu10k1_ptr_write(emu, SPCS1, 0, emu->spdif_bits[1]); | 183 | snd_emu10k1_ptr_write(emu, SPCS1, 0, emu->spdif_bits[1]); |
| 182 | snd_emu10k1_ptr_write(emu, SPCS2, 0, emu->spdif_bits[2]); | 184 | snd_emu10k1_ptr_write(emu, SPCS2, 0, emu->spdif_bits[2]); |
| 183 | 185 | ||
| 184 | if (emu->card_capabilities->ca0151_chip) { /* audigy2 */ | 186 | if (emu->card_capabilities->emu_model) { |
| 187 | } else if (emu->card_capabilities->ca0151_chip) { /* audigy2 */ | ||
| 185 | /* Hacks for Alice3 to work independent of haP16V driver */ | 188 | /* Hacks for Alice3 to work independent of haP16V driver */ |
| 186 | /* Setup SRCMulti_I2S SamplingRate */ | 189 | /* Setup SRCMulti_I2S SamplingRate */ |
| 187 | tmp = snd_emu10k1_ptr_read(emu, A_SPDIF_SAMPLERATE, 0); | 190 | snd_emu10k1_ptr_write(emu, A_I2S_CAPTURE_RATE, 0, A_I2S_CAPTURE_96000); |
| 188 | tmp &= 0xfffff1ff; | ||
| 189 | tmp |= (0x2<<9); | ||
| 190 | snd_emu10k1_ptr_write(emu, A_SPDIF_SAMPLERATE, 0, tmp); | ||
| 191 | 191 | ||
| 192 | /* Setup SRCSel (Enable Spdif,I2S SRCMulti) */ | 192 | /* Setup SRCSel (Enable Spdif,I2S SRCMulti) */ |
| 193 | snd_emu10k1_ptr20_write(emu, SRCSel, 0, 0x14); | 193 | snd_emu10k1_ptr20_write(emu, SRCSel, 0, 0x14); |
| @@ -199,32 +199,26 @@ static int snd_emu10k1_init(struct snd_emu10k1 *emu, int enable_ir, int resume) · 5 unmodified lines | |||
| 199 | outl(0x0201, emu->port + HCFG2); | 199 | outl(0x0201, emu->port + HCFG2); |
| 200 | /* Set playback routing. */ | 200 | /* Set playback routing. */ |
| 201 | snd_emu10k1_ptr20_write(emu, CAPTURE_P16V_SOURCE, 0, 0x78e4); | 201 | snd_emu10k1_ptr20_write(emu, CAPTURE_P16V_SOURCE, 0, 0x78e4); |
| 202 | } | 202 | } else if (emu->card_capabilities->ca0108_chip) { /* audigy2 Value */ |
| 203 | if (emu->card_capabilities->ca0108_chip) { /* audigy2 Value */ | ||
| 204 | /* Hacks for Alice3 to work independent of haP16V driver */ | 203 | /* Hacks for Alice3 to work independent of haP16V driver */ |
| 205 | dev_info(emu->card->dev, "Audigy2 value: Special config.\n"); | 204 | dev_info(emu->card->dev, "Audigy2 value: Special config.\n"); |
| 206 | /* Setup SRCMulti_I2S SamplingRate */ | 205 | /* Setup SRCMulti_I2S SamplingRate */ |
| 207 | tmp = snd_emu10k1_ptr_read(emu, A_SPDIF_SAMPLERATE, 0); | 206 | snd_emu10k1_ptr_write(emu, A_I2S_CAPTURE_RATE, 0, A_I2S_CAPTURE_96000); |
| 208 | tmp &= 0xfffff1ff; | ||
| 209 | tmp |= (0x2<<9); | ||
| 210 | snd_emu10k1_ptr_write(emu, A_SPDIF_SAMPLERATE, 0, tmp); | ||
| 211 | 207 | ||
| 212 | /* Setup SRCSel (Enable Spdif,I2S SRCMulti) */ | 208 | /* Setup SRCSel (Enable Spdif,I2S SRCMulti) */ |
| 213 | outl(0x600000, emu->port + 0x20); | 209 | snd_emu10k1_ptr20_write(emu, P17V_SRCSel, 0, 0x14); |
| 214 | outl(0x14, emu->port + 0x24); | ||
| 215 | 210 | ||
| 216 | /* Setup SRCMulti Input Audio Enable */ | 211 | /* Setup SRCMulti Input Audio Enable */ |
| 217 | outl(0x7b0000, emu->port + 0x20); | 212 | snd_emu10k1_ptr20_write(emu, P17V_MIXER_I2S_ENABLE, 0, 0xFF000000); |
| 218 | outl(0xFF000000, emu->port + 0x24); | ||
| 219 | 213 | ||
| 220 | /* Setup SPDIF Out Audio Enable */ | 214 | /* Setup SPDIF Out Audio Enable */ |
| 221 | /* The Audigy 2 Value has a separate SPDIF out, | 215 | /* The Audigy 2 Value has a separate SPDIF out, |
| 222 | * so no need for a mixer switch | 216 | * so no need for a mixer switch |
| 223 | */ | 217 | */ |
| 224 | outl(0x7a0000, emu->port + 0x20); | 218 | snd_emu10k1_ptr20_write(emu, P17V_MIXER_SPDIF_ENABLE, 0, 0xFF000000); |
| 225 | outl(0xFF000000, emu->port + 0x24); | 219 | |
| 226 | tmp = inl(emu->port + A_IOCFG) & ~0x8; /* Clear bit 3 */ | 220 | tmp = inw(emu->port + A_IOCFG) & ~0x8; /* Clear bit 3 */ |
| 227 | outl(tmp, emu->port + A_IOCFG); | 221 | outw(tmp, emu->port + A_IOCFG); |
| 228 | } | 222 | } |
| 229 | if (emu->card_capabilities->spi_dac) { /* Audigy 2 ZS Notebook with DAC Wolfson WM8768/WM8568 */ | 223 | if (emu->card_capabilities->spi_dac) { /* Audigy 2 ZS Notebook with DAC Wolfson WM8768/WM8568 */ |
| 230 | int size, n; | 224 | int size, n; |
| @@ -244,15 +238,15 @@ static int snd_emu10k1_init(struct snd_emu10k1 *emu, int enable_ir, int resume) · 13 unmodified lines | |||
| 244 | * GPIO6: Unknown | 238 | * GPIO6: Unknown |
| 245 | * GPIO7: Unknown | 239 | * GPIO7: Unknown |
| 246 | */ | 240 | */ |
| 247 | outl(0x76, emu->port + A_IOCFG); /* Windows uses 0x3f76 */ | 241 | outw(0x76, emu->port + A_IOCFG); /* Windows uses 0x3f76 */ |
| 248 | } | 242 | } |
| 249 | if (emu->card_capabilities->i2c_adc) { /* Audigy 2 ZS Notebook with ADC Wolfson WM8775 */ | 243 | if (emu->card_capabilities->i2c_adc) { /* Audigy 2 ZS Notebook with ADC Wolfson WM8775 */ |
| 250 | int size, n; | 244 | int size, n; |
| 251 | 245 | ||
| 252 | snd_emu10k1_ptr20_write(emu, P17V_I2S_SRC_SEL, 0, 0x2020205f); | 246 | snd_emu10k1_ptr20_write(emu, P17V_I2S_SRC_SEL, 0, 0x2020205f); |
| 253 | tmp = inl(emu->port + A_IOCFG); | 247 | tmp = inw(emu->port + A_IOCFG); |
| 254 | outl(tmp | 0x4, emu->port + A_IOCFG); /* Set bit 2 for mic input */ | 248 | outw(tmp | 0x4, emu->port + A_IOCFG); /* Set bit 2 for mic input */ |
| 255 | tmp = inl(emu->port + A_IOCFG); | 249 | tmp = inw(emu->port + A_IOCFG); |
| 256 | size = ARRAY_SIZE(i2c_adc_init); | 250 | size = ARRAY_SIZE(i2c_adc_init); |
| 257 | for (n = 0; n < size; n++) | 251 | for (n = 0; n < size; n++) |
| 258 | snd_emu10k1_i2c_write(emu, i2c_adc_init[n][0], i2c_adc_init[n][1]); | 252 | snd_emu10k1_i2c_write(emu, i2c_adc_init[n][0], i2c_adc_init[n][1]); |
| @@ -308,12 +302,12 @@ static int snd_emu10k1_init(struct snd_emu10k1 *emu, int enable_ir, int resume) · 49 unmodified lines | |||
| 308 | } else if (emu->card_capabilities->i2c_adc) { | 302 | } else if (emu->card_capabilities->i2c_adc) { |
| 309 | ; /* Disable A_IOCFG for Audigy 2 ZS Notebook */ | 303 | ; /* Disable A_IOCFG for Audigy 2 ZS Notebook */ |
| 310 | } else if (emu->audigy) { | 304 | } else if (emu->audigy) { |
| 311 | unsigned int reg = inl(emu->port + A_IOCFG); | 305 | u16 reg = inw(emu->port + A_IOCFG); |
| 312 | outl(reg | A_IOCFG_GPOUT2, emu->port + A_IOCFG); | 306 | outw(reg | A_IOCFG_GPOUT2, emu->port + A_IOCFG); |
| 313 | udelay(500); | 307 | udelay(500); |
| 314 | outl(reg | A_IOCFG_GPOUT1 | A_IOCFG_GPOUT2, emu->port + A_IOCFG); | 308 | outw(reg | A_IOCFG_GPOUT1 | A_IOCFG_GPOUT2, emu->port + A_IOCFG); |
| 315 | udelay(100); | 309 | udelay(100); |
| 316 | outl(reg, emu->port + A_IOCFG); | 310 | outw(reg, emu->port + A_IOCFG); |
| 317 | } else { | 311 | } else { |
| 318 | unsigned int reg = inl(emu->port + HCFG); | 312 | unsigned int reg = inl(emu->port + HCFG); |
| 319 | outl(reg | HCFG_GPOUT2, emu->port + HCFG); | 313 | outl(reg | HCFG_GPOUT2, emu->port + HCFG); |
| @@ -329,8 +323,8 @@ static int snd_emu10k1_init(struct snd_emu10k1 *emu, int enable_ir, int resume) · 9 unmodified lines | |||
| 329 | } else if (emu->card_capabilities->i2c_adc) { | 323 | } else if (emu->card_capabilities->i2c_adc) { |
| 330 | ; /* Disable A_IOCFG for Audigy 2 ZS Notebook */ | 324 | ; /* Disable A_IOCFG for Audigy 2 ZS Notebook */ |
| 331 | } else if (emu->audigy) { /* enable analog output */ | 325 | } else if (emu->audigy) { /* enable analog output */ |
| 332 | unsigned int reg = inl(emu->port + A_IOCFG); | 326 | u16 reg = inw(emu->port + A_IOCFG); |
| 333 | outl(reg | A_IOCFG_GPOUT0, emu->port + A_IOCFG); | 327 | outw(reg | A_IOCFG_GPOUT0, emu->port + A_IOCFG); |
| 334 | } | 328 | } |
| 335 | 329 | ||
| 336 | if (emu->address_mode == 0) { | 330 | if (emu->address_mode == 0) { |
| @@ -354,19 +348,19 @@ static void snd_emu10k1_audio_enable(struct snd_emu10k1 *emu) · 17 unmodified lines | |||
| 354 | } else if (emu->card_capabilities->i2c_adc) { | 348 | } else if (emu->card_capabilities->i2c_adc) { |
| 355 | ; /* Disable A_IOCFG for Audigy 2 ZS Notebook */ | 349 | ; /* Disable A_IOCFG for Audigy 2 ZS Notebook */ |
| 356 | } else if (emu->audigy) { | 350 | } else if (emu->audigy) { |
| 357 | outl(inl(emu->port + A_IOCFG) & ~0x44, emu->port + A_IOCFG); | 351 | outw(inw(emu->port + A_IOCFG) & ~0x44, emu->port + A_IOCFG); |
| 358 | 352 | ||
| 359 | if (emu->card_capabilities->ca0151_chip) { /* audigy2 */ | 353 | if (emu->card_capabilities->ca0151_chip) { /* audigy2 */ |
| 360 | /* Unmute Analog now. Set GPO6 to 1 for Apollo. | 354 | /* Unmute Analog now. Set GPO6 to 1 for Apollo. |
| 361 | * This has to be done after init ALice3 I2SOut beyond 48KHz. | 355 | * This has to be done after init ALice3 I2SOut beyond 48KHz. |
| 362 | * So, sequence is important. */ | 356 | * So, sequence is important. */ |
| 363 | outl(inl(emu->port + A_IOCFG) | 0x0040, emu->port + A_IOCFG); | 357 | outw(inw(emu->port + A_IOCFG) | 0x0040, emu->port + A_IOCFG); |
| 364 | } else if (emu->card_capabilities->ca0108_chip) { /* audigy2 value */ | 358 | } else if (emu->card_capabilities->ca0108_chip) { /* audigy2 value */ |
| 365 | /* Unmute Analog now. */ | 359 | /* Unmute Analog now. */ |
| 366 | outl(inl(emu->port + A_IOCFG) | 0x0060, emu->port + A_IOCFG); | 360 | outw(inw(emu->port + A_IOCFG) | 0x0060, emu->port + A_IOCFG); |
| 367 | } else { | 361 | } else { |
| 368 | /* Disable routing from AC97 line out to Front speakers */ | 362 | /* Disable routing from AC97 line out to Front speakers */ |
| 369 | outl(inl(emu->port + A_IOCFG) | 0x0080, emu->port + A_IOCFG); | 363 | outw(inw(emu->port + A_IOCFG) | 0x0080, emu->port + A_IOCFG); |
| 370 | } | 364 | } |
| 371 | } | 365 | } |
| 372 | 366 | ||
| @@ -651,26 +645,27 @@ static int snd_emu1010_load_firmware_entry(struct snd_emu10k1 *emu, · 278 unmodified lines | |||
| 651 | const struct firmware *fw_entry) | 645 | const struct firmware *fw_entry) |
| 652 | { | 646 | { |
| 653 | int n, i; | 647 | int n, i; |
| 654 | int reg; | 648 | u16 reg; |
| 655 | int value; | 649 | u8 value; |
| 656 | __always_unused unsigned int write_post; | 650 | __always_unused u16 write_post; |
| 657 | unsigned long flags; | 651 | unsigned long flags; |
| 658 | 652 | ||
| 659 | if (!fw_entry) | 653 | if (!fw_entry) |
| 660 | return -EIO; | 654 | return -EIO; |
| 661 | 655 | ||
| 662 | /* The FPGA is a Xilinx Spartan IIE XC2S50E */ | 656 | /* The FPGA is a Xilinx Spartan IIE XC2S50E */ |
| 657 | /* On E-MU 0404b it is a Xilinx Spartan III XC3S50 */ | ||
| 663 | /* GPIO7 -> FPGA PGMN | 658 | /* GPIO7 -> FPGA PGMN |
| 664 | * GPIO6 -> FPGA CCLK | 659 | * GPIO6 -> FPGA CCLK |
| 665 | * GPIO5 -> FPGA DIN | 660 | * GPIO5 -> FPGA DIN |
| 666 | * FPGA CONFIG OFF -> FPGA PGMN | 661 | * FPGA CONFIG OFF -> FPGA PGMN |
| 667 | */ | 662 | */ |
| 668 | spin_lock_irqsave(&emu->emu_lock, flags); | 663 | spin_lock_irqsave(&emu->emu_lock, flags); |
| 669 | outl(0x00, emu->port + A_IOCFG); /* Set PGMN low for 1uS. */ | 664 | outw(0x00, emu->port + A_GPIO); /* Set PGMN low for 100uS. */ |
| 670 | write_post = inl(emu->port + A_IOCFG); | 665 | write_post = inw(emu->port + A_GPIO); |
| 671 | udelay(100); | 666 | udelay(100); |
| 672 | outl(0x80, emu->port + A_IOCFG); /* Leave bit 7 set during netlist setup. */ | 667 | outw(0x80, emu->port + A_GPIO); /* Leave bit 7 set during netlist setup. */ |
| 673 | write_post = inl(emu->port + A_IOCFG); | 668 | write_post = inw(emu->port + A_GPIO); |
| 674 | udelay(100); /* Allow FPGA memory to clean */ | 669 | udelay(100); /* Allow FPGA memory to clean */ |
| 675 | for (n = 0; n < fw_entry->size; n++) { | 670 | for (n = 0; n < fw_entry->size; n++) { |
| 676 | value = fw_entry->data[n]; | 671 | value = fw_entry->data[n]; |
| @@ -679,15 +674,15 @@ static int snd_emu1010_load_firmware_entry(struct snd_emu10k1 *emu, · 2 unmodified lines | |||
| 679 | if (value & 0x1) | 674 | if (value & 0x1) |
| 680 | reg = reg | 0x20; | 675 | reg = reg | 0x20; |
| 681 | value = value >> 1; | 676 | value = value >> 1; |
| 682 | outl(reg, emu->port + A_IOCFG); | 677 | outw(reg, emu->port + A_GPIO); |
| 683 | write_post = inl(emu->port + A_IOCFG); | 678 | write_post = inw(emu->port + A_GPIO); |
| 684 | outl(reg | 0x40, emu->port + A_IOCFG); | 679 | outw(reg | 0x40, emu->port + A_GPIO); |
| 685 | write_post = inl(emu->port + A_IOCFG); | 680 | write_post = inw(emu->port + A_GPIO); |
| 686 | } | 681 | } |
| 687 | } | 682 | } |
| 688 | /* After programming, set GPIO bit 4 high again. */ | 683 | /* After programming, set GPIO bit 4 high again. */ |
| 689 | outl(0x10, emu->port + A_IOCFG); | 684 | outw(0x10, emu->port + A_GPIO); |
| 690 | write_post = inl(emu->port + A_IOCFG); | 685 | write_post = inw(emu->port + A_GPIO); |
| 691 | spin_unlock_irqrestore(&emu->emu_lock, flags); | 686 | spin_unlock_irqrestore(&emu->emu_lock, flags); |
| 692 | 687 | ||
| 693 | return 0; | 688 | return 0; |
| @@ -782,7 +777,7 @@ static void emu1010_firmware_work(struct work_struct *work) · 88 unmodified lines | |||
| 782 | } else if (!reg && emu->emu1010.last_reg) { | 777 | } else if (!reg && emu->emu1010.last_reg) { |
| 783 | /* Audio Dock removed */ | 778 | /* Audio Dock removed */ |
| 784 | dev_info(emu->card->dev, "emu1010: Audio Dock detached\n"); | 779 | dev_info(emu->card->dev, "emu1010: Audio Dock detached\n"); |
| 785 | /* Unmute all */ | 780 | /* The hardware auto-mutes all, so we unmute again */ |
| 786 | snd_emu1010_fpga_write(emu, EMU_HANA_UNMUTE, EMU_UNMUTE); | 781 | snd_emu1010_fpga_write(emu, EMU_HANA_UNMUTE, EMU_UNMUTE); |
| 787 | } | 782 | } |
| 788 | 783 | ||
| @@ -794,29 +789,6 @@ static void emu1010_firmware_work(struct work_struct *work) · 5 unmodified lines | |||
| 794 | } | 789 | } |
| 795 | 790 | ||
| 796 | /* | 791 | /* |
| 797 | * EMU-1010 - details found out from this driver, official MS Win drivers, | ||
| 798 | * testing the card: | ||
| 799 | * | ||
| 800 | * Audigy2 (aka Alice2): | ||
| 801 | * --------------------- | ||
| 802 | * * communication over PCI | ||
| 803 | * * conversion of 32-bit data coming over EMU32 links from HANA FPGA | ||
| 804 | * to 2 x 16-bit, using internal DSP instructions | ||
| 805 | * * slave mode, clock supplied by HANA | ||
| 806 | * * linked to HANA using: | ||
| 807 | * 32 x 32-bit serial EMU32 output channels | ||
| 808 | * 16 x EMU32 input channels | ||
| 809 | * (?) x I2S I/O channels (?) | ||
| 810 | * | ||
| 811 | * FPGA (aka HANA): | ||
| 812 | * --------------- | ||
| 813 | * * provides all (?) physical inputs and outputs of the card | ||
| 814 | * (ADC, DAC, SPDIF I/O, ADAT I/O, etc.) | ||
| 815 | * * provides clock signal for the card and Alice2 | ||
| 816 | * * two crystals - for 44.1kHz and 48kHz multiples | ||
| 817 | * * provides internal routing of signal sources to signal destinations | ||
| 818 | * * inputs/outputs to Alice2 - see above | ||
| 819 | * | ||
| 820 | * Current status of the driver: | 792 | * Current status of the driver: |
| 821 | * ---------------------------- | 793 | * ---------------------------- |
| 822 | * * only 44.1/48kHz supported (the MS Win driver supports up to 192 kHz) | 794 | * * only 44.1/48kHz supported (the MS Win driver supports up to 192 kHz) |
| @@ -831,24 +803,10 @@ static int snd_emu10k1_emu1010_init(struct snd_emu10k1 *emu) · 8 unmodified lines | |||
| 831 | int err; | 803 | int err; |
| 832 | 804 | ||
| 833 | dev_info(emu->card->dev, "emu1010: Special config.\n"); | 805 | dev_info(emu->card->dev, "emu1010: Special config.\n"); |
| 834 | /* AC97 2.1, Any 16Meg of 4Gig address, Auto-Mute, EMU32 Slave, | 806 | |
| 835 | * Lock Sound Memory Cache, Lock Tank Memory Cache, | 807 | /* Mute, and disable audio and lock cache, just in case. |
| 836 | * Mute all codecs. | 808 | * Proper init follows in snd_emu10k1_init(). */ |
| 837 | */ | 809 | outl(HCFG_LOCKSOUNDCACHE | HCFG_LOCKTANKCACHE_MASK, emu->port + HCFG); |
| 838 | outl(0x0005a00c, emu->port + HCFG); | ||
| 839 | /* AC97 2.1, Any 16Meg of 4Gig address, Auto-Mute, EMU32 Slave, | ||
| 840 | * Lock Tank Memory Cache, | ||
| 841 | * Mute all codecs. | ||
| 842 | */ | ||
| 843 | outl(0x0005a004, emu->port + HCFG); | ||
| 844 | /* AC97 2.1, Any 16Meg of 4Gig address, Auto-Mute, EMU32 Slave, | ||
| 845 | * Mute all codecs. | ||
| 846 | */ | ||
| 847 | outl(0x0005a000, emu->port + HCFG); | ||
| 848 | /* AC97 2.1, Any 16Meg of 4Gig address, Auto-Mute, EMU32 Slave, | ||
| 849 | * Mute all codecs. | ||
| 850 | */ | ||
| 851 | outl(0x0005a000, emu->port + HCFG); | ||
| 852 | 810 | ||
| 853 | /* Disable 48Volt power to Audio Dock */ | 811 | /* Disable 48Volt power to Audio Dock */ |
| 854 | snd_emu1010_fpga_write(emu, EMU_HANA_DOCK_PWR, 0); | 812 | snd_emu1010_fpga_write(emu, EMU_HANA_DOCK_PWR, 0); |
| @@ -897,34 +855,20 @@ static int snd_emu10k1_emu1010_init(struct snd_emu10k1 *emu) · 42 unmodified lines | |||
| 897 | 855 | ||
| 898 | snd_emu1010_fpga_read(emu, EMU_HANA_OPTION_CARDS, ®); | 856 | snd_emu1010_fpga_read(emu, EMU_HANA_OPTION_CARDS, ®); |
| 899 | dev_info(emu->card->dev, "emu1010: Card options = 0x%x\n", reg); | 857 | dev_info(emu->card->dev, "emu1010: Card options = 0x%x\n", reg); |
| 900 | snd_emu1010_fpga_read(emu, EMU_HANA_OPTION_CARDS, ®); | ||
| 901 | dev_info(emu->card->dev, "emu1010: Card options = 0x%x\n", reg); | ||
| 902 | snd_emu1010_fpga_read(emu, EMU_HANA_OPTICAL_TYPE, &tmp); | ||
| 903 | /* Optical -> ADAT I/O */ | 858 | /* Optical -> ADAT I/O */ |
| 904 | /* 0 : SPDIF | ||
| 905 | * 1 : ADAT | ||
| 906 | */ | ||
| 907 | emu->emu1010.optical_in = 1; /* IN_ADAT */ | 859 | emu->emu1010.optical_in = 1; /* IN_ADAT */ |
| 908 | emu->emu1010.optical_out = 1; /* IN_ADAT */ | 860 | emu->emu1010.optical_out = 1; /* OUT_ADAT */ |
| 909 | tmp = 0; | ||
| 910 | tmp = (emu->emu1010.optical_in ? EMU_HANA_OPTICAL_IN_ADAT : 0) | | 861 | tmp = (emu->emu1010.optical_in ? EMU_HANA_OPTICAL_IN_ADAT : 0) | |
| 911 | (emu->emu1010.optical_out ? EMU_HANA_OPTICAL_OUT_ADAT : 0); | 862 | (emu->emu1010.optical_out ? EMU_HANA_OPTICAL_OUT_ADAT : 0); |
| 912 | snd_emu1010_fpga_write(emu, EMU_HANA_OPTICAL_TYPE, tmp); | 863 | snd_emu1010_fpga_write(emu, EMU_HANA_OPTICAL_TYPE, tmp); |
| 913 | snd_emu1010_fpga_read(emu, EMU_HANA_ADC_PADS, &tmp); | ||
| 914 | /* Set no attenuation on Audio Dock pads. */ | 864 | /* Set no attenuation on Audio Dock pads. */ |
| 915 | snd_emu1010_fpga_write(emu, EMU_HANA_ADC_PADS, 0x00); | 865 | snd_emu1010_fpga_write(emu, EMU_HANA_ADC_PADS, 0x00); |
| 916 | emu->emu1010.adc_pads = 0x00; | 866 | emu->emu1010.adc_pads = 0x00; |
| 917 | snd_emu1010_fpga_read(emu, EMU_HANA_DOCK_MISC, &tmp); | ||
| 918 | /* Unmute Audio dock DACs, Headphone source DAC-4. */ | 867 | /* Unmute Audio dock DACs, Headphone source DAC-4. */ |
| 919 | snd_emu1010_fpga_write(emu, EMU_HANA_DOCK_MISC, 0x30); | 868 | snd_emu1010_fpga_write(emu, EMU_HANA_DOCK_MISC, 0x30); |
| 920 | snd_emu1010_fpga_write(emu, EMU_HANA_DOCK_LEDS_2, 0x12); | ||
| 921 | snd_emu1010_fpga_read(emu, EMU_HANA_DAC_PADS, &tmp); | ||
| 922 | /* DAC PADs. */ | 869 | /* DAC PADs. */ |
| 923 | snd_emu1010_fpga_write(emu, EMU_HANA_DAC_PADS, 0x0f); | 870 | snd_emu1010_fpga_write(emu, EMU_HANA_DAC_PADS, 0x0f); |
| 924 | emu->emu1010.dac_pads = 0x0f; | 871 | emu->emu1010.dac_pads = 0x0f; |
| 925 | snd_emu1010_fpga_read(emu, EMU_HANA_DOCK_MISC, &tmp); | ||
| 926 | snd_emu1010_fpga_write(emu, EMU_HANA_DOCK_MISC, 0x30); | ||
| 927 | snd_emu1010_fpga_read(emu, EMU_HANA_SPDIF_MODE, &tmp); | ||
| 928 | /* SPDIF Format. Set Consumer mode, 24bit, copy enable */ | 872 | /* SPDIF Format. Set Consumer mode, 24bit, copy enable */ |
| 929 | snd_emu1010_fpga_write(emu, EMU_HANA_SPDIF_MODE, 0x10); | 873 | snd_emu1010_fpga_write(emu, EMU_HANA_SPDIF_MODE, 0x10); |
| 930 | /* MIDI routing */ | 874 | /* MIDI routing */ |
| @@ -936,8 +880,7 @@ static int snd_emu10k1_emu1010_init(struct snd_emu10k1 *emu) · 5 unmodified lines | |||
| 936 | /* IRQ Enable: All off */ | 880 | /* IRQ Enable: All off */ |
| 937 | snd_emu1010_fpga_write(emu, EMU_HANA_IRQ_ENABLE, 0x00); | 881 | snd_emu1010_fpga_write(emu, EMU_HANA_IRQ_ENABLE, 0x00); |
| 938 | 882 | ||
| 939 | snd_emu1010_fpga_read(emu, EMU_HANA_OPTION_CARDS, ®); | 883 | emu->emu1010.internal_clock = 1; /* 48000 */ |
| 940 | dev_info(emu->card->dev, "emu1010: Card options3 = 0x%x\n", reg); | ||
| 941 | /* Default WCLK set to 48kHz. */ | 884 | /* Default WCLK set to 48kHz. */ |
| 942 | snd_emu1010_fpga_write(emu, EMU_HANA_DEFCLOCK, 0x00); | 885 | snd_emu1010_fpga_write(emu, EMU_HANA_DEFCLOCK, 0x00); |
| 943 | /* Word Clock source, Internal 48kHz x1 */ | 886 | /* Word Clock source, Internal 48kHz x1 */ |
| @@ -1073,29 +1016,6 @@ static int snd_emu10k1_emu1010_init(struct snd_emu10k1 *emu) · 129 unmodified lines | |||
| 1073 | EMU_DST_ALICE_I2S2_RIGHT, EMU_SRC_DOCK_ADC3_RIGHT1); | 1016 | EMU_DST_ALICE_I2S2_RIGHT, EMU_SRC_DOCK_ADC3_RIGHT1); |
| 1074 | snd_emu1010_fpga_write(emu, EMU_HANA_UNMUTE, 0x01); /* Unmute all */ | 1017 | snd_emu1010_fpga_write(emu, EMU_HANA_UNMUTE, 0x01); /* Unmute all */ |
| 1075 | 1018 | ||
| 1076 | snd_emu1010_fpga_read(emu, EMU_HANA_OPTION_CARDS, &tmp); | ||
| 1077 | |||
| 1078 | /* AC97 1.03, Any 32Meg of 2Gig address, Auto-Mute, EMU32 Slave, | ||
| 1079 | * Lock Sound Memory Cache, Lock Tank Memory Cache, | ||
| 1080 | * Mute all codecs. | ||
| 1081 | */ | ||
| 1082 | outl(0x0000a000, emu->port + HCFG); | ||
| 1083 | /* AC97 1.03, Any 32Meg of 2Gig address, Auto-Mute, EMU32 Slave, | ||
| 1084 | * Lock Sound Memory Cache, Lock Tank Memory Cache, | ||
| 1085 | * Un-Mute all codecs. | ||
| 1086 | */ | ||
| 1087 | outl(0x0000a001, emu->port + HCFG); | ||
| 1088 | |||
| 1089 | /* Initial boot complete. Now patches */ | ||
| 1090 | |||
| 1091 | snd_emu1010_fpga_read(emu, EMU_HANA_OPTION_CARDS, &tmp); | ||
| 1092 | snd_emu1010_fpga_write(emu, EMU_HANA_MIDI_IN, 0x19); /* MIDI Route */ | ||
| 1093 | snd_emu1010_fpga_write(emu, EMU_HANA_MIDI_OUT, 0x0c); /* Unknown */ | ||
| 1094 | snd_emu1010_fpga_write(emu, EMU_HANA_MIDI_IN, 0x19); /* MIDI Route */ | ||
| 1095 | snd_emu1010_fpga_write(emu, EMU_HANA_MIDI_OUT, 0x0c); /* Unknown */ | ||
| 1096 | snd_emu1010_fpga_read(emu, EMU_HANA_SPDIF_MODE, &tmp); | ||
| 1097 | snd_emu1010_fpga_write(emu, EMU_HANA_SPDIF_MODE, 0x10); /* SPDIF Format spdif (or 0x11 for aes/ebu) */ | ||
| 1098 | |||
| 1099 | #if 0 | 1019 | #if 0 |
| 1100 | snd_emu1010_fpga_link_dst_src_write(emu, | 1020 | snd_emu1010_fpga_link_dst_src_write(emu, |
| 1101 | EMU_DST_HAMOA_DAC_LEFT1, EMU_SRC_ALICE_EMU32B + 2); /* ALICE2 bus 0xa2 */ | 1021 | EMU_DST_HAMOA_DAC_LEFT1, EMU_SRC_ALICE_EMU32B + 2); /* ALICE2 bus 0xa2 */ |
| @@ -1215,21 +1135,6 @@ static int snd_emu10k1_emu1010_init(struct snd_emu10k1 *emu) · 113 unmodified lines | |||
| 1215 | EMU_DST_HANA_ADAT + 7, EMU_SRC_ALICE_EMU32A + 7); | 1135 | EMU_DST_HANA_ADAT + 7, EMU_SRC_ALICE_EMU32A + 7); |
| 1216 | emu->emu1010.output_source[23] = 28; | 1136 | emu->emu1010.output_source[23] = 28; |
| 1217 | } | 1137 | } |
| 1218 | /* TEMP: Select SPDIF in/out */ | ||
| 1219 | /* snd_emu1010_fpga_write(emu, EMU_HANA_OPTICAL_TYPE, 0x0); */ /* Output spdif */ | ||
| 1220 | |||
| 1221 | /* TEMP: Select 48kHz SPDIF out */ | ||
| 1222 | snd_emu1010_fpga_write(emu, EMU_HANA_UNMUTE, 0x0); /* Mute all */ | ||
| 1223 | snd_emu1010_fpga_write(emu, EMU_HANA_DEFCLOCK, 0x0); /* Default fallback clock 48kHz */ | ||
| 1224 | /* Word Clock source, Internal 48kHz x1 */ | ||
| 1225 | snd_emu1010_fpga_write(emu, EMU_HANA_WCLOCK, EMU_HANA_WCLOCK_INT_48K); | ||
| 1226 | /* snd_emu1010_fpga_write(emu, EMU_HANA_WCLOCK, EMU_HANA_WCLOCK_INT_48K | EMU_HANA_WCLOCK_4X); */ | ||
| 1227 | emu->emu1010.internal_clock = 1; /* 48000 */ | ||
| 1228 | snd_emu1010_fpga_write(emu, EMU_HANA_DOCK_LEDS_2, 0x12); /* Set LEDs on Audio Dock */ | ||
| 1229 | snd_emu1010_fpga_write(emu, EMU_HANA_UNMUTE, 0x1); /* Unmute all */ | ||
| 1230 | /* snd_emu1010_fpga_write(emu, 0x7, 0x0); */ /* Mute all */ | ||
| 1231 | /* snd_emu1010_fpga_write(emu, 0x7, 0x1); */ /* Unmute all */ | ||
| 1232 | /* snd_emu1010_fpga_write(emu, 0xe, 0x12); */ /* Set LEDs on Audio Dock */ | ||
| 1233 | 1138 | ||
| 1234 | return 0; | 1139 | return 0; |
| 1235 | } | 1140 | } |
| @@ -1343,6 +1248,15 @@ static const struct snd_emu_chip_details emu_chip_details[] = { · 107 unmodified lines | |||
| 1343 | * AC97: STAC9750 | 1248 | * AC97: STAC9750 |
| 1344 | * CA0151: None | 1249 | * CA0151: None |
| 1345 | */ | 1250 | */ |
| 1251 | /* | ||
| 1252 | * A_IOCFG Input (GPIO) | ||
| 1253 | * 0x400 = Front analog jack plugged in. (Green socket) | ||
| 1254 | * 0x1000 = Rear analog jack plugged in. (Black socket) | ||
| 1255 | * 0x2000 = Center/LFE analog jack plugged in. (Orange socket) | ||
| 1256 | * A_IOCFG Output (GPIO) | ||
| 1257 | * 0x60 = Sound out of front Left. | ||
| 1258 | * Win sets it to 0xXX61 | ||
| 1259 | */ | ||
| 1346 | {.vendor = 0x1102, .device = 0x0008, .subsystem = 0x10011102, | 1260 | {.vendor = 0x1102, .device = 0x0008, .subsystem = 0x10011102, |
| 1347 | .driver = "Audigy2", .name = "SB Audigy 2 Value [SB0400]", | 1261 | .driver = "Audigy2", .name = "SB Audigy 2 Value [SB0400]", |
| 1348 | .id = "Audigy2", | 1262 | .id = "Audigy2", |
| @@ -1391,6 +1305,9 @@ static const struct snd_emu_chip_details emu_chip_details[] = { · 42 unmodified lines | |||
| 1391 | .spi_dac = 1, | 1305 | .spi_dac = 1, |
| 1392 | .i2c_adc = 1, | 1306 | .i2c_adc = 1, |
| 1393 | .spk71 = 1} , | 1307 | .spk71 = 1} , |
| 1308 | /* This is MAEM8950 "Mana" */ | ||
| 1309 | /* Attach MicroDock[M] to make it an E-MU 1616[m]. */ | ||
| 1310 | /* Does NOT support sync daughter card (obviously). */ | ||
| 1394 | /* Tested by James@superbug.co.uk 4th Nov 2007. */ | 1311 | /* Tested by James@superbug.co.uk 4th Nov 2007. */ |
| 1395 | {.vendor = 0x1102, .device = 0x0008, .subsystem = 0x42011102, | 1312 | {.vendor = 0x1102, .device = 0x0008, .subsystem = 0x42011102, |
| 1396 | .driver = "Audigy2", .name = "E-mu 1010 Notebook [MAEM8950]", | 1313 | .driver = "Audigy2", .name = "E-mu 1010 Notebook [MAEM8950]", |
| @@ -1401,7 +1318,10 @@ static const struct snd_emu_chip_details emu_chip_details[] = { · 4 unmodified lines | |||
| 1401 | .spk71 = 1 , | 1318 | .spk71 = 1 , |
| 1402 | .emu_model = EMU_MODEL_EMU1616}, | 1319 | .emu_model = EMU_MODEL_EMU1616}, |
| 1403 | /* Tested by James@superbug.co.uk 4th Nov 2007. */ | 1320 | /* Tested by James@superbug.co.uk 4th Nov 2007. */ |
| 1404 | /* This is MAEM8960, 0202 is MAEM 8980 */ | 1321 | /* This is MAEM8960 "Hana3", 0202 is MAEM8980 */ |
| 1322 | /* Attach 0202 daughter card to make it an E-MU 1212m, OR a | ||
| 1323 | * MicroDock[M] to make it an E-MU 1616[m]. */ | ||
| 1324 | /* Does NOT support sync daughter card. */ | ||
| 1405 | {.vendor = 0x1102, .device = 0x0008, .subsystem = 0x40041102, | 1325 | {.vendor = 0x1102, .device = 0x0008, .subsystem = 0x40041102, |
| 1406 | .driver = "Audigy2", .name = "E-mu 1010b PCI [MAEM8960]", | 1326 | .driver = "Audigy2", .name = "E-mu 1010b PCI [MAEM8960]", |
| 1407 | .id = "EMU1010", | 1327 | .id = "EMU1010", |
| @@ -1411,6 +1331,11 @@ static const struct snd_emu_chip_details emu_chip_details[] = { · 3 unmodified lines | |||
| 1411 | .emu_model = EMU_MODEL_EMU1010B}, /* EMU 1010 new revision */ | 1331 | .emu_model = EMU_MODEL_EMU1010B}, /* EMU 1010 new revision */ |
| 1412 | /* Tested by Maxim Kachur <mcdebugger@duganet.ru> 17th Oct 2012. */ | 1332 | /* Tested by Maxim Kachur <mcdebugger@duganet.ru> 17th Oct 2012. */ |
| 1413 | /* This is MAEM8986, 0202 is MAEM8980 */ | 1333 | /* This is MAEM8986, 0202 is MAEM8980 */ |
| 1334 | /* Attach 0202 daughter card to make it an E-MU 1212m, OR a | ||
| 1335 | * MicroDockM to make it an E-MU 1616m. The non-m | ||
| 1336 | * version was never sold with this card, but should | ||
| 1337 | * still work. */ | ||
| 1338 | /* Does NOT support sync daughter card. */ | ||
| 1414 | {.vendor = 0x1102, .device = 0x0008, .subsystem = 0x40071102, | 1339 | {.vendor = 0x1102, .device = 0x0008, .subsystem = 0x40071102, |
| 1415 | .driver = "Audigy2", .name = "E-mu 1010 PCIe [MAEM8986]", | 1340 | .driver = "Audigy2", .name = "E-mu 1010 PCIe [MAEM8986]", |
| 1416 | .id = "EMU1010", | 1341 | .id = "EMU1010", |
| @@ -1419,7 +1344,10 @@ static const struct snd_emu_chip_details emu_chip_details[] = { · 2 unmodified lines | |||
| 1419 | .spk71 = 1, | 1344 | .spk71 = 1, |
| 1420 | .emu_model = EMU_MODEL_EMU1010B}, /* EMU 1010 PCIe */ | 1345 | .emu_model = EMU_MODEL_EMU1010B}, /* EMU 1010 PCIe */ |
| 1421 | /* Tested by James@superbug.co.uk 8th July 2005. */ | 1346 | /* Tested by James@superbug.co.uk 8th July 2005. */ |
| 1422 | /* This is MAEM8810, 0202 is MAEM8820 */ | 1347 | /* This is MAEM8810 "Hana", 0202 is MAEM8820 "Hamoa" */ |
| 1348 | /* Attach 0202 daughter card to make it an E-MU 1212m, OR an | ||
| 1349 | * AudioDock[M] to make it an E-MU 1820[m]. */ | ||
| 1350 | /* Supports sync daughter card. */ | ||
| 1423 | {.vendor = 0x1102, .device = 0x0004, .subsystem = 0x40011102, | 1351 | {.vendor = 0x1102, .device = 0x0004, .subsystem = 0x40011102, |
| 1424 | .driver = "Audigy2", .name = "E-mu 1010 [MAEM8810]", | 1352 | .driver = "Audigy2", .name = "E-mu 1010 [MAEM8810]", |
| 1425 | .id = "EMU1010", | 1353 | .id = "EMU1010", |
| @@ -1427,7 +1355,9 @@ static const struct snd_emu_chip_details emu_chip_details[] = { · 1 unmodified line | |||
| 1427 | .ca0102_chip = 1, | 1355 | .ca0102_chip = 1, |
| 1428 | .spk71 = 1, | 1356 | .spk71 = 1, |
| 1429 | .emu_model = EMU_MODEL_EMU1010}, /* EMU 1010 old revision */ | 1357 | .emu_model = EMU_MODEL_EMU1010}, /* EMU 1010 old revision */ |
| 1430 | /* EMU0404b */ | 1358 | /* This is MAEM8852 "HanaLiteLite" */ |
| 1359 | /* Supports sync daughter card. */ | ||
| 1360 | /* Tested by oswald.buddenhagen@gmx.de Mar 2023. */ | ||
| 1431 | {.vendor = 0x1102, .device = 0x0008, .subsystem = 0x40021102, | 1361 | {.vendor = 0x1102, .device = 0x0008, .subsystem = 0x40021102, |
| 1432 | .driver = "Audigy2", .name = "E-mu 0404b PCI [MAEM8852]", | 1362 | .driver = "Audigy2", .name = "E-mu 0404b PCI [MAEM8852]", |
| 1433 | .id = "EMU0404", | 1363 | .id = "EMU0404", |
| @@ -1435,6 +1365,8 @@ static const struct snd_emu_chip_details emu_chip_details[] = { · 1 unmodified line | |||
| 1435 | .ca0108_chip = 1, | 1365 | .ca0108_chip = 1, |
| 1436 | .spk71 = 1, | 1366 | .spk71 = 1, |
| 1437 | .emu_model = EMU_MODEL_EMU0404}, /* EMU 0404 new revision */ | 1367 | .emu_model = EMU_MODEL_EMU0404}, /* EMU 0404 new revision */ |
| 1368 | /* This is MAEM8850 "HanaLite" */ | ||
| 1369 | /* Supports sync daughter card. */ | ||
| 1438 | /* Tested by James@superbug.co.uk 20-3-2007. */ | 1370 | /* Tested by James@superbug.co.uk 20-3-2007. */ |
| 1439 | {.vendor = 0x1102, .device = 0x0004, .subsystem = 0x40021102, | 1371 | {.vendor = 0x1102, .device = 0x0004, .subsystem = 0x40021102, |
| 1440 | .driver = "Audigy2", .name = "E-mu 0404 [MAEM8850]", | 1372 | .driver = "Audigy2", .name = "E-mu 0404 [MAEM8850]", |
| @@ -1444,6 +1376,7 @@ static const struct snd_emu_chip_details emu_chip_details[] = { · 3 unmodified lines | |||
| 1444 | .spk71 = 1, | 1376 | .spk71 = 1, |
| 1445 | .emu_model = EMU_MODEL_EMU0404}, /* EMU 0404 */ | 1377 | .emu_model = EMU_MODEL_EMU0404}, /* EMU 0404 */ |
| 1446 | /* EMU0404 PCIe */ | 1378 | /* EMU0404 PCIe */ |
| 1379 | /* Does NOT support sync daughter card. */ | ||
| 1447 | {.vendor = 0x1102, .device = 0x0008, .subsystem = 0x40051102, | 1380 | {.vendor = 0x1102, .device = 0x0008, .subsystem = 0x40051102, |
| 1448 | .driver = "Audigy2", .name = "E-mu 0404 PCIe [MAEM8984]", | 1381 | .driver = "Audigy2", .name = "E-mu 0404 PCIe [MAEM8984]", |
| 1449 | .id = "EMU0404", | 1382 | .id = "EMU0404", |
| @@ -1451,7 +1384,6 @@ static const struct snd_emu_chip_details emu_chip_details[] = { · 1 unmodified line | |||
| 1451 | .ca0108_chip = 1, | 1384 | .ca0108_chip = 1, |
| 1452 | .spk71 = 1, | 1385 | .spk71 = 1, |
| 1453 | .emu_model = EMU_MODEL_EMU0404}, /* EMU 0404 PCIe ver_03 */ | 1386 | .emu_model = EMU_MODEL_EMU0404}, /* EMU 0404 PCIe ver_03 */ |
| 1454 | /* Note that all E-mu cards require kernel 2.6 or newer. */ | ||
| 1455 | {.vendor = 0x1102, .device = 0x0008, | 1387 | {.vendor = 0x1102, .device = 0x0008, |
| 1456 | .driver = "Audigy2", .name = "SB Audigy 2 Value [Unknown]", | 1388 | .driver = "Audigy2", .name = "SB Audigy 2 Value [Unknown]", |
| 1457 | .id = "Audigy2", | 1389 | .id = "Audigy2", |
| @@ -1532,6 +1464,8 @@ static const struct snd_emu_chip_details emu_chip_details[] = { · 74 unmodified lines | |||
| 1532 | .spdif_bug = 1, | 1464 | .spdif_bug = 1, |
| 1533 | .adc_1361t = 1, /* 24 bit capture instead of 16bit */ | 1465 | .adc_1361t = 1, /* 24 bit capture instead of 16bit */ |
| 1534 | .ac97_chip = 1} , | 1466 | .ac97_chip = 1} , |
| 1467 | /* Audigy 2 Platinum EX */ | ||
| 1468 | /* Win driver sets A_IOCFG output to 0x1c00 */ | ||
| 1535 | {.vendor = 0x1102, .device = 0x0004, .subsystem = 0x10051102, | 1469 | {.vendor = 0x1102, .device = 0x0004, .subsystem = 0x10051102, |
| 1536 | .driver = "Audigy2", .name = "Audigy 2 Platinum EX [SB0280]", | 1470 | .driver = "Audigy2", .name = "Audigy 2 Platinum EX [SB0280]", |
| 1537 | .id = "Audigy2", | 1471 | .id = "Audigy2", |
| @@ -1552,6 +1486,8 @@ static const struct snd_emu_chip_details emu_chip_details[] = { · 14 unmodified lines | |||
| 1552 | .spdif_bug = 1, | 1486 | .spdif_bug = 1, |
| 1553 | .invert_shared_spdif = 1, /* digital/analog switch swapped */ | 1487 | .invert_shared_spdif = 1, /* digital/analog switch swapped */ |
| 1554 | .ac97_chip = 1} , | 1488 | .ac97_chip = 1} , |
| 1489 | /* Audigy 2 Platinum */ | ||
| 1490 | /* Win driver sets A_IOCFG output to 0xa00 */ | ||
| 1555 | {.vendor = 0x1102, .device = 0x0004, .subsystem = 0x10021102, | 1491 | {.vendor = 0x1102, .device = 0x0004, .subsystem = 0x10021102, |
| 1556 | .driver = "Audigy2", .name = "SB Audigy 2 Platinum [SB0240P]", | 1492 | .driver = "Audigy2", .name = "SB Audigy 2 Platinum [SB0240P]", |
| 1557 | .id = "Audigy2", | 1493 | .id = "Audigy2", |
| @@ -1657,6 +1593,9 @@ static const struct snd_emu_chip_details emu_chip_details[] = { · 99 unmodified lines | |||
| 1657 | .emu10k1_chip = 1, | 1593 | .emu10k1_chip = 1, |
| 1658 | .ac97_chip = 1, | 1594 | .ac97_chip = 1, |
| 1659 | .sblive51 = 1} , | 1595 | .sblive51 = 1} , |
| 1596 | /* SB Live! Platinum */ | ||
| 1597 | /* Win driver sets A_IOCFG output to 0 */ | ||
| 1598 | /* Tested by Jonathan Dowland <jon@dow.land> Apr 2023. */ | ||
| 1660 | {.vendor = 0x1102, .device = 0x0002, .subsystem = 0x80401102, | 1599 | {.vendor = 0x1102, .device = 0x0002, .subsystem = 0x80401102, |
| 1661 | .driver = "EMU10K1", .name = "SB Live! Platinum [CT4760P]", | 1600 | .driver = "EMU10K1", .name = "SB Live! Platinum [CT4760P]", |
| 1662 | .id = "Live", | 1601 | .id = "Live", |
| @@ -1901,11 +1840,12 @@ int snd_emu10k1_create(struct snd_card *card, · 238 unmodified lines | |||
| 1901 | 1840 | ||
| 1902 | pci_set_master(pci); | 1841 | pci_set_master(pci); |
| 1903 | 1842 | ||
| 1904 | emu->fx8010.fxbus_mask = 0x303f; | 1843 | // The masks are not used for Audigy. |
| 1844 | // FIXME: these should come from the card_capabilites table. | ||
| 1905 | if (extin_mask == 0) | 1845 | if (extin_mask == 0) |
| 1906 | extin_mask = 0x3fcf; | 1846 | extin_mask = 0x3fcf; // EXTIN_* |
| 1907 | if (extout_mask == 0) | 1847 | if (extout_mask == 0) |
| 1908 | extout_mask = 0x7fff; | 1848 | extout_mask = 0x7fff; // EXTOUT_* |
| 1909 | emu->fx8010.extin_mask = extin_mask; | 1849 | emu->fx8010.extin_mask = extin_mask; |
| 1910 | emu->fx8010.extout_mask = extout_mask; | 1850 | emu->fx8010.extout_mask = extout_mask; |
| 1911 | emu->enable_ir = enable_ir; | 1851 | emu->enable_ir = enable_ir; |
| @@ -1970,12 +1910,10 @@ int snd_emu10k1_create(struct snd_card *card, · 58 unmodified lines | |||
| 1970 | pgtbl[idx] = cpu_to_le32(silent_page | idx); | 1910 | pgtbl[idx] = cpu_to_le32(silent_page | idx); |
| 1971 | 1911 | ||
| 1972 | /* set up voice indices */ | 1912 | /* set up voice indices */ |
| 1973 | for (idx = 0; idx < NUM_G; idx++) { | 1913 | for (idx = 0; idx < NUM_G; idx++) |
| 1974 | emu->voices[idx].emu = emu; | ||
| 1975 | emu->voices[idx].number = idx; | 1914 | emu->voices[idx].number = idx; |
| 1976 | } | ||
| 1977 | 1915 | ||
| 1978 | err = snd_emu10k1_init(emu, enable_ir, 0); | 1916 | err = snd_emu10k1_init(emu, enable_ir); |
| 1979 | if (err < 0) | 1917 | if (err < 0) |
| 1980 | return err; | 1918 | return err; |
| 1981 | #ifdef CONFIG_PM_SLEEP | 1919 | #ifdef CONFIG_PM_SLEEP |
| @@ -2007,7 +1945,7 @@ static const unsigned char saved_regs[] = { · 25 unmodified lines | |||
| 2007 | 0xff /* end */ | 1945 | 0xff /* end */ |
| 2008 | }; | 1946 | }; |
| 2009 | static const unsigned char saved_regs_audigy[] = { | 1947 | static const unsigned char saved_regs_audigy[] = { |
| 2010 | A_ADCIDX, A_MICIDX, A_FXWC1, A_FXWC2, A_SAMPLE_RATE, | 1948 | A_ADCIDX, A_MICIDX, A_FXWC1, A_FXWC2, A_EHC, |
| 2011 | A_FXRT2, A_SENDAMOUNTS, A_FXRT1, | 1949 | A_FXRT2, A_SENDAMOUNTS, A_FXRT1, |
| 2012 | 0xff /* end */ | 1950 | 0xff /* end */ |
| 2013 | }; | 1951 | }; |
| @@ -2054,7 +1992,7 @@ void snd_emu10k1_suspend_regs(struct snd_emu10k1 *emu) · 40 unmodified lines | |||
| 2054 | *val = snd_emu10k1_ptr_read(emu, *reg, i); | 1992 | *val = snd_emu10k1_ptr_read(emu, *reg, i); |
| 2055 | } | 1993 | } |
| 2056 | if (emu->audigy) | 1994 | if (emu->audigy) |
| 2057 | emu->saved_a_iocfg = inl(emu->port + A_IOCFG); | 1995 | emu->saved_a_iocfg = inw(emu->port + A_IOCFG); |
| 2058 | emu->saved_hcfg = inl(emu->port + HCFG); | 1996 | emu->saved_hcfg = inl(emu->port + HCFG); |
| 2059 | } | 1997 | } |
| 2060 | 1998 | ||
| @@ -2068,7 +2006,7 @@ void snd_emu10k1_resume_init(struct snd_emu10k1 *emu) · 7 unmodified lines | |||
| 2068 | snd_emu10k1_emu1010_init(emu); | 2006 | snd_emu10k1_emu1010_init(emu); |
| 2069 | else | 2007 | else |
| 2070 | snd_emu10k1_ptr_write(emu, AC97SLOT, 0, AC97SLOT_CNTR|AC97SLOT_LFE); | 2008 | snd_emu10k1_ptr_write(emu, AC97SLOT, 0, AC97SLOT_CNTR|AC97SLOT_LFE); |
| 2071 | snd_emu10k1_init(emu, emu->enable_ir, 1); | 2009 | snd_emu10k1_init(emu, emu->enable_ir); |
| 2072 | } | 2010 | } |
| 2073 | 2011 | ||
| 2074 | void snd_emu10k1_resume_regs(struct snd_emu10k1 *emu) | 2012 | void snd_emu10k1_resume_regs(struct snd_emu10k1 *emu) |
| @@ -2081,7 +2019,7 @@ void snd_emu10k1_resume_regs(struct snd_emu10k1 *emu) · 6 unmodified lines | |||
| 2081 | 2019 | ||
| 2082 | /* resore for spdif */ | 2020 | /* resore for spdif */ |
| 2083 | if (emu->audigy) | 2021 | if (emu->audigy) |
| 2084 | outl(emu->saved_a_iocfg, emu->port + A_IOCFG); | 2022 | outw(emu->saved_a_iocfg, emu->port + A_IOCFG); |
| 2085 | outl(emu->saved_hcfg, emu->port + HCFG); | 2023 | outl(emu->saved_hcfg, emu->port + HCFG); |
| 2086 | 2024 | ||
| 2087 | val = emu->saved_ptr; | 2025 | val = emu->saved_ptr; |
| @@ -641,8 +641,8 @@ snd_emu10k1_look_for_ctl(struct snd_emu10k1 *emu, · 640 unmodified lines | |||
| 641 | list_for_each_entry(ctl, &emu->fx8010.gpr_ctl, list) { | 641 | list_for_each_entry(ctl, &emu->fx8010.gpr_ctl, list) { |
| 642 | kcontrol = ctl->kcontrol; | 642 | kcontrol = ctl->kcontrol; |
| 643 | if (kcontrol->id.iface == id->iface && | 643 | if (kcontrol->id.iface == id->iface && |
| 644 | !strcmp(kcontrol->id.name, id->name) && | 644 | kcontrol->id.index == id->index && |
| 645 | kcontrol->id.index == id->index) | 645 | !strcmp(kcontrol->id.name, id->name)) |
| 646 | return ctl; | 646 | return ctl; |
| 647 | } | 647 | } |
| 648 | return NULL; | 648 | return NULL; |
| @@ -1187,8 +1187,8 @@ snd_emu10k1_init_stereo_onoff_control(struct snd_emu10k1_fx8010_control_gpr *ctl · 538 unmodified lines | |||
| 1187 | } | 1187 | } |
| 1188 | 1188 | ||
| 1189 | /* | 1189 | /* |
| 1190 | * Used for emu1010 - conversion from 32-bit capture inputs from HANA | 1190 | * Used for emu1010 - conversion from 32-bit capture inputs from the FPGA |
| 1191 | * to 2 x 16-bit registers in audigy - their values are read via DMA. | 1191 | * to 2 x 16-bit registers in Audigy - their values are read via DMA. |
| 1192 | * Conversion is performed by Audigy DSP instructions of FX8010. | 1192 | * Conversion is performed by Audigy DSP instructions of FX8010. |
| 1193 | */ | 1193 | */ |
| 1194 | static int snd_emu10k1_audigy_dsp_convert_32_to_2x16( | 1194 | static int snd_emu10k1_audigy_dsp_convert_32_to_2x16( |
| @@ -1213,7 +1213,7 @@ static int snd_emu10k1_audigy_dsp_convert_32_to_2x16( · 18 unmodified lines | |||
| 1213 | 1213 | ||
| 1214 | static int _snd_emu10k1_audigy_init_efx(struct snd_emu10k1 *emu) | 1214 | static int _snd_emu10k1_audigy_init_efx(struct snd_emu10k1 *emu) |
| 1215 | { | 1215 | { |
| 1216 | int err, i, z, gpr, nctl; | 1216 | int err, z, gpr, nctl; |
| 1217 | int bit_shifter16; | 1217 | int bit_shifter16; |
| 1218 | const int playback = 10; | 1218 | const int playback = 10; |
| 1219 | const int capture = playback + (SND_EMU10K1_PLAYBACK_CHANNELS * 2); /* we reserve 10 voices */ | 1219 | const int capture = playback + (SND_EMU10K1_PLAYBACK_CHANNELS * 2); /* we reserve 10 voices */ |
| @@ -1245,12 +1245,10 @@ static int _snd_emu10k1_audigy_init_efx(struct snd_emu10k1 *emu) · 25 unmodified lines | |||
| 1245 | icode->code = icode->tram_addr_map + 256; | 1245 | icode->code = icode->tram_addr_map + 256; |
| 1246 | 1246 | ||
| 1247 | /* clear free GPRs */ | 1247 | /* clear free GPRs */ |
| 1248 | for (i = 0; i < 512; i++) | 1248 | memset(icode->gpr_valid, 0xff, 512 / 8); |
| 1249 | set_bit(i, icode->gpr_valid); | ||
| 1250 | 1249 | ||
| 1251 | /* clear TRAM data & address lines */ | 1250 | /* clear TRAM data & address lines */ |
| 1252 | for (i = 0; i < 256; i++) | 1251 | memset(icode->tram_valid, 0xff, 256 / 8); |
| 1253 | set_bit(i, icode->tram_valid); | ||
| 1254 | 1252 | ||
| 1255 | strcpy(icode->name, "Audigy DSP code for ALSA"); | 1253 | strcpy(icode->name, "Audigy DSP code for ALSA"); |
| 1256 | ptr = 0; | 1254 | ptr = 0; |
| @@ -1261,9 +1259,6 @@ static int _snd_emu10k1_audigy_init_efx(struct snd_emu10k1 *emu) · 4 unmodified lines | |||
| 1261 | gpr_map[gpr++] = 0x0000ffff; | 1259 | gpr_map[gpr++] = 0x0000ffff; |
| 1262 | bit_shifter16 = gpr; | 1260 | bit_shifter16 = gpr; |
| 1263 | 1261 | ||
| 1264 | /* stop FX processor */ | ||
| 1265 | snd_emu10k1_ptr_write(emu, A_DBG, 0, (emu->fx8010.dbg = 0) | A_DBG_SINGLE_STEP); | ||
| 1266 | |||
| 1267 | #if 1 | 1262 | #if 1 |
| 1268 | /* PCM front Playback Volume (independent from stereo mix) | 1263 | /* PCM front Playback Volume (independent from stereo mix) |
| 1269 | * playback = 0 + ( gpr * FXBUS_PCM_LEFT_FRONT >> 31) | 1264 | * playback = 0 + ( gpr * FXBUS_PCM_LEFT_FRONT >> 31) |
| @@ -1332,8 +1327,9 @@ static int _snd_emu10k1_audigy_init_efx(struct snd_emu10k1 *emu) · 62 unmodified lines | |||
| 1332 | #define A_ADD_VOLUME_IN(var,vol,input) \ | 1327 | #define A_ADD_VOLUME_IN(var,vol,input) \ |
| 1333 | A_OP(icode, &ptr, iMAC0, A_GPR(var), A_GPR(var), A_GPR(vol), A_EXTIN(input)) | 1328 | A_OP(icode, &ptr, iMAC0, A_GPR(var), A_GPR(var), A_GPR(vol), A_EXTIN(input)) |
| 1334 | 1329 | ||
| 1335 | /* emu1212 DSP 0 and DSP 1 Capture */ | ||
| 1336 | if (emu->card_capabilities->emu_model) { | 1330 | if (emu->card_capabilities->emu_model) { |
| 1331 | /* EMU1010 DSP 0 and DSP 1 Capture */ | ||
| 1332 | // The 24 MSB hold the actual value. We implicitly discard the 16 LSB. | ||
| 1337 | if (emu->card_capabilities->ca0108_chip) { | 1333 | if (emu->card_capabilities->ca0108_chip) { |
| 1338 | /* Note:JCD:No longer bit shift lower 16bits to upper 16bits of 32bit value. */ | 1334 | /* Note:JCD:No longer bit shift lower 16bits to upper 16bits of 32bit value. */ |
| 1339 | A_OP(icode, &ptr, iMACINT0, A_GPR(tmp), A_C_00000000, A3_EMU32IN(0x0), A_C_00000001); | 1335 | A_OP(icode, &ptr, iMACINT0, A_GPR(tmp), A_C_00000000, A3_EMU32IN(0x0), A_C_00000001); |
| @@ -1638,8 +1634,11 @@ A_OP(icode, &ptr, iMAC0, A_GPR(var), A_GPR(var), A_GPR(vol), A_EXTIN(input)) · 298 unmodified lines | |||
| 1638 | #endif | 1634 | #endif |
| 1639 | 1635 | ||
| 1640 | if (emu->card_capabilities->emu_model) { | 1636 | if (emu->card_capabilities->emu_model) { |
| 1637 | /* Capture 16 channels of S32_LE sound. */ | ||
| 1641 | if (emu->card_capabilities->ca0108_chip) { | 1638 | if (emu->card_capabilities->ca0108_chip) { |
| 1642 | dev_info(emu->card->dev, "EMU2 inputs on\n"); | 1639 | dev_info(emu->card->dev, "EMU2 inputs on\n"); |
| 1640 | /* Note that the Tina[2] DSPs have 16 more EMU32 inputs which we don't use. */ | ||
| 1641 | |||
| 1643 | for (z = 0; z < 0x10; z++) { | 1642 | for (z = 0; z < 0x10; z++) { |
| 1644 | snd_emu10k1_audigy_dsp_convert_32_to_2x16( icode, &ptr, tmp, | 1643 | snd_emu10k1_audigy_dsp_convert_32_to_2x16( icode, &ptr, tmp, |
| 1645 | bit_shifter16, | 1644 | bit_shifter16, |
| @@ -1648,7 +1647,7 @@ A_OP(icode, &ptr, iMAC0, A_GPR(var), A_GPR(var), A_GPR(vol), A_EXTIN(input)) · 2 unmodified lines | |||
| 1648 | } | 1647 | } |
| 1649 | } else { | 1648 | } else { |
| 1650 | dev_info(emu->card->dev, "EMU inputs on\n"); | 1649 | dev_info(emu->card->dev, "EMU inputs on\n"); |
| 1651 | /* Capture 16 (originally 8) channels of S32_LE sound */ | 1650 | /* Note that the Alice2 DSPs have 6 I2S inputs which we don't use. */ |
| 1652 | 1651 | ||
| 1653 | /* | 1652 | /* |
| 1654 | dev_dbg(emu->card->dev, "emufx.c: gpr=0x%x, tmp=0x%x\n", | 1653 | dev_dbg(emu->card->dev, "emufx.c: gpr=0x%x, tmp=0x%x\n", |
| @@ -1886,12 +1885,10 @@ static int _snd_emu10k1_init_efx(struct snd_emu10k1 *emu) · 231 unmodified lines | |||
| 1886 | icode->code = icode->tram_addr_map + 160; | 1885 | icode->code = icode->tram_addr_map + 160; |
| 1887 | 1886 | ||
| 1888 | /* clear free GPRs */ | 1887 | /* clear free GPRs */ |
| 1889 | for (i = 0; i < 256; i++) | 1888 | memset(icode->gpr_valid, 0xff, 256 / 8); |
| 1890 | set_bit(i, icode->gpr_valid); | ||
| 1891 | 1889 | ||
| 1892 | /* clear TRAM data & address lines */ | 1890 | /* clear TRAM data & address lines */ |
| 1893 | for (i = 0; i < 160; i++) | 1891 | memset(icode->tram_valid, 0xff, 160 / 8); |
| 1894 | set_bit(i, icode->tram_valid); | ||
| 1895 | 1892 | ||
| 1896 | strcpy(icode->name, "SB Live! FX8010 code for ALSA v1.2 by Jaroslav Kysela"); | 1893 | strcpy(icode->name, "SB Live! FX8010 code for ALSA v1.2 by Jaroslav Kysela"); |
| 1897 | ptr = 0; i = 0; | 1894 | ptr = 0; i = 0; |
| @@ -1903,9 +1900,6 @@ static int _snd_emu10k1_init_efx(struct snd_emu10k1 *emu) · 5 unmodified lines | |||
| 1903 | tmp = 0x88; /* we need 4 temporary GPR */ | 1900 | tmp = 0x88; /* we need 4 temporary GPR */ |
| 1904 | /* from 0x8c to 0xff is the area for tone control */ | 1901 | /* from 0x8c to 0xff is the area for tone control */ |
| 1905 | 1902 | ||
| 1906 | /* stop FX processor */ | ||
| 1907 | snd_emu10k1_ptr_write(emu, DBG, 0, (emu->fx8010.dbg = 0) | EMU10K1_DBG_SINGLE_STEP); | ||
| 1908 | |||
| 1909 | /* | 1903 | /* |
| 1910 | * Process FX Buses | 1904 | * Process FX Buses |
| 1911 | */ | 1905 | */ |
| @@ -2523,7 +2517,7 @@ static void snd_emu10k1_fx8010_info(struct snd_emu10k1 *emu, · 611 unmodified lines | |||
| 2523 | struct snd_emu10k1_fx8010_info *info) | 2517 | struct snd_emu10k1_fx8010_info *info) |
| 2524 | { | 2518 | { |
| 2525 | const char * const *fxbus, * const *extin, * const *extout; | 2519 | const char * const *fxbus, * const *extin, * const *extout; |
| 2526 | unsigned short fxbus_mask, extin_mask, extout_mask; | 2520 | unsigned short extin_mask, extout_mask; |
| 2527 | int res; | 2521 | int res; |
| 2528 | 2522 | ||
| 2529 | info->internal_tram_size = emu->fx8010.itram_size; | 2523 | info->internal_tram_size = emu->fx8010.itram_size; |
| @@ -2531,11 +2525,10 @@ static void snd_emu10k1_fx8010_info(struct snd_emu10k1 *emu, · 1 unmodified line | |||
| 2531 | fxbus = fxbuses; | 2525 | fxbus = fxbuses; |
| 2532 | extin = emu->audigy ? audigy_ins : creative_ins; | 2526 | extin = emu->audigy ? audigy_ins : creative_ins; |
| 2533 | extout = emu->audigy ? audigy_outs : creative_outs; | 2527 | extout = emu->audigy ? audigy_outs : creative_outs; |
| 2534 | fxbus_mask = emu->fx8010.fxbus_mask; | 2528 | extin_mask = emu->audigy ? ~0 : emu->fx8010.extin_mask; |
| 2535 | extin_mask = emu->fx8010.extin_mask; | 2529 | extout_mask = emu->audigy ? ~0 : emu->fx8010.extout_mask; |
| 2536 | extout_mask = emu->fx8010.extout_mask; | ||
| 2537 | for (res = 0; res < 16; res++, fxbus++, extin++, extout++) { | 2530 | for (res = 0; res < 16; res++, fxbus++, extin++, extout++) { |
| 2538 | copy_string(info->fxbus_names[res], fxbus_mask & (1 << res) ? *fxbus : NULL, "FXBUS", res); | 2531 | copy_string(info->fxbus_names[res], *fxbus, "FXBUS", res); |
| 2539 | copy_string(info->extin_names[res], extin_mask & (1 << res) ? *extin : NULL, "Unused", res); | 2532 | copy_string(info->extin_names[res], extin_mask & (1 << res) ? *extin : NULL, "Unused", res); |
| 2540 | copy_string(info->extout_names[res], extout_mask & (1 << res) ? *extout : NULL, "Unused", res); | 2533 | copy_string(info->extout_names[res], extout_mask & (1 << res) ? *extout : NULL, "Unused", res); |
| 2541 | } | 2534 | } |
| @@ -2651,17 +2644,19 @@ static int snd_emu10k1_fx8010_ioctl(struct snd_hwdep * hw, struct file *file, un · 109 unmodified lines | |||
| 2651 | return -EPERM; | 2644 | return -EPERM; |
| 2652 | if (get_user(addr, (unsigned int __user *)argp)) | 2645 | if (get_user(addr, (unsigned int __user *)argp)) |
| 2653 | return -EFAULT; | 2646 | return -EFAULT; |
| 2654 | if (addr > 0x1ff) | 2647 | if (emu->audigy) { |
| 2655 | return -EINVAL; | 2648 | if (addr > A_DBG_STEP_ADDR) |
| 2656 | if (emu->audigy) | 2649 | return -EINVAL; |
| 2657 | snd_emu10k1_ptr_write(emu, A_DBG, 0, emu->fx8010.dbg |= A_DBG_SINGLE_STEP | addr); | 2650 | snd_emu10k1_ptr_write(emu, A_DBG, 0, emu->fx8010.dbg |= A_DBG_SINGLE_STEP); |
| 2658 | else | 2651 | udelay(10); |
| 2659 | snd_emu10k1_ptr_write(emu, DBG, 0, emu->fx8010.dbg |= EMU10K1_DBG_SINGLE_STEP | addr); | 2652 | snd_emu10k1_ptr_write(emu, A_DBG, 0, emu->fx8010.dbg | A_DBG_STEP | addr); |
| 2660 | udelay(10); | 2653 | } else { |
| 2661 | if (emu->audigy) | 2654 | if (addr > EMU10K1_DBG_SINGLE_STEP_ADDR) |
| 2662 | snd_emu10k1_ptr_write(emu, A_DBG, 0, emu->fx8010.dbg |= A_DBG_SINGLE_STEP | A_DBG_STEP_ADDR | addr); | 2655 | return -EINVAL; |
| 2663 | else | 2656 | snd_emu10k1_ptr_write(emu, DBG, 0, emu->fx8010.dbg |= EMU10K1_DBG_SINGLE_STEP); |
| 2664 | snd_emu10k1_ptr_write(emu, DBG, 0, emu->fx8010.dbg |= EMU10K1_DBG_SINGLE_STEP | EMU10K1_DBG_STEP | addr); | 2657 | udelay(10); |
| 2658 | snd_emu10k1_ptr_write(emu, DBG, 0, emu->fx8010.dbg | EMU10K1_DBG_STEP | addr); | ||
| 2659 | } | ||
| 2665 | return 0; | 2660 | return 0; |
| 2666 | case SNDRV_EMU10K1_IOCTL_DBG_READ: | 2661 | case SNDRV_EMU10K1_IOCTL_DBG_READ: |
| 2667 | if (emu->audigy) | 2662 | if (emu->audigy) |
| @@ -346,7 +346,7 @@ static const unsigned int emu1616_output_dst[] = { · 345 unmodified lines | |||
| 346 | }; | 346 | }; |
| 347 | 347 | ||
| 348 | /* | 348 | /* |
| 349 | * Data destinations - HANA outputs going to Alice2 (audigy) for | 349 | * Data destinations - FPGA outputs going to Alice2 (Audigy) for |
| 350 | * capture (EMU32 + I2S links) | 350 | * capture (EMU32 + I2S links) |
| 351 | * Each destination has an enum mixer control to choose a data source | 351 | * Each destination has an enum mixer control to choose a data source |
| 352 | */ | 352 | */ |
| @@ -367,6 +367,7 @@ static const unsigned int emu1010_input_dst[] = { · 14 unmodified lines | |||
| 367 | EMU_DST_ALICE2_EMU32_D, | 367 | EMU_DST_ALICE2_EMU32_D, |
| 368 | EMU_DST_ALICE2_EMU32_E, | 368 | EMU_DST_ALICE2_EMU32_E, |
| 369 | EMU_DST_ALICE2_EMU32_F, | 369 | EMU_DST_ALICE2_EMU32_F, |
| 370 | /* These exist only on rev1 EMU1010 cards. */ | ||
| 370 | EMU_DST_ALICE_I2S0_LEFT, | 371 | EMU_DST_ALICE_I2S0_LEFT, |
| 371 | EMU_DST_ALICE_I2S0_RIGHT, | 372 | EMU_DST_ALICE_I2S0_RIGHT, |
| 372 | EMU_DST_ALICE_I2S1_LEFT, | 373 | EMU_DST_ALICE_I2S1_LEFT, |
| @@ -708,7 +709,7 @@ static int snd_emu1010_internal_clock_put(struct snd_kcontrol *kcontrol, · 335 unmodified lines | |||
| 708 | /* 44100 */ | 709 | /* 44100 */ |
| 709 | /* Mute all */ | 710 | /* Mute all */ |
| 710 | snd_emu1010_fpga_write(emu, EMU_HANA_UNMUTE, EMU_MUTE ); | 711 | snd_emu1010_fpga_write(emu, EMU_HANA_UNMUTE, EMU_MUTE ); |
| 711 | /* Default fallback clock 48kHz */ | 712 | /* Default fallback clock 44.1kHz */ |
| 712 | snd_emu1010_fpga_write(emu, EMU_HANA_DEFCLOCK, EMU_HANA_DEFCLOCK_44_1K ); | 713 | snd_emu1010_fpga_write(emu, EMU_HANA_DEFCLOCK, EMU_HANA_DEFCLOCK_44_1K ); |
| 713 | /* Word Clock source, Internal 44.1kHz x1 */ | 714 | /* Word Clock source, Internal 44.1kHz x1 */ |
| 714 | snd_emu1010_fpga_write(emu, EMU_HANA_WCLOCK, | 715 | snd_emu1010_fpga_write(emu, EMU_HANA_WCLOCK, |
| @@ -924,7 +925,7 @@ static int snd_audigy_i2c_capture_source_put(struct snd_kcontrol *kcontrol, · 209 unmodified lines | |||
| 924 | struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol); | 925 | struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol); |
| 925 | unsigned int source_id; | 926 | unsigned int source_id; |
| 926 | unsigned int ngain, ogain; | 927 | unsigned int ngain, ogain; |
| 927 | u32 gpio; | 928 | u16 gpio; |
| 928 | int change = 0; | 929 | int change = 0; |
| 929 | unsigned long flags; | 930 | unsigned long flags; |
| 930 | u32 source; | 931 | u32 source; |
| @@ -941,11 +942,11 @@ static int snd_audigy_i2c_capture_source_put(struct snd_kcontrol *kcontrol, · 10 unmodified lines | |||
| 941 | if (change) { | 942 | if (change) { |
| 942 | snd_emu10k1_i2c_write(emu, ADC_MUX, 0); /* Mute input */ | 943 | snd_emu10k1_i2c_write(emu, ADC_MUX, 0); /* Mute input */ |
| 943 | spin_lock_irqsave(&emu->emu_lock, flags); | 944 | spin_lock_irqsave(&emu->emu_lock, flags); |
| 944 | gpio = inl(emu->port + A_IOCFG); | 945 | gpio = inw(emu->port + A_IOCFG); |
| 945 | if (source_id==0) | 946 | if (source_id==0) |
| 946 | outl(gpio | 0x4, emu->port + A_IOCFG); | 947 | outw(gpio | 0x4, emu->port + A_IOCFG); |
| 947 | else | 948 | else |
| 948 | outl(gpio & ~0x4, emu->port + A_IOCFG); | 949 | outw(gpio & ~0x4, emu->port + A_IOCFG); |
| 949 | spin_unlock_irqrestore(&emu->emu_lock, flags); | 950 | spin_unlock_irqrestore(&emu->emu_lock, flags); |
| 950 | 951 | ||
| 951 | ngain = emu->i2c_capture_volume[source_id][0]; /* Left */ | 952 | ngain = emu->i2c_capture_volume[source_id][0]; /* Left */ |
| @@ -1005,7 +1006,7 @@ static int snd_audigy_i2c_volume_put(struct snd_kcontrol *kcontrol, · 53 unmodified lines | |||
| 1005 | { | 1006 | { |
| 1006 | struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol); | 1007 | struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol); |
| 1007 | unsigned int ogain; | 1008 | unsigned int ogain; |
| 1008 | unsigned int ngain; | 1009 | unsigned int ngain0, ngain1; |
| 1009 | unsigned int source_id; | 1010 | unsigned int source_id; |
| 1010 | int change = 0; | 1011 | int change = 0; |
| 1011 | 1012 | ||
| @@ -1014,24 +1015,24 @@ static int snd_audigy_i2c_volume_put(struct snd_kcontrol *kcontrol, · 2 unmodified lines | |||
| 1014 | /* capture_source: uinfo->value.enumerated.items = 2 */ | 1015 | /* capture_source: uinfo->value.enumerated.items = 2 */ |
| 1015 | if (source_id >= 2) | 1016 | if (source_id >= 2) |
| 1016 | return -EINVAL; | 1017 | return -EINVAL; |
| 1018 | ngain0 = ucontrol->value.integer.value[0]; | ||
| 1019 | ngain1 = ucontrol->value.integer.value[1]; | ||
| 1020 | if (ngain0 > 0xff) | ||
| 1021 | return -EINVAL; | ||
| 1022 | if (ngain1 > 0xff) | ||
| 1023 | return -EINVAL; | ||
| 1017 | ogain = emu->i2c_capture_volume[source_id][0]; /* Left */ | 1024 | ogain = emu->i2c_capture_volume[source_id][0]; /* Left */ |
| 1018 | ngain = ucontrol->value.integer.value[0]; | 1025 | if (ogain != ngain0) { |
| 1019 | if (ngain > 0xff) | ||
| 1020 | return 0; | ||
| 1021 | if (ogain != ngain) { | ||
| 1022 | if (emu->i2c_capture_source == source_id) | 1026 | if (emu->i2c_capture_source == source_id) |
| 1023 | snd_emu10k1_i2c_write(emu, ADC_ATTEN_ADCL, ((ngain) & 0xff) ); | 1027 | snd_emu10k1_i2c_write(emu, ADC_ATTEN_ADCL, ngain0); |
| 1024 | emu->i2c_capture_volume[source_id][0] = ngain; | 1028 | emu->i2c_capture_volume[source_id][0] = ngain0; |
| 1025 | change = 1; | 1029 | change = 1; |
| 1026 | } | 1030 | } |
| 1027 | ogain = emu->i2c_capture_volume[source_id][1]; /* Right */ | 1031 | ogain = emu->i2c_capture_volume[source_id][1]; /* Right */ |
| 1028 | ngain = ucontrol->value.integer.value[1]; | 1032 | if (ogain != ngain1) { |
| 1029 | if (ngain > 0xff) | ||
| 1030 | return 0; | ||
| 1031 | if (ogain != ngain) { | ||
| 1032 | if (emu->i2c_capture_source == source_id) | 1033 | if (emu->i2c_capture_source == source_id) |
| 1033 | snd_emu10k1_i2c_write(emu, ADC_ATTEN_ADCR, ((ngain) & 0xff)); | 1034 | snd_emu10k1_i2c_write(emu, ADC_ATTEN_ADCR, ngain1); |
| 1034 | emu->i2c_capture_volume[source_id][1] = ngain; | 1035 | emu->i2c_capture_volume[source_id][1] = ngain1; |
| 1035 | change = 1; | 1036 | change = 1; |
| 1036 | } | 1037 | } |
| 1037 | 1038 | ||
| @@ -1632,7 +1633,7 @@ static int snd_emu10k1_shared_spdif_get(struct snd_kcontrol *kcontrol, · 594 unmodified lines | |||
| 1632 | struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol); | 1633 | struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol); |
| 1633 | 1634 | ||
| 1634 | if (emu->audigy) | 1635 | if (emu->audigy) |
| 1635 | ucontrol->value.integer.value[0] = inl(emu->port + A_IOCFG) & A_IOCFG_GPOUT0 ? 1 : 0; | 1636 | ucontrol->value.integer.value[0] = inw(emu->port + A_IOCFG) & A_IOCFG_GPOUT0 ? 1 : 0; |
| 1636 | else | 1637 | else |
| 1637 | ucontrol->value.integer.value[0] = inl(emu->port + HCFG) & HCFG_GPOUT0 ? 1 : 0; | 1638 | ucontrol->value.integer.value[0] = inl(emu->port + HCFG) & HCFG_GPOUT0 ? 1 : 0; |
| 1638 | if (emu->card_capabilities->invert_shared_spdif) | 1639 | if (emu->card_capabilities->invert_shared_spdif) |
| @@ -1657,13 +1658,13 @@ static int snd_emu10k1_shared_spdif_put(struct snd_kcontrol *kcontrol, · 18 unmodified lines | |||
| 1657 | if ( emu->card_capabilities->i2c_adc) { | 1658 | if ( emu->card_capabilities->i2c_adc) { |
| 1658 | /* Do nothing for Audigy 2 ZS Notebook */ | 1659 | /* Do nothing for Audigy 2 ZS Notebook */ |
| 1659 | } else if (emu->audigy) { | 1660 | } else if (emu->audigy) { |
| 1660 | reg = inl(emu->port + A_IOCFG); | 1661 | reg = inw(emu->port + A_IOCFG); |
| 1661 | val = sw ? A_IOCFG_GPOUT0 : 0; | 1662 | val = sw ? A_IOCFG_GPOUT0 : 0; |
| 1662 | change = (reg & A_IOCFG_GPOUT0) != val; | 1663 | change = (reg & A_IOCFG_GPOUT0) != val; |
| 1663 | if (change) { | 1664 | if (change) { |
| 1664 | reg &= ~A_IOCFG_GPOUT0; | 1665 | reg &= ~A_IOCFG_GPOUT0; |
| 1665 | reg |= val; | 1666 | reg |= val; |
| 1666 | outl(reg | val, emu->port + A_IOCFG); | 1667 | outw(reg | val, emu->port + A_IOCFG); |
| 1667 | } | 1668 | } |
| 1668 | } | 1669 | } |
| 1669 | reg = inl(emu->port + HCFG); | 1670 | reg = inl(emu->port + HCFG); |
| @@ -76,23 +76,6 @@ static void snd_emu10k1_pcm_efx_interrupt(struct snd_emu10k1 *emu, · 75 unmodified lines | |||
| 76 | snd_pcm_period_elapsed(emu->pcm_capture_efx_substream); | 76 | snd_pcm_period_elapsed(emu->pcm_capture_efx_substream); |
| 77 | } | 77 | } |
| 78 | 78 | ||
| 79 | static snd_pcm_uframes_t snd_emu10k1_efx_playback_pointer(struct snd_pcm_substream *substream) | ||
| 80 | { | ||
| 81 | struct snd_emu10k1 *emu = snd_pcm_substream_chip(substream); | ||
| 82 | struct snd_pcm_runtime *runtime = substream->runtime; | ||
| 83 | struct snd_emu10k1_pcm *epcm = runtime->private_data; | ||
| 84 | unsigned int ptr; | ||
| 85 | |||
| 86 | if (!epcm->running) | ||
| 87 | return 0; | ||
| 88 | ptr = snd_emu10k1_ptr_read(emu, CCCA, epcm->voices[0]->number) & 0x00ffffff; | ||
| 89 | ptr += runtime->buffer_size; | ||
| 90 | ptr -= epcm->ccca_start_addr; | ||
| 91 | ptr %= runtime->buffer_size; | ||
| 92 | |||
| 93 | return ptr; | ||
| 94 | } | ||
| 95 | |||
| 96 | static int snd_emu10k1_pcm_channel_alloc(struct snd_emu10k1_pcm * epcm, int voices) | 79 | static int snd_emu10k1_pcm_channel_alloc(struct snd_emu10k1_pcm * epcm, int voices) |
| 97 | { | 80 | { |
| 98 | int err, i; | 81 | int err, i; |
| @@ -343,7 +326,6 @@ static void snd_emu10k1_pcm_init_voice(struct snd_emu10k1 *emu, · 244 unmodified lines | |||
| 343 | } else | 326 | } else |
| 344 | snd_emu10k1_ptr_write(emu, FXRT, voice, | 327 | snd_emu10k1_ptr_write(emu, FXRT, voice, |
| 345 | snd_emu10k1_compose_send_routing(send_routing)); | 328 | snd_emu10k1_compose_send_routing(send_routing)); |
| 346 | /* Stop CA */ | ||
| 347 | /* Assumption that PT is already 0 so no harm overwriting */ | 329 | /* Assumption that PT is already 0 so no harm overwriting */ |
| 348 | snd_emu10k1_ptr_write(emu, PTRX, voice, (send_amount[0] << 8) | send_amount[1]); | 330 | snd_emu10k1_ptr_write(emu, PTRX, voice, (send_amount[0] << 8) | send_amount[1]); |
| 349 | snd_emu10k1_ptr_write(emu, DSL, voice, end_addr | (send_amount[3] << 24)); | 331 | snd_emu10k1_ptr_write(emu, DSL, voice, end_addr | (send_amount[3] << 24)); |
| @@ -429,36 +411,6 @@ static int snd_emu10k1_playback_hw_params(struct snd_pcm_substream *substream, · 79 unmodified lines | |||
| 429 | } | 411 | } |
| 430 | 412 | ||
| 431 | static int snd_emu10k1_playback_hw_free(struct snd_pcm_substream *substream) | 413 | static int snd_emu10k1_playback_hw_free(struct snd_pcm_substream *substream) |
| 432 | { | ||
| 433 | struct snd_emu10k1 *emu = snd_pcm_substream_chip(substream); | ||
| 434 | struct snd_pcm_runtime *runtime = substream->runtime; | ||
| 435 | struct snd_emu10k1_pcm *epcm; | ||
| 436 | |||
| 437 | if (runtime->private_data == NULL) | ||
| 438 | return 0; | ||
| 439 | epcm = runtime->private_data; | ||
| 440 | if (epcm->extra) { | ||
| 441 | snd_emu10k1_voice_free(epcm->emu, epcm->extra); | ||
| 442 | epcm->extra = NULL; | ||
| 443 | } | ||
| 444 | if (epcm->voices[1]) { | ||
| 445 | snd_emu10k1_voice_free(epcm->emu, epcm->voices[1]); | ||
| 446 | epcm->voices[1] = NULL; | ||
| 447 | } | ||
| 448 | if (epcm->voices[0]) { | ||
| 449 | snd_emu10k1_voice_free(epcm->emu, epcm->voices[0]); | ||
| 450 | epcm->voices[0] = NULL; | ||
| 451 | } | ||
| 452 | if (epcm->memblk) { | ||
| 453 | snd_emu10k1_free_pages(emu, epcm->memblk); | ||
| 454 | epcm->memblk = NULL; | ||
| 455 | epcm->start_addr = 0; | ||
| 456 | } | ||
| 457 | snd_pcm_lib_free_pages(substream); | ||
| 458 | return 0; | ||
| 459 | } | ||
| 460 | |||
| 461 | static int snd_emu10k1_efx_playback_hw_free(struct snd_pcm_substream *substream) | ||
| 462 | { | 414 | { |
| 463 | struct snd_emu10k1 *emu = snd_pcm_substream_chip(substream); | 415 | struct snd_emu10k1 *emu = snd_pcm_substream_chip(substream); |
| 464 | struct snd_pcm_runtime *runtime = substream->runtime; | 416 | struct snd_pcm_runtime *runtime = substream->runtime; |
| @@ -527,9 +479,6 @@ static int snd_emu10k1_efx_playback_prepare(struct snd_pcm_substream *substream) · 62 unmodified lines | |||
| 527 | start_addr = epcm->start_addr; | 479 | start_addr = epcm->start_addr; |
| 528 | end_addr = epcm->start_addr + snd_pcm_lib_buffer_bytes(substream); | 480 | end_addr = epcm->start_addr + snd_pcm_lib_buffer_bytes(substream); |
| 529 | 481 | ||
| 530 | /* | ||
| 531 | * the kX driver leaves some space between voices | ||
| 532 | */ | ||
| 533 | channel_size = ( end_addr - start_addr ) / NUM_EFX_PLAYBACK; | 482 | channel_size = ( end_addr - start_addr ) / NUM_EFX_PLAYBACK; |
| 534 | 483 | ||
| 535 | snd_emu10k1_pcm_init_voice(emu, 1, 1, epcm->extra, | 484 | snd_emu10k1_pcm_init_voice(emu, 1, 1, epcm->extra, |
| @@ -1091,8 +1040,6 @@ static int snd_emu10k1_efx_playback_open(struct snd_pcm_substream *substream) · 555 unmodified lines | |||
| 1091 | epcm->type = PLAYBACK_EFX; | 1040 | epcm->type = PLAYBACK_EFX; |
| 1092 | epcm->substream = substream; | 1041 | epcm->substream = substream; |
| 1093 | 1042 | ||
| 1094 | emu->pcm_playback_efx_substream = substream; | ||
| 1095 | |||
| 1096 | runtime->private_data = epcm; | 1043 | runtime->private_data = epcm; |
| 1097 | runtime->private_free = snd_emu10k1_pcm_free_substream; | 1044 | runtime->private_free = snd_emu10k1_pcm_free_substream; |
| 1098 | runtime->hw = snd_emu10k1_efx_playback; | 1045 | runtime->hw = snd_emu10k1_efx_playback; |
| @@ -1267,9 +1214,7 @@ static int snd_emu10k1_capture_efx_open(struct snd_pcm_substream *substream) · 168 unmodified lines | |||
| 1267 | runtime->hw.rate_min = runtime->hw.rate_max = 48000; | 1214 | runtime->hw.rate_min = runtime->hw.rate_max = 48000; |
| 1268 | spin_lock_irq(&emu->reg_lock); | 1215 | spin_lock_irq(&emu->reg_lock); |
| 1269 | if (emu->card_capabilities->emu_model) { | 1216 | if (emu->card_capabilities->emu_model) { |
| 1270 | /* Nb. of channels has been increased to 16 */ | ||
| 1271 | /* TODO | 1217 | /* TODO |
| 1272 | * SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S32_LE | ||
| 1273 | * SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000 | | 1218 | * SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000 | |
| 1274 | * SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000 | | 1219 | * SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000 | |
| 1275 | * SNDRV_PCM_RATE_176400 | SNDRV_PCM_RATE_192000 | 1220 | * SNDRV_PCM_RATE_176400 | SNDRV_PCM_RATE_192000 |
| @@ -1280,13 +1225,14 @@ static int snd_emu10k1_capture_efx_open(struct snd_pcm_substream *substream) · 4 unmodified lines | |||
| 1280 | * Need to add mixer control to fix sample rate | 1225 | * Need to add mixer control to fix sample rate |
| 1281 | * | 1226 | * |
| 1282 | * There are 32 mono channels of 16bits each. | 1227 | * There are 32 mono channels of 16bits each. |
| 1283 | * 24bit Audio uses 2x channels over 16bit | 1228 | * 24bit Audio uses 2x channels over 16bit, |
| 1284 | * 96kHz uses 2x channels over 48kHz | 1229 | * 96kHz uses 2x channels over 48kHz, |
| 1285 | * 192kHz uses 4x channels over 48kHz | 1230 | * 192kHz uses 4x channels over 48kHz. |
| 1286 | * So, for 48kHz 24bit, one has 16 channels | 1231 | * So, for 48kHz 24bit, one has 16 channels, |
| 1287 | * for 96kHz 24bit, one has 8 channels | 1232 | * for 96kHz 24bit, one has 8 channels, |
| 1288 | * for 192kHz 24bit, one has 4 channels | 1233 | * for 192kHz 24bit, one has 4 channels. |
| 1289 | * | 1234 | * 1010rev2 and 1616(m) cards have double that, |
| 1235 | * but we don't exceed 16 channels anyway. | ||
| 1290 | */ | 1236 | */ |
| 1291 | #if 1 | 1237 | #if 1 |
| 1292 | switch (emu->emu1010.internal_clock) { | 1238 | switch (emu->emu1010.internal_clock) { |
| @@ -1372,10 +1318,10 @@ static const struct snd_pcm_ops snd_emu10k1_efx_playback_ops = { · 79 unmodified lines | |||
| 1372 | .open = snd_emu10k1_efx_playback_open, | 1318 | .open = snd_emu10k1_efx_playback_open, |
| 1373 | .close = snd_emu10k1_efx_playback_close, | 1319 | .close = snd_emu10k1_efx_playback_close, |
| 1374 | .hw_params = snd_emu10k1_playback_hw_params, | 1320 | .hw_params = snd_emu10k1_playback_hw_params, |
| 1375 | .hw_free = snd_emu10k1_efx_playback_hw_free, | 1321 | .hw_free = snd_emu10k1_playback_hw_free, |
| 1376 | .prepare = snd_emu10k1_efx_playback_prepare, | 1322 | .prepare = snd_emu10k1_efx_playback_prepare, |
| 1377 | .trigger = snd_emu10k1_efx_playback_trigger, | 1323 | .trigger = snd_emu10k1_efx_playback_trigger, |
| 1378 | .pointer = snd_emu10k1_efx_playback_pointer, | 1324 | .pointer = snd_emu10k1_playback_pointer, |
| 1379 | }; | 1325 | }; |
| 1380 | 1326 | ||
| 1381 | int snd_emu10k1_pcm(struct snd_emu10k1 *emu, int device) | 1327 | int snd_emu10k1_pcm(struct snd_emu10k1 *emu, int device) |
| @@ -1508,11 +1454,12 @@ static int snd_emu10k1_pcm_efx_voices_mask_put(struct snd_kcontrol *kcontrol, st · 126 unmodified lines | |||
| 1508 | nval[idx / 32] |= 1 << (idx % 32); | 1454 | nval[idx / 32] |= 1 << (idx % 32); |
| 1509 | bits++; | 1455 | bits++; |
| 1510 | } | 1456 | } |
| 1511 | 1457 | ||
| 1458 | // Check that the number of requested channels is a power of two | ||
| 1459 | // not bigger than the number of available channels. | ||
| 1512 | for (idx = 0; idx < nefxb; idx++) | 1460 | for (idx = 0; idx < nefxb; idx++) |
| 1513 | if (1 << idx == bits) | 1461 | if (1 << idx == bits) |
| 1514 | break; | 1462 | break; |
| 1515 | |||
| 1516 | if (idx >= nefxb) | 1463 | if (idx >= nefxb) |
| 1517 | return -EINVAL; | 1464 | return -EINVAL; |
| 1518 | 1465 | ||
| @@ -1802,7 +1749,6 @@ int snd_emu10k1_pcm_efx(struct snd_emu10k1 *emu, int device) · 283 unmodified lines | |||
| 1802 | * to these | 1749 | * to these |
| 1803 | */ | 1750 | */ |
| 1804 | 1751 | ||
| 1805 | /* emu->efx_voices_mask[0] = FXWC_DEFAULTROUTE_C | FXWC_DEFAULTROUTE_A; */ | ||
| 1806 | if (emu->audigy) { | 1752 | if (emu->audigy) { |
| 1807 | emu->efx_voices_mask[0] = 0; | 1753 | emu->efx_voices_mask[0] = 0; |
| 1808 | if (emu->card_capabilities->emu_model) | 1754 | if (emu->card_capabilities->emu_model) |
| @@ -477,10 +477,7 @@ static void snd_emu_proc_ptr_reg_read(struct snd_info_entry *entry, · 476 unmodified lines | |||
| 477 | for(i = offset; i < offset+length; i++) { | 477 | for(i = offset; i < offset+length; i++) { |
| 478 | snd_iprintf(buffer, "%02X: ",i); | 478 | snd_iprintf(buffer, "%02X: ",i); |
| 479 | for (j = 0; j < voices; j++) { | 479 | for (j = 0; j < voices; j++) { |
| 480 | if(iobase == 0) | 480 | value = snd_ptr_read(emu, iobase, i, j); |
| 481 | value = snd_ptr_read(emu, 0, i, j); | ||
| 482 | else | ||
| 483 | value = snd_ptr_read(emu, 0x20, i, j); | ||
| 484 | snd_iprintf(buffer, "%08lX ", value); | 481 | snd_iprintf(buffer, "%08lX ", value); |
| 485 | } | 482 | } |
| 486 | snd_iprintf(buffer, "\n"); | 483 | snd_iprintf(buffer, "\n"); |
| @@ -233,56 +233,57 @@ int snd_emu10k1_i2c_write(struct snd_emu10k1 *emu, · 232 unmodified lines | |||
| 233 | return err; | 233 | return err; |
| 234 | } | 234 | } |
| 235 | 235 | ||
| 236 | int snd_emu1010_fpga_write(struct snd_emu10k1 * emu, u32 reg, u32 value) | 236 | void snd_emu1010_fpga_write(struct snd_emu10k1 *emu, u32 reg, u32 value) |
| 237 | { | 237 | { |
| 238 | unsigned long flags; | 238 | unsigned long flags; |
| 239 | 239 | ||
| 240 | if (reg > 0x3f) | 240 | if (snd_BUG_ON(reg > 0x3f)) |
| 241 | return 1; | 241 | return; |
| 242 | reg += 0x40; /* 0x40 upwards are registers. */ | 242 | reg += 0x40; /* 0x40 upwards are registers. */ |
| 243 | if (value > 0x3f) /* 0 to 0x3f are values */ | 243 | if (snd_BUG_ON(value > 0x3f)) /* 0 to 0x3f are values */ |
| 244 | return 1; | 244 | return; |
| 245 | spin_lock_irqsave(&emu->emu_lock, flags); | 245 | spin_lock_irqsave(&emu->emu_lock, flags); |
| 246 | outl(reg, emu->port + A_IOCFG); | 246 | outw(reg, emu->port + A_GPIO); |
| 247 | udelay(10); | 247 | udelay(10); |
| 248 | outl(reg | 0x80, emu->port + A_IOCFG); /* High bit clocks the value into the fpga. */ | 248 | outw(reg | 0x80, emu->port + A_GPIO); /* High bit clocks the value into the fpga. */ |
| 249 | udelay(10); | 249 | udelay(10); |
| 250 | outl(value, emu->port + A_IOCFG); | 250 | outw(value, emu->port + A_GPIO); |
| 251 | udelay(10); | 251 | udelay(10); |
| 252 | outl(value | 0x80 , emu->port + A_IOCFG); /* High bit clocks the value into the fpga. */ | 252 | outw(value | 0x80 , emu->port + A_GPIO); /* High bit clocks the value into the fpga. */ |
| 253 | spin_unlock_irqrestore(&emu->emu_lock, flags); | 253 | spin_unlock_irqrestore(&emu->emu_lock, flags); |
| 254 | |||
| 255 | return 0; | ||
| 256 | } | 254 | } |
| 257 | 255 | ||
| 258 | int snd_emu1010_fpga_read(struct snd_emu10k1 * emu, u32 reg, u32 *value) | 256 | void snd_emu1010_fpga_read(struct snd_emu10k1 *emu, u32 reg, u32 *value) |
| 259 | { | 257 | { |
| 258 | // The higest input pin is used as the designated interrupt trigger, | ||
| 259 | // so it needs to be masked out. | ||
| 260 | u32 mask = emu->card_capabilities->ca0108_chip ? 0x1f : 0x7f; | ||
| 260 | unsigned long flags; | 261 | unsigned long flags; |
| 261 | if (reg > 0x3f) | 262 | if (snd_BUG_ON(reg > 0x3f)) |
| 262 | return 1; | 263 | return; |
| 263 | reg += 0x40; /* 0x40 upwards are registers. */ | 264 | reg += 0x40; /* 0x40 upwards are registers. */ |
| 264 | spin_lock_irqsave(&emu->emu_lock, flags); | 265 | spin_lock_irqsave(&emu->emu_lock, flags); |
| 265 | outl(reg, emu->port + A_IOCFG); | 266 | outw(reg, emu->port + A_GPIO); |
| 266 | udelay(10); | 267 | udelay(10); |
| 267 | outl(reg | 0x80, emu->port + A_IOCFG); /* High bit clocks the value into the fpga. */ | 268 | outw(reg | 0x80, emu->port + A_GPIO); /* High bit clocks the value into the fpga. */ |
| 268 | udelay(10); | 269 | udelay(10); |
| 269 | *value = ((inl(emu->port + A_IOCFG) >> 8) & 0x7f); | 270 | *value = ((inw(emu->port + A_GPIO) >> 8) & mask); |
| 270 | spin_unlock_irqrestore(&emu->emu_lock, flags); | 271 | spin_unlock_irqrestore(&emu->emu_lock, flags); |
| 271 | |||
| 272 | return 0; | ||
| 273 | } | 272 | } |
| 274 | 273 | ||
| 275 | /* Each Destination has one and only one Source, | 274 | /* Each Destination has one and only one Source, |
| 276 | * but one Source can feed any number of Destinations simultaneously. | 275 | * but one Source can feed any number of Destinations simultaneously. |
| 277 | */ | 276 | */ |
| 278 | int snd_emu1010_fpga_link_dst_src_write(struct snd_emu10k1 * emu, u32 dst, u32 src) | 277 | void snd_emu1010_fpga_link_dst_src_write(struct snd_emu10k1 *emu, u32 dst, u32 src) |
| 279 | { | 278 | { |
| 280 | snd_emu1010_fpga_write(emu, 0x00, ((dst >> 8) & 0x3f) ); | 279 | if (snd_BUG_ON(dst & ~0x71f)) |
| 281 | snd_emu1010_fpga_write(emu, 0x01, (dst & 0x3f) ); | 280 | return; |
| 282 | snd_emu1010_fpga_write(emu, 0x02, ((src >> 8) & 0x3f) ); | 281 | if (snd_BUG_ON(src & ~0x71f)) |
| 283 | snd_emu1010_fpga_write(emu, 0x03, (src & 0x3f) ); | 282 | return; |
| 284 | 283 | snd_emu1010_fpga_write(emu, 0x00, dst >> 8); | |
| 285 | return 0; | 284 | snd_emu1010_fpga_write(emu, 0x01, dst & 0x1f); |
| 285 | snd_emu1010_fpga_write(emu, 0x02, src >> 8); | ||
| 286 | snd_emu1010_fpga_write(emu, 0x03, src & 0x1f); | ||
| 286 | } | 287 | } |
| 287 | 288 | ||
| 288 | void snd_emu10k1_intr_enable(struct snd_emu10k1 *emu, unsigned int intrenb) | 289 | void snd_emu10k1_intr_enable(struct snd_emu10k1 *emu, unsigned int intrenb) |
| @@ -313,7 +314,6 @@ void snd_emu10k1_voice_intr_enable(struct snd_emu10k1 *emu, unsigned int voicenu · 24 unmodified lines | |||
| 313 | unsigned int val; | 314 | unsigned int val; |
| 314 | 315 | ||
| 315 | spin_lock_irqsave(&emu->emu_lock, flags); | 316 | spin_lock_irqsave(&emu->emu_lock, flags); |
| 316 | /* voice interrupt */ | ||
| 317 | if (voicenum >= 32) { | 317 | if (voicenum >= 32) { |
| 318 | outl(CLIEH << 16, emu->port + PTR); | 318 | outl(CLIEH << 16, emu->port + PTR); |
| 319 | val = inl(emu->port + DATA); | 319 | val = inl(emu->port + DATA); |
| @@ -333,7 +333,6 @@ void snd_emu10k1_voice_intr_disable(struct snd_emu10k1 *emu, unsigned int voicen · 13 unmodified lines | |||
| 333 | unsigned int val; | 333 | unsigned int val; |
| 334 | 334 | ||
| 335 | spin_lock_irqsave(&emu->emu_lock, flags); | 335 | spin_lock_irqsave(&emu->emu_lock, flags); |
| 336 | /* voice interrupt */ | ||
| 337 | if (voicenum >= 32) { | 336 | if (voicenum >= 32) { |
| 338 | outl(CLIEH << 16, emu->port + PTR); | 337 | outl(CLIEH << 16, emu->port + PTR); |
| 339 | val = inl(emu->port + DATA); | 338 | val = inl(emu->port + DATA); |
| @@ -352,7 +351,6 @@ void snd_emu10k1_voice_intr_ack(struct snd_emu10k1 *emu, unsigned int voicenum) · 12 unmodified lines | |||
| 352 | unsigned long flags; | 351 | unsigned long flags; |
| 353 | 352 | ||
| 354 | spin_lock_irqsave(&emu->emu_lock, flags); | 353 | spin_lock_irqsave(&emu->emu_lock, flags); |
| 355 | /* voice interrupt */ | ||
| 356 | if (voicenum >= 32) { | 354 | if (voicenum >= 32) { |
| 357 | outl(CLIPH << 16, emu->port + PTR); | 355 | outl(CLIPH << 16, emu->port + PTR); |
| 358 | voicenum = 1 << (voicenum - 32); | 356 | voicenum = 1 << (voicenum - 32); |
| @@ -370,7 +368,6 @@ void snd_emu10k1_voice_half_loop_intr_enable(struct snd_emu10k1 *emu, unsigned i · 11 unmodified lines | |||
| 370 | unsigned int val; | 368 | unsigned int val; |
| 371 | 369 | ||
| 372 | spin_lock_irqsave(&emu->emu_lock, flags); | 370 | spin_lock_irqsave(&emu->emu_lock, flags); |
| 373 | /* voice interrupt */ | ||
| 374 | if (voicenum >= 32) { | 371 | if (voicenum >= 32) { |
| 375 | outl(HLIEH << 16, emu->port + PTR); | 372 | outl(HLIEH << 16, emu->port + PTR); |
| 376 | val = inl(emu->port + DATA); | 373 | val = inl(emu->port + DATA); |
| @@ -390,7 +387,6 @@ void snd_emu10k1_voice_half_loop_intr_disable(struct snd_emu10k1 *emu, unsigned · 13 unmodified lines | |||
| 390 | unsigned int val; | 387 | unsigned int val; |
| 391 | 388 | ||
| 392 | spin_lock_irqsave(&emu->emu_lock, flags); | 389 | spin_lock_irqsave(&emu->emu_lock, flags); |
| 393 | /* voice interrupt */ | ||
| 394 | if (voicenum >= 32) { | 390 | if (voicenum >= 32) { |
| 395 | outl(HLIEH << 16, emu->port + PTR); | 391 | outl(HLIEH << 16, emu->port + PTR); |
| 396 | val = inl(emu->port + DATA); | 392 | val = inl(emu->port + DATA); |
| @@ -409,7 +405,6 @@ void snd_emu10k1_voice_half_loop_intr_ack(struct snd_emu10k1 *emu, unsigned int · 12 unmodified lines | |||
| 409 | unsigned long flags; | 405 | unsigned long flags; |
| 410 | 406 | ||
| 411 | spin_lock_irqsave(&emu->emu_lock, flags); | 407 | spin_lock_irqsave(&emu->emu_lock, flags); |
| 412 | /* voice interrupt */ | ||
| 413 | if (voicenum >= 32) { | 408 | if (voicenum >= 32) { |
| 414 | outl(HLIPH << 16, emu->port + PTR); | 409 | outl(HLIPH << 16, emu->port + PTR); |
| 415 | voicenum = 1 << (voicenum - 32); | 410 | voicenum = 1 << (voicenum - 32); |
| @@ -427,7 +422,6 @@ void snd_emu10k1_voice_set_loop_stop(struct snd_emu10k1 *emu, unsigned int voice · 11 unmodified lines | |||
| 427 | unsigned int sol; | 422 | unsigned int sol; |
| 428 | 423 | ||
| 429 | spin_lock_irqsave(&emu->emu_lock, flags); | 424 | spin_lock_irqsave(&emu->emu_lock, flags); |
| 430 | /* voice interrupt */ | ||
| 431 | if (voicenum >= 32) { | 425 | if (voicenum >= 32) { |
| 432 | outl(SOLEH << 16, emu->port + PTR); | 426 | outl(SOLEH << 16, emu->port + PTR); |
| 433 | sol = inl(emu->port + DATA); | 427 | sol = inl(emu->port + DATA); |
| @@ -447,7 +441,6 @@ void snd_emu10k1_voice_clear_loop_stop(struct snd_emu10k1 *emu, unsigned int voi · 13 unmodified lines | |||
| 447 | unsigned int sol; | 441 | unsigned int sol; |
| 448 | 442 | ||
| 449 | spin_lock_irqsave(&emu->emu_lock, flags); | 443 | spin_lock_irqsave(&emu->emu_lock, flags); |
| 450 | /* voice interrupt */ | ||
| 451 | if (voicenum >= 32) { | 444 | if (voicenum >= 32) { |
| 452 | outl(SOLEH << 16, emu->port + PTR); | 445 | outl(SOLEH << 16, emu->port + PTR); |
| 453 | sol = inl(emu->port + DATA); | 446 | sol = inl(emu->port + DATA); |
| @@ -18,7 +18,7 @@ · 17 unmodified lines | |||
| 18 | irqreturn_t snd_emu10k1_interrupt(int irq, void *dev_id) | 18 | irqreturn_t snd_emu10k1_interrupt(int irq, void *dev_id) |
| 19 | { | 19 | { |
| 20 | struct snd_emu10k1 *emu = dev_id; | 20 | struct snd_emu10k1 *emu = dev_id; |
| 21 | unsigned int status, status2, orig_status, orig_status2; | 21 | unsigned int status, orig_status; |
| 22 | int handled = 0; | 22 | int handled = 0; |
| 23 | int timeout = 0; | 23 | int timeout = 0; |
| 24 | 24 | ||
| @@ -139,32 +139,10 @@ irqreturn_t snd_emu10k1_interrupt(int irq, void *dev_id) · 114 unmodified lines | |||
| 139 | status &= ~IPR_FXDSP; | 139 | status &= ~IPR_FXDSP; |
| 140 | } | 140 | } |
| 141 | if (status & IPR_P16V) { | 141 | if (status & IPR_P16V) { |
| 142 | while ((status2 = inl(emu->port + IPR2)) != 0) { | 142 | if (emu->p16v_interrupt) |
| 143 | u32 mask = INTE2_PLAYBACK_CH_0_LOOP; /* Full Loop */ | 143 | emu->p16v_interrupt(emu); |
| 144 | struct snd_emu10k1_voice *pvoice = &(emu->p16v_voices[0]); | 144 | else |
| 145 | struct snd_emu10k1_voice *cvoice = &(emu->p16v_capture_voice); | 145 | outl(0, emu->port + INTE2); |
| 146 | |||
| 147 | /* dev_dbg(emu->card->dev, "status2=0x%x\n", status2); */ | ||
| 148 | orig_status2 = status2; | ||
| 149 | if(status2 & mask) { | ||
| 150 | if(pvoice->use) { | ||
| 151 | snd_pcm_period_elapsed(pvoice->epcm->substream); | ||
| 152 | } else { | ||
| 153 | dev_err(emu->card->dev, | ||
| 154 | "p16v: status: 0x%08x, mask=0x%08x, pvoice=%p, use=%d\n", | ||
| 155 | status2, mask, pvoice, | ||
| 156 | pvoice->use); | ||
| 157 | } | ||
| 158 | } | ||
| 159 | if(status2 & 0x110000) { | ||
| 160 | /* dev_info(emu->card->dev, "capture int found\n"); */ | ||
| 161 | if(cvoice->use) { | ||
| 162 | /* dev_info(emu->card->dev, "capture period_elapsed\n"); */ | ||
| 163 | snd_pcm_period_elapsed(cvoice->epcm->substream); | ||
| 164 | } | ||
| 165 | } | ||
| 166 | outl(orig_status2, emu->port + IPR2); /* ack all */ | ||
| 167 | } | ||
| 168 | status &= ~IPR_P16V; | 146 | status &= ~IPR_P16V; |
| 169 | } | 147 | } |
| 170 | 148 | ||
| @@ -149,42 +149,19 @@ static const struct snd_pcm_hardware snd_p16v_capture_hw = { · 148 unmodified lines | |||
| 149 | .fifo_size = 0, | 149 | .fifo_size = 0, |
| 150 | }; | 150 | }; |
| 151 | 151 | ||
| 152 | static void snd_p16v_pcm_free_substream(struct snd_pcm_runtime *runtime) | ||
| 153 | { | ||
| 154 | struct snd_emu10k1_pcm *epcm = runtime->private_data; | ||
| 155 | |||
| 156 | kfree(epcm); | ||
| 157 | } | ||
| 158 | |||
| 159 | /* open_playback callback */ | 152 | /* open_playback callback */ |
| 160 | static int snd_p16v_pcm_open_playback_channel(struct snd_pcm_substream *substream, int channel_id) | 153 | static int snd_p16v_pcm_open_playback_channel(struct snd_pcm_substream *substream, int channel_id) |
| 161 | { | 154 | { |
| 162 | struct snd_emu10k1 *emu = snd_pcm_substream_chip(substream); | ||
| 163 | struct snd_emu10k1_voice *channel = &(emu->p16v_voices[channel_id]); | ||
| 164 | struct snd_emu10k1_pcm *epcm; | ||
| 165 | struct snd_pcm_runtime *runtime = substream->runtime; | 155 | struct snd_pcm_runtime *runtime = substream->runtime; |
| 166 | int err; | 156 | int err; |
| 167 | 157 | ||
| 168 | epcm = kzalloc(sizeof(*epcm), GFP_KERNEL); | ||
| 169 | /* dev_dbg(emu->card->dev, "epcm kcalloc: %p\n", epcm); */ | ||
| 170 | |||
| 171 | if (epcm == NULL) | ||
| 172 | return -ENOMEM; | ||
| 173 | epcm->emu = emu; | ||
| 174 | epcm->substream = substream; | ||
| 175 | /* | 158 | /* |
| 176 | dev_dbg(emu->card->dev, "epcm device=%d, channel_id=%d\n", | 159 | dev_dbg(emu->card->dev, "epcm device=%d, channel_id=%d\n", |
| 177 | substream->pcm->device, channel_id); | 160 | substream->pcm->device, channel_id); |
| 178 | */ | 161 | */ |
| 179 | runtime->private_data = epcm; | ||
| 180 | runtime->private_free = snd_p16v_pcm_free_substream; | ||
| 181 | 162 | ||
| 182 | runtime->hw = snd_p16v_playback_hw; | 163 | runtime->hw = snd_p16v_playback_hw; |
| 183 | 164 | ||
| 184 | channel->emu = emu; | ||
| 185 | channel->number = channel_id; | ||
| 186 | |||
| 187 | channel->use=1; | ||
| 188 | #if 0 /* debug */ | 165 | #if 0 /* debug */ |
| 189 | dev_dbg(emu->card->dev, | 166 | dev_dbg(emu->card->dev, |
| 190 | "p16v: open channel_id=%d, channel=%p, use=0x%x\n", | 167 | "p16v: open channel_id=%d, channel=%p, use=0x%x\n", |
| @@ -193,7 +170,6 @@ static int snd_p16v_pcm_open_playback_channel(struct snd_pcm_substream *substrea · 2 unmodified lines | |||
| 193 | channel_id, chip, channel); | 170 | channel_id, chip, channel); |
| 194 | #endif /* debug */ | 171 | #endif /* debug */ |
| 195 | /* channel->interrupt = snd_p16v_pcm_channel_interrupt; */ | 172 | /* channel->interrupt = snd_p16v_pcm_channel_interrupt; */ |
| 196 | channel->epcm = epcm; | ||
| 197 | err = snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS); | 173 | err = snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS); |
| 198 | if (err < 0) | 174 | if (err < 0) |
| 199 | return err; | 175 | return err; |
| @@ -205,44 +181,20 @@ static int snd_p16v_pcm_open_playback_channel(struct snd_pcm_substream *substrea · 5 unmodified lines | |||
| 205 | 181 | ||
| 206 | return 0; | 182 | return 0; |
| 207 | } | 183 | } |
| 184 | |||
| 208 | /* open_capture callback */ | 185 | /* open_capture callback */ |
| 209 | static int snd_p16v_pcm_open_capture_channel(struct snd_pcm_substream *substream, int channel_id) | 186 | static int snd_p16v_pcm_open_capture_channel(struct snd_pcm_substream *substream, int channel_id) |
| 210 | { | 187 | { |
| 211 | struct snd_emu10k1 *emu = snd_pcm_substream_chip(substream); | ||
| 212 | struct snd_emu10k1_voice *channel = &(emu->p16v_capture_voice); | ||
| 213 | struct snd_emu10k1_pcm *epcm; | ||
| 214 | struct snd_pcm_runtime *runtime = substream->runtime; | 188 | struct snd_pcm_runtime *runtime = substream->runtime; |
| 215 | int err; | 189 | int err; |
| 216 | 190 | ||
| 217 | epcm = kzalloc(sizeof(*epcm), GFP_KERNEL); | ||
| 218 | /* dev_dbg(emu->card->dev, "epcm kcalloc: %p\n", epcm); */ | ||
| 219 | |||
| 220 | if (epcm == NULL) | ||
| 221 | return -ENOMEM; | ||
| 222 | epcm->emu = emu; | ||
| 223 | epcm->substream = substream; | ||
| 224 | /* | 191 | /* |
| 225 | dev_dbg(emu->card->dev, "epcm device=%d, channel_id=%d\n", | 192 | dev_dbg(emu->card->dev, "epcm device=%d, channel_id=%d\n", |
| 226 | substream->pcm->device, channel_id); | 193 | substream->pcm->device, channel_id); |
| 227 | */ | 194 | */ |
| 228 | runtime->private_data = epcm; | ||
| 229 | runtime->private_free = snd_p16v_pcm_free_substream; | ||
| 230 | 195 | ||
| 231 | runtime->hw = snd_p16v_capture_hw; | 196 | runtime->hw = snd_p16v_capture_hw; |
| 232 | 197 | ||
| 233 | channel->emu = emu; | ||
| 234 | channel->number = channel_id; | ||
| 235 | |||
| 236 | channel->use=1; | ||
| 237 | #if 0 /* debug */ | ||
| 238 | dev_dbg(emu->card->dev, | ||
| 239 | "p16v: open channel_id=%d, channel=%p, use=0x%x\n", | ||
| 240 | channel_id, channel, channel->use); | ||
| 241 | dev_dbg(emu->card->dev, "open:channel_id=%d, chip=%p, channel=%p\n", | ||
| 242 | channel_id, chip, channel); | ||
| 243 | #endif /* debug */ | ||
| 244 | /* channel->interrupt = snd_p16v_pcm_channel_interrupt; */ | ||
| 245 | channel->epcm = epcm; | ||
| 246 | err = snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS); | 198 | err = snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS); |
| 247 | if (err < 0) | 199 | if (err < 0) |
| 248 | return err; | 200 | return err; |
| @@ -254,22 +206,12 @@ static int snd_p16v_pcm_open_capture_channel(struct snd_pcm_substream *substream · 5 unmodified lines | |||
| 254 | /* close callback */ | 206 | /* close callback */ |
| 255 | static int snd_p16v_pcm_close_playback(struct snd_pcm_substream *substream) | 207 | static int snd_p16v_pcm_close_playback(struct snd_pcm_substream *substream) |
| 256 | { | 208 | { |
| 257 | struct snd_emu10k1 *emu = snd_pcm_substream_chip(substream); | ||
| 258 | //struct snd_pcm_runtime *runtime = substream->runtime; | ||
| 259 | //struct snd_emu10k1_pcm *epcm = runtime->private_data; | ||
| 260 | emu->p16v_voices[substream->pcm->device - emu->p16v_device_offset].use = 0; | ||
| 261 | /* FIXME: maybe zero others */ | ||
| 262 | return 0; | 209 | return 0; |
| 263 | } | 210 | } |
| 264 | 211 | ||
| 265 | /* close callback */ | 212 | /* close callback */ |
| 266 | static int snd_p16v_pcm_close_capture(struct snd_pcm_substream *substream) | 213 | static int snd_p16v_pcm_close_capture(struct snd_pcm_substream *substream) |
| 267 | { | 214 | { |
| 268 | struct snd_emu10k1 *emu = snd_pcm_substream_chip(substream); | ||
| 269 | //struct snd_pcm_runtime *runtime = substream->runtime; | ||
| 270 | //struct snd_emu10k1_pcm *epcm = runtime->private_data; | ||
| 271 | emu->p16v_capture_voice.use = 0; | ||
| 272 | /* FIXME: maybe zero others */ | ||
| 273 | return 0; | 215 | return 0; |
| 274 | } | 216 | } |
| 275 | 217 | ||
| @@ -411,13 +353,48 @@ static void snd_p16v_intr_disable(struct snd_emu10k1 *emu, unsigned int intrenb) · 135 unmodified lines | |||
| 411 | spin_unlock_irqrestore(&emu->emu_lock, flags); | 353 | spin_unlock_irqrestore(&emu->emu_lock, flags); |
| 412 | } | 354 | } |
| 413 | 355 | ||
| 356 | static void snd_p16v_interrupt(struct snd_emu10k1 *emu) | ||
| 357 | { | ||
| 358 | unsigned int status; | ||
| 359 | |||
| 360 | while ((status = inl(emu->port + IPR2)) != 0) { | ||
| 361 | u32 mask = INTE2_PLAYBACK_CH_0_LOOP; /* Full Loop */ | ||
| 362 | |||
| 363 | /* dev_dbg(emu->card->dev, "p16v status=0x%x\n", status); */ | ||
| 364 | if (status & mask) { | ||
| 365 | struct snd_pcm_substream *substream = | ||
| 366 | emu->pcm_p16v->streams[SNDRV_PCM_STREAM_PLAYBACK].substream; | ||
| 367 | struct snd_pcm_runtime *runtime = substream->runtime; | ||
| 368 | |||
| 369 | if (runtime && runtime->private_data) { | ||
| 370 | snd_pcm_period_elapsed(substream); | ||
| 371 | } else { | ||
| 372 | dev_err(emu->card->dev, | ||
| 373 | "p16v: status: 0x%08x, mask=0x%08x\n", | ||
| 374 | status, mask); | ||
| 375 | } | ||
| 376 | } | ||
| 377 | if (status & 0x110000) { | ||
| 378 | struct snd_pcm_substream *substream = | ||
| 379 | emu->pcm_p16v->streams[SNDRV_PCM_STREAM_CAPTURE].substream; | ||
| 380 | struct snd_pcm_runtime *runtime = substream->runtime; | ||
| 381 | |||
| 382 | /* dev_info(emu->card->dev, "capture int found\n"); */ | ||
| 383 | if (runtime && runtime->private_data) { | ||
| 384 | /* dev_info(emu->card->dev, "capture period_elapsed\n"); */ | ||
| 385 | snd_pcm_period_elapsed(substream); | ||
| 386 | } | ||
| 387 | } | ||
| 388 | outl(status, emu->port + IPR2); /* ack all */ | ||
| 389 | } | ||
| 390 | } | ||
| 391 | |||
| 414 | /* trigger_playback callback */ | 392 | /* trigger_playback callback */ |
| 415 | static int snd_p16v_pcm_trigger_playback(struct snd_pcm_substream *substream, | 393 | static int snd_p16v_pcm_trigger_playback(struct snd_pcm_substream *substream, |
| 416 | int cmd) | 394 | int cmd) |
| 417 | { | 395 | { |
| 418 | struct snd_emu10k1 *emu = snd_pcm_substream_chip(substream); | 396 | struct snd_emu10k1 *emu = snd_pcm_substream_chip(substream); |
| 419 | struct snd_pcm_runtime *runtime; | 397 | struct snd_pcm_runtime *runtime; |
| 420 | struct snd_emu10k1_pcm *epcm; | ||
| 421 | int channel; | 398 | int channel; |
| 422 | int result = 0; | 399 | int result = 0; |
| 423 | struct snd_pcm_substream *s; | 400 | struct snd_pcm_substream *s; |
| @@ -439,10 +416,9 @@ static int snd_p16v_pcm_trigger_playback(struct snd_pcm_substream *substream, · 15 unmodified lines | |||
| 439 | s->stream != SNDRV_PCM_STREAM_PLAYBACK) | 416 | s->stream != SNDRV_PCM_STREAM_PLAYBACK) |
| 440 | continue; | 417 | continue; |
| 441 | runtime = s->runtime; | 418 | runtime = s->runtime; |
| 442 | epcm = runtime->private_data; | ||
| 443 | channel = substream->pcm->device-emu->p16v_device_offset; | 419 | channel = substream->pcm->device-emu->p16v_device_offset; |
| 444 | /* dev_dbg(emu->card->dev, "p16v channel=%d\n", channel); */ | 420 | /* dev_dbg(emu->card->dev, "p16v channel=%d\n", channel); */ |
| 445 | epcm->running = running; | 421 | runtime->private_data = (void *)(ptrdiff_t)running; |
| 446 | basic |= (0x1<<channel); | 422 | basic |= (0x1<<channel); |
| 447 | inte |= (INTE2_PLAYBACK_CH_0_LOOP<<channel); | 423 | inte |= (INTE2_PLAYBACK_CH_0_LOOP<<channel); |
| 448 | snd_pcm_trigger_done(s, substream); | 424 | snd_pcm_trigger_done(s, substream); |
| @@ -471,7 +447,6 @@ static int snd_p16v_pcm_trigger_capture(struct snd_pcm_substream *substream, · 22 unmodified lines | |||
| 471 | { | 447 | { |
| 472 | struct snd_emu10k1 *emu = snd_pcm_substream_chip(substream); | 448 | struct snd_emu10k1 *emu = snd_pcm_substream_chip(substream); |
| 473 | struct snd_pcm_runtime *runtime = substream->runtime; | 449 | struct snd_pcm_runtime *runtime = substream->runtime; |
| 474 | struct snd_emu10k1_pcm *epcm = runtime->private_data; | ||
| 475 | int channel = 0; | 450 | int channel = 0; |
| 476 | int result = 0; | 451 | int result = 0; |
| 477 | u32 inte = INTE2_CAPTURE_CH_0_LOOP | INTE2_CAPTURE_CH_0_HALF_LOOP; | 452 | u32 inte = INTE2_CAPTURE_CH_0_LOOP | INTE2_CAPTURE_CH_0_HALF_LOOP; |
| @@ -480,13 +455,13 @@ static int snd_p16v_pcm_trigger_capture(struct snd_pcm_substream *substream, · 2 unmodified lines | |||
| 480 | case SNDRV_PCM_TRIGGER_START: | 455 | case SNDRV_PCM_TRIGGER_START: |
| 481 | snd_p16v_intr_enable(emu, inte); | 456 | snd_p16v_intr_enable(emu, inte); |
| 482 | snd_emu10k1_ptr20_write(emu, BASIC_INTERRUPT, 0, snd_emu10k1_ptr20_read(emu, BASIC_INTERRUPT, 0)|(0x100<<channel)); | 457 | snd_emu10k1_ptr20_write(emu, BASIC_INTERRUPT, 0, snd_emu10k1_ptr20_read(emu, BASIC_INTERRUPT, 0)|(0x100<<channel)); |
| 483 | epcm->running = 1; | 458 | runtime->private_data = (void *)1; |
| 484 | break; | 459 | break; |
| 485 | case SNDRV_PCM_TRIGGER_STOP: | 460 | case SNDRV_PCM_TRIGGER_STOP: |
| 486 | snd_emu10k1_ptr20_write(emu, BASIC_INTERRUPT, 0, snd_emu10k1_ptr20_read(emu, BASIC_INTERRUPT, 0) & ~(0x100<<channel)); | 461 | snd_emu10k1_ptr20_write(emu, BASIC_INTERRUPT, 0, snd_emu10k1_ptr20_read(emu, BASIC_INTERRUPT, 0) & ~(0x100<<channel)); |
| 487 | snd_p16v_intr_disable(emu, inte); | 462 | snd_p16v_intr_disable(emu, inte); |
| 488 | //snd_emu10k1_ptr20_write(emu, EXTENDED_INT_MASK, 0, snd_emu10k1_ptr20_read(emu, EXTENDED_INT_MASK, 0) & ~(0x110000<<channel)); | 463 | //snd_emu10k1_ptr20_write(emu, EXTENDED_INT_MASK, 0, snd_emu10k1_ptr20_read(emu, EXTENDED_INT_MASK, 0) & ~(0x110000<<channel)); |
| 489 | epcm->running = 0; | 464 | runtime->private_data = NULL; |
| 490 | break; | 465 | break; |
| 491 | default: | 466 | default: |
| 492 | result = -EINVAL; | 467 | result = -EINVAL; |
| @@ -501,10 +476,10 @@ snd_p16v_pcm_pointer_playback(struct snd_pcm_substream *substream) · 8 unmodified lines | |||
| 501 | { | 476 | { |
| 502 | struct snd_emu10k1 *emu = snd_pcm_substream_chip(substream); | 477 | struct snd_emu10k1 *emu = snd_pcm_substream_chip(substream); |
| 503 | struct snd_pcm_runtime *runtime = substream->runtime; | 478 | struct snd_pcm_runtime *runtime = substream->runtime; |
| 504 | struct snd_emu10k1_pcm *epcm = runtime->private_data; | ||
| 505 | snd_pcm_uframes_t ptr, ptr1, ptr2,ptr3,ptr4 = 0; | 479 | snd_pcm_uframes_t ptr, ptr1, ptr2,ptr3,ptr4 = 0; |
| 506 | int channel = substream->pcm->device - emu->p16v_device_offset; | 480 | int channel = substream->pcm->device - emu->p16v_device_offset; |
| 507 | if (!epcm->running) | 481 | |
| 482 | if (!runtime->private_data) | ||
| 508 | return 0; | 483 | return 0; |
| 509 | 484 | ||
| 510 | ptr3 = snd_emu10k1_ptr20_read(emu, PLAYBACK_LIST_PTR, channel); | 485 | ptr3 = snd_emu10k1_ptr20_read(emu, PLAYBACK_LIST_PTR, channel); |
| @@ -526,11 +501,10 @@ snd_p16v_pcm_pointer_capture(struct snd_pcm_substream *substream) · 15 unmodified lines | |||
| 526 | { | 501 | { |
| 527 | struct snd_emu10k1 *emu = snd_pcm_substream_chip(substream); | 502 | struct snd_emu10k1 *emu = snd_pcm_substream_chip(substream); |
| 528 | struct snd_pcm_runtime *runtime = substream->runtime; | 503 | struct snd_pcm_runtime *runtime = substream->runtime; |
| 529 | struct snd_emu10k1_pcm *epcm = runtime->private_data; | ||
| 530 | snd_pcm_uframes_t ptr, ptr1, ptr2 = 0; | 504 | snd_pcm_uframes_t ptr, ptr1, ptr2 = 0; |
| 531 | int channel = 0; | 505 | int channel = 0; |
| 532 | 506 | ||
| 533 | if (!epcm->running) | 507 | if (!runtime->private_data) |
| 534 | return 0; | 508 | return 0; |
| 535 | 509 | ||
| 536 | ptr1 = snd_emu10k1_ptr20_read(emu, CAPTURE_POINTER, channel); | 510 | ptr1 = snd_emu10k1_ptr20_read(emu, CAPTURE_POINTER, channel); |
| @@ -591,6 +565,7 @@ int snd_p16v_pcm(struct snd_emu10k1 *emu, int device) · 54 unmodified lines | |||
| 591 | pcm->dev_subclass = SNDRV_PCM_SUBCLASS_GENERIC_MIX; | 565 | pcm->dev_subclass = SNDRV_PCM_SUBCLASS_GENERIC_MIX; |
| 592 | strcpy(pcm->name, "p16v"); | 566 | strcpy(pcm->name, "p16v"); |
| 593 | emu->pcm_p16v = pcm; | 567 | emu->pcm_p16v = pcm; |
| 568 | emu->p16v_interrupt = snd_p16v_interrupt; | ||
| 594 | 569 | ||
| 595 | for(substream = pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream; | 570 | for(substream = pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream; |
| 596 | substream; | 571 | substream; |
| @@ -64,7 +64,7 @@ · 63 unmodified lines | |||
| 64 | */ | 64 | */ |
| 65 | 65 | ||
| 66 | /********************************************************************************************************/ | 66 | /********************************************************************************************************/ |
| 67 | /* Audigy2 P16V pointer-offset register set, accessed through the PTR2 and DATA2 registers */ | 67 | /* Audigy2 P16V pointer-offset register set, accessed through the PTR2 and DATA2 registers */ |
| 68 | /********************************************************************************************************/ | 68 | /********************************************************************************************************/ |
| 69 | 69 | ||
| 70 | /* The sample rate of the SPDIF outputs is set by modifying a register in the EMU10K2 PTR register A_SPDIF_SAMPLERATE. | 70 | /* The sample rate of the SPDIF outputs is set by modifying a register in the EMU10K2 PTR register A_SPDIF_SAMPLERATE. |
| @@ -6,8 +6,8 @@ · 5 unmodified lines | |||
| 6 | */ | 6 | */ |
| 7 | 7 | ||
| 8 | /******************************************************************************/ | 8 | /******************************************************************************/ |
| 9 | /* Audigy2Value Tina (P17V) pointer-offset register set, | 9 | /* Audigy2Value Tina (P17V) pointer-offset register set, */ |
| 10 | * accessed through the PTR20 and DATA24 registers */ | 10 | /* accessed through the PTR2 and DATA2 registers */ |
| 11 | /******************************************************************************/ | 11 | /******************************************************************************/ |
| 12 | 12 | ||
| 13 | /* 00 - 07: Not used */ | 13 | /* 00 - 07: Not used */ |
| @@ -514,13 +514,13 @@ static void cs35l41_hda_playback_hook(struct device *dev, int action) · 513 unmodified lines | |||
| 514 | break; | 514 | break; |
| 515 | case HDA_GEN_PCM_ACT_PREPARE: | 515 | case HDA_GEN_PCM_ACT_PREPARE: |
| 516 | mutex_lock(&cs35l41->fw_mutex); | 516 | mutex_lock(&cs35l41->fw_mutex); |
| 517 | ret = cs35l41_global_enable(reg, cs35l41->hw_cfg.bst_type, 1); | 517 | ret = cs35l41_global_enable(reg, cs35l41->hw_cfg.bst_type, 1, NULL); |
| 518 | mutex_unlock(&cs35l41->fw_mutex); | 518 | mutex_unlock(&cs35l41->fw_mutex); |
| 519 | break; | 519 | break; |
| 520 | case HDA_GEN_PCM_ACT_CLEANUP: | 520 | case HDA_GEN_PCM_ACT_CLEANUP: |
| 521 | mutex_lock(&cs35l41->fw_mutex); | 521 | mutex_lock(&cs35l41->fw_mutex); |
| 522 | regmap_multi_reg_write(reg, cs35l41_hda_mute, ARRAY_SIZE(cs35l41_hda_mute)); | 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); | 523 | ret = cs35l41_global_enable(reg, cs35l41->hw_cfg.bst_type, 0, NULL); |
| 524 | mutex_unlock(&cs35l41->fw_mutex); | 524 | mutex_unlock(&cs35l41->fw_mutex); |
| 525 | break; | 525 | break; |
| 526 | case HDA_GEN_PCM_ACT_CLOSE: | 526 | case HDA_GEN_PCM_ACT_CLOSE: |
| @@ -672,7 +672,7 @@ static int cs35l41_runtime_suspend(struct device *dev) · 145 unmodified lines | |||
| 672 | if (cs35l41->playback_started) { | 672 | if (cs35l41->playback_started) { |
| 673 | regmap_multi_reg_write(cs35l41->regmap, cs35l41_hda_mute, | 673 | regmap_multi_reg_write(cs35l41->regmap, cs35l41_hda_mute, |
| 674 | ARRAY_SIZE(cs35l41_hda_mute)); | 674 | ARRAY_SIZE(cs35l41_hda_mute)); |
| 675 | cs35l41_global_enable(cs35l41->regmap, cs35l41->hw_cfg.bst_type, 0); | 675 | cs35l41_global_enable(cs35l41->regmap, cs35l41->hw_cfg.bst_type, 0, NULL); |
| 676 | regmap_update_bits(cs35l41->regmap, CS35L41_PWR_CTRL2, | 676 | regmap_update_bits(cs35l41->regmap, CS35L41_PWR_CTRL2, |
| 677 | CS35L41_AMP_EN_MASK, 0 << CS35L41_AMP_EN_SHIFT); | 677 | CS35L41_AMP_EN_MASK, 0 << CS35L41_AMP_EN_SHIFT); |
| 678 | if (cs35l41->hw_cfg.bst_type == CS35L41_EXT_BOOST) | 678 | if (cs35l41->hw_cfg.bst_type == CS35L41_EXT_BOOST) |
| @@ -2528,6 +2528,9 @@ static const struct pci_device_id azx_ids[] = { · 2527 unmodified lines | |||
| 2528 | /* Meteorlake-P */ | 2528 | /* Meteorlake-P */ |
| 2529 | { PCI_DEVICE(0x8086, 0x7e28), | 2529 | { PCI_DEVICE(0x8086, 0x7e28), |
| 2530 | .driver_data = AZX_DRIVER_SKL | AZX_DCAPS_INTEL_SKYLAKE}, | 2530 | .driver_data = AZX_DRIVER_SKL | AZX_DCAPS_INTEL_SKYLAKE}, |
| 2531 | /* Lunarlake-P */ | ||
| 2532 | { PCI_DEVICE(0x8086, 0xa828), | ||
| 2533 | .driver_data = AZX_DRIVER_SKL | AZX_DCAPS_INTEL_SKYLAKE}, | ||
| 2531 | /* Broxton-P(Apollolake) */ | 2534 | /* Broxton-P(Apollolake) */ |
| 2532 | { PCI_DEVICE(0x8086, 0x5a98), | 2535 | { PCI_DEVICE(0x8086, 0x5a98), |
| 2533 | .driver_data = AZX_DRIVER_SKL | AZX_DCAPS_INTEL_BROXTON }, | 2536 | .driver_data = AZX_DRIVER_SKL | AZX_DCAPS_INTEL_BROXTON }, |
| @@ -580,12 +580,10 @@ static void hda_tegra_probe_work(struct work_struct *work) · 579 unmodified lines | |||
| 580 | return; /* no error return from async probe */ | 580 | return; /* no error return from async probe */ |
| 581 | } | 581 | } |
| 582 | 582 | ||
| 583 | static int hda_tegra_remove(struct platform_device *pdev) | 583 | static void hda_tegra_remove(struct platform_device *pdev) |
| 584 | { | 584 | { |
| 585 | snd_card_free(dev_get_drvdata(&pdev->dev)); | 585 | snd_card_free(dev_get_drvdata(&pdev->dev)); |
| 586 | pm_runtime_disable(&pdev->dev); | 586 | pm_runtime_disable(&pdev->dev); |
| 587 | |||
| 588 | return 0; | ||
| 589 | } | 587 | } |
| 590 | 588 | ||
| 591 | static void hda_tegra_shutdown(struct platform_device *pdev) | 589 | static void hda_tegra_shutdown(struct platform_device *pdev) |
| @@ -607,7 +605,7 @@ static struct platform_driver tegra_platform_hda = { · 15 unmodified lines | |||
| 607 | .of_match_table = hda_tegra_match, | 605 | .of_match_table = hda_tegra_match, |
| 608 | }, | 606 | }, |
| 609 | .probe = hda_tegra_probe, | 607 | .probe = hda_tegra_probe, |
| 610 | .remove = hda_tegra_remove, | 608 | .remove_new = hda_tegra_remove, |
| 611 | .shutdown = hda_tegra_shutdown, | 609 | .shutdown = hda_tegra_shutdown, |
| 612 | }; | 610 | }; |
| 613 | module_platform_driver(tegra_platform_hda); | 611 | module_platform_driver(tegra_platform_hda); |
| @@ -2104,10 +2104,6 @@ static int generic_hdmi_playback_pcm_prepare(struct hda_pcm_stream *hinfo, · 2103 unmodified lines | |||
| 2104 | goto unlock; | 2104 | goto unlock; |
| 2105 | } | 2105 | } |
| 2106 | 2106 | ||
| 2107 | if (snd_BUG_ON(pin_idx < 0)) { | ||
| 2108 | err = -EINVAL; | ||
| 2109 | goto unlock; | ||
| 2110 | } | ||
| 2111 | per_pin = get_pin(spec, pin_idx); | 2107 | per_pin = get_pin(spec, pin_idx); |
| 2112 | 2108 | ||
| 2113 | /* Verify pin:cvt selections to avoid silent audio after S3. | 2109 | /* Verify pin:cvt selections to avoid silent audio after S3. |
| @@ -2199,13 +2195,13 @@ static int hdmi_pcm_close(struct hda_pcm_stream *hinfo, · 85 unmodified lines | |||
| 2199 | snd_hda_spdif_ctls_unassign(codec, pcm_idx); | 2195 | snd_hda_spdif_ctls_unassign(codec, pcm_idx); |
| 2200 | clear_bit(pcm_idx, &spec->pcm_in_use); | 2196 | clear_bit(pcm_idx, &spec->pcm_in_use); |
| 2201 | pin_idx = hinfo_to_pin_index(codec, hinfo); | 2197 | pin_idx = hinfo_to_pin_index(codec, hinfo); |
| 2198 | /* | ||
| 2199 | * In such a case, return 0 to match the behavior in | ||
| 2200 | * hdmi_pcm_open() | ||
| 2201 | */ | ||
| 2202 | if (pin_idx < 0) | 2202 | if (pin_idx < 0) |
| 2203 | goto unlock; | 2203 | goto unlock; |
| 2204 | 2204 | ||
| 2205 | if (snd_BUG_ON(pin_idx < 0)) { | ||
| 2206 | err = -EINVAL; | ||
| 2207 | goto unlock; | ||
| 2208 | } | ||
| 2209 | per_pin = get_pin(spec, pin_idx); | 2205 | per_pin = get_pin(spec, pin_idx); |
| 2210 | 2206 | ||
| 2211 | if (spec->dyn_pin_out) { | 2207 | if (spec->dyn_pin_out) { |
| @@ -6146,12 +6146,6 @@ static int snd_hdspm_hwdep_dummy_op(struct snd_hwdep *hw, struct file *file) · 6145 unmodified lines | |||
| 6146 | return 0; | 6146 | return 0; |
| 6147 | } | 6147 | } |
| 6148 | 6148 | ||
| 6149 | static inline int copy_u32_le(void __user *dest, void __iomem *src) | ||
| 6150 | { | ||
| 6151 | u32 val = readl(src); | ||
| 6152 | return copy_to_user(dest, &val, 4); | ||
| 6153 | } | ||
| 6154 | |||
| 6155 | static int snd_hdspm_hwdep_ioctl(struct snd_hwdep *hw, struct file *file, | 6149 | static int snd_hdspm_hwdep_ioctl(struct snd_hwdep *hw, struct file *file, |
| 6156 | unsigned int cmd, unsigned long arg) | 6150 | unsigned int cmd, unsigned long arg) |
| 6157 | { | 6151 | { |
| @@ -98,8 +98,10 @@ static int snd_ymfpci_create_gameport(struct snd_ymfpci *chip, int dev, · 97 unmodified lines | |||
| 98 | case 0x204: legacy_ctrl2 |= 2 << 6; break; | 98 | case 0x204: legacy_ctrl2 |= 2 << 6; break; |
| 99 | case 0x205: legacy_ctrl2 |= 3 << 6; break; | 99 | case 0x205: legacy_ctrl2 |= 3 << 6; break; |
| 100 | default: | 100 | default: |
| 101 | dev_err(chip->card->dev, | 101 | if (io_port > 0) |
| 102 | "invalid joystick port %#x", io_port); | 102 | dev_err(chip->card->dev, |
| 103 | "The %s does not support arbitrary IO ports for the game port (requested 0x%x)\n", | ||
| 104 | chip->card->shortname, (unsigned int)io_port); | ||
| 103 | return -EINVAL; | 105 | return -EINVAL; |
| 104 | } | 106 | } |
| 105 | } | 107 | } |
| @@ -186,6 +188,13 @@ static int snd_card_ymfpci_probe(struct pci_dev *pci, · 80 unmodified lines | |||
| 186 | default: model = str = "???"; break; | 188 | default: model = str = "???"; break; |
| 187 | } | 189 | } |
| 188 | 190 | ||
| 191 | strcpy(card->driver, str); | ||
| 192 | sprintf(card->shortname, "Yamaha %s (%s)", model, str); | ||
| 193 | sprintf(card->longname, "%s at 0x%lx, irq %i", | ||
| 194 | card->shortname, | ||
| 195 | chip->reg_area_phys, | ||
| 196 | chip->irq); | ||
| 197 | |||
| 189 | legacy_ctrl = 0; | 198 | legacy_ctrl = 0; |
| 190 | legacy_ctrl2 = 0x0800; /* SBEN = 0, SMOD = 01, LAD = 0 */ | 199 | legacy_ctrl2 = 0x0800; /* SBEN = 0, SMOD = 01, LAD = 0 */ |
| 191 | 200 | ||
| @@ -218,7 +227,13 @@ static int snd_card_ymfpci_probe(struct pci_dev *pci, · 26 unmodified lines | |||
| 218 | case 0x398: legacy_ctrl2 |= 1; break; | 227 | case 0x398: legacy_ctrl2 |= 1; break; |
| 219 | case 0x3a0: legacy_ctrl2 |= 2; break; | 228 | case 0x3a0: legacy_ctrl2 |= 2; break; |
| 220 | case 0x3a8: legacy_ctrl2 |= 3; break; | 229 | case 0x3a8: legacy_ctrl2 |= 3; break; |
| 221 | default: fm_port[dev] = 0; break; | 230 | default: |
| 231 | if (fm_port[dev] > 0) | ||
| 232 | dev_err(card->dev, | ||
| 233 | "The %s does not support arbitrary IO ports for FM (requested 0x%x)\n", | ||
| 234 | card->shortname, (unsigned int)fm_port[dev]); | ||
| 235 | fm_port[dev] = 0; | ||
| 236 | break; | ||
| 222 | } | 237 | } |
| 223 | if (fm_port[dev] > 0) | 238 | if (fm_port[dev] > 0) |
| 224 | fm_res = devm_request_region(&pci->dev, fm_port[dev], | 239 | fm_res = devm_request_region(&pci->dev, fm_port[dev], |
| @@ -234,7 +249,13 @@ static int snd_card_ymfpci_probe(struct pci_dev *pci, · 9 unmodified lines | |||
| 234 | case 0x300: legacy_ctrl2 |= 1 << 4; break; | 249 | case 0x300: legacy_ctrl2 |= 1 << 4; break; |
| 235 | case 0x332: legacy_ctrl2 |= 2 << 4; break; | 250 | case 0x332: legacy_ctrl2 |= 2 << 4; break; |
| 236 | case 0x334: legacy_ctrl2 |= 3 << 4; break; | 251 | case 0x334: legacy_ctrl2 |= 3 << 4; break; |
| 237 | default: mpu_port[dev] = 0; break; | 252 | default: |
| 253 | if (mpu_port[dev] > 0) | ||
| 254 | dev_err(card->dev, | ||
| 255 | "The %s does not support arbitrary IO ports for MPU-401 (requested 0x%x)\n", | ||
| 256 | card->shortname, (unsigned int)mpu_port[dev]); | ||
| 257 | mpu_port[dev] = 0; | ||
| 258 | break; | ||
| 238 | } | 259 | } |
| 239 | if (mpu_port[dev] > 0) | 260 | if (mpu_port[dev] > 0) |
| 240 | mpu_res = devm_request_region(&pci->dev, mpu_port[dev], | 261 | mpu_res = devm_request_region(&pci->dev, mpu_port[dev], |
| @@ -257,12 +278,6 @@ static int snd_card_ymfpci_probe(struct pci_dev *pci, · 16 unmodified lines | |||
| 257 | if (err < 0) | 278 | if (err < 0) |
| 258 | return err; | 279 | return err; |
| 259 | 280 | ||
| 260 | strcpy(card->driver, str); | ||
| 261 | sprintf(card->shortname, "Yamaha %s (%s)", model, str); | ||
| 262 | sprintf(card->longname, "%s at 0x%lx, irq %i", | ||
| 263 | card->shortname, | ||
| 264 | chip->reg_area_phys, | ||
| 265 | chip->irq); | ||
| 266 | err = snd_ymfpci_pcm(chip, 0); | 281 | err = snd_ymfpci_pcm(chip, 0); |
| 267 | if (err < 0) | 282 | if (err < 0) |
| 268 | return err; | 283 | return err; |
| @@ -337,11 +352,9 @@ static struct pci_driver ymfpci_driver = { · 68 unmodified lines | |||
| 337 | .name = KBUILD_MODNAME, | 352 | .name = KBUILD_MODNAME, |
| 338 | .id_table = snd_ymfpci_ids, | 353 | .id_table = snd_ymfpci_ids, |
| 339 | .probe = snd_card_ymfpci_probe, | 354 | .probe = snd_card_ymfpci_probe, |
| 340 | #ifdef CONFIG_PM_SLEEP | ||
| 341 | .driver = { | 355 | .driver = { |
| 342 | .pm = &snd_ymfpci_pm, | 356 | .pm = pm_sleep_ptr(&snd_ymfpci_pm), |
| 343 | }, | 357 | }, |
| 344 | #endif | ||
| 345 | }; | 358 | }; |
| 346 | 359 | ||
| 347 | module_pci_driver(ymfpci_driver); | 360 | module_pci_driver(ymfpci_driver); |
| @@ -268,6 +268,49 @@ struct snd_ymfpci_pcm { · 267 unmodified lines | |||
| 268 | u32 shift; | 268 | u32 shift; |
| 269 | }; | 269 | }; |
| 270 | 270 | ||
| 271 | static const int saved_regs_index[] = { | ||
| 272 | /* spdif */ | ||
| 273 | YDSXGR_SPDIFOUTCTRL, | ||
| 274 | YDSXGR_SPDIFOUTSTATUS, | ||
| 275 | YDSXGR_SPDIFINCTRL, | ||
| 276 | /* volumes */ | ||
| 277 | YDSXGR_PRIADCLOOPVOL, | ||
| 278 | YDSXGR_NATIVEDACINVOL, | ||
| 279 | YDSXGR_NATIVEDACOUTVOL, | ||
| 280 | YDSXGR_BUF441OUTVOL, | ||
| 281 | YDSXGR_NATIVEADCINVOL, | ||
| 282 | YDSXGR_SPDIFLOOPVOL, | ||
| 283 | YDSXGR_SPDIFOUTVOL, | ||
| 284 | YDSXGR_ZVOUTVOL, | ||
| 285 | YDSXGR_LEGACYOUTVOL, | ||
| 286 | /* address bases */ | ||
| 287 | YDSXGR_PLAYCTRLBASE, | ||
| 288 | YDSXGR_RECCTRLBASE, | ||
| 289 | YDSXGR_EFFCTRLBASE, | ||
| 290 | YDSXGR_WORKBASE, | ||
| 291 | /* capture set up */ | ||
| 292 | YDSXGR_MAPOFREC, | ||
| 293 | YDSXGR_RECFORMAT, | ||
| 294 | YDSXGR_RECSLOTSR, | ||
| 295 | YDSXGR_ADCFORMAT, | ||
| 296 | YDSXGR_ADCSLOTSR, | ||
| 297 | }; | ||
| 298 | #define YDSXGR_NUM_SAVED_REGS ARRAY_SIZE(saved_regs_index) | ||
| 299 | |||
| 300 | static const int pci_saved_regs_index[] = { | ||
| 301 | /* All Chips */ | ||
| 302 | PCIR_DSXG_LEGACY, | ||
| 303 | PCIR_DSXG_ELEGACY, | ||
| 304 | /* YMF 744/754 */ | ||
| 305 | PCIR_DSXG_FMBASE, | ||
| 306 | PCIR_DSXG_SBBASE, | ||
| 307 | PCIR_DSXG_MPU401BASE, | ||
| 308 | PCIR_DSXG_JOYBASE, | ||
| 309 | }; | ||
| 310 | #define DSXG_PCI_NUM_SAVED_REGS ARRAY_SIZE(pci_saved_regs_index) | ||
| 311 | #define DSXG_PCI_NUM_SAVED_LEGACY_REGS 2 | ||
| 312 | static_assert(DSXG_PCI_NUM_SAVED_LEGACY_REGS <= DSXG_PCI_NUM_SAVED_REGS); | ||
| 313 | |||
| 271 | struct snd_ymfpci { | 314 | struct snd_ymfpci { |
| 272 | int irq; | 315 | int irq; |
| 273 | 316 | ||
| @@ -276,7 +319,7 @@ struct snd_ymfpci { · 2 unmodified lines | |||
| 276 | unsigned long reg_area_phys; | 319 | unsigned long reg_area_phys; |
| 277 | void __iomem *reg_area_virt; | 320 | void __iomem *reg_area_virt; |
| 278 | 321 | ||
| 279 | unsigned short old_legacy_ctrl; | 322 | u16 old_legacy_ctrl; |
| 280 | #ifdef SUPPORT_JOYSTICK | 323 | #ifdef SUPPORT_JOYSTICK |
| 281 | struct gameport *gameport; | 324 | struct gameport *gameport; |
| 282 | #endif | 325 | #endif |
| @@ -345,17 +388,14 @@ struct snd_ymfpci { · 62 unmodified lines | |||
| 345 | const struct firmware *dsp_microcode; | 388 | const struct firmware *dsp_microcode; |
| 346 | const struct firmware *controller_microcode; | 389 | const struct firmware *controller_microcode; |
| 347 | 390 | ||
| 348 | #ifdef CONFIG_PM_SLEEP | 391 | u32 saved_regs[YDSXGR_NUM_SAVED_REGS]; |
| 349 | u32 *saved_regs; | ||
| 350 | u32 saved_ydsxgr_mode; | 392 | u32 saved_ydsxgr_mode; |
| 351 | u16 saved_dsxg_legacy; | 393 | u16 saved_dsxg_pci_regs[DSXG_PCI_NUM_SAVED_REGS]; |
| 352 | u16 saved_dsxg_elegacy; | ||
| 353 | #endif | ||
| 354 | }; | 394 | }; |
| 355 | 395 | ||
| 356 | int snd_ymfpci_create(struct snd_card *card, | 396 | int snd_ymfpci_create(struct snd_card *card, |
| 357 | struct pci_dev *pci, | 397 | struct pci_dev *pci, |
| 358 | unsigned short old_legacy_ctrl); | 398 | u16 old_legacy_ctrl); |
| 359 | void snd_ymfpci_free_gameport(struct snd_ymfpci *chip); | 399 | void snd_ymfpci_free_gameport(struct snd_ymfpci *chip); |
| 360 | 400 | ||
| 361 | extern const struct dev_pm_ops snd_ymfpci_pm; | 401 | extern const struct dev_pm_ops snd_ymfpci_pm; |
| @@ -31,11 +31,6 @@ · 30 unmodified lines | |||
| 31 | 31 | ||
| 32 | static void snd_ymfpci_irq_wait(struct snd_ymfpci *chip); | 32 | static void snd_ymfpci_irq_wait(struct snd_ymfpci *chip); |
| 33 | 33 | ||
| 34 | static inline u8 snd_ymfpci_readb(struct snd_ymfpci *chip, u32 offset) | ||
| 35 | { | ||
| 36 | return readb(chip->reg_area_virt + offset); | ||
| 37 | } | ||
| 38 | |||
| 39 | static inline void snd_ymfpci_writeb(struct snd_ymfpci *chip, u32 offset, u8 val) | 34 | static inline void snd_ymfpci_writeb(struct snd_ymfpci *chip, u32 offset, u8 val) |
| 40 | { | 35 | { |
| 41 | writeb(val, chip->reg_area_virt + offset); | 36 | writeb(val, chip->reg_area_virt + offset); |
| @@ -2219,57 +2214,33 @@ static void snd_ymfpci_free(struct snd_card *card) · 2177 unmodified lines | |||
| 2219 | 2214 | ||
| 2220 | snd_ymfpci_free_gameport(chip); | 2215 | snd_ymfpci_free_gameport(chip); |
| 2221 | 2216 | ||
| 2222 | pci_write_config_word(chip->pci, 0x40, chip->old_legacy_ctrl); | 2217 | pci_write_config_word(chip->pci, PCIR_DSXG_LEGACY, chip->old_legacy_ctrl); |
| 2223 | 2218 | ||
| 2224 | release_firmware(chip->dsp_microcode); | 2219 | release_firmware(chip->dsp_microcode); |
| 2225 | release_firmware(chip->controller_microcode); | 2220 | release_firmware(chip->controller_microcode); |
| 2226 | } | 2221 | } |
| 2227 | 2222 | ||
| 2228 | #ifdef CONFIG_PM_SLEEP | ||
| 2229 | static const int saved_regs_index[] = { | ||
| 2230 | /* spdif */ | ||
| 2231 | YDSXGR_SPDIFOUTCTRL, | ||
| 2232 | YDSXGR_SPDIFOUTSTATUS, | ||
| 2233 | YDSXGR_SPDIFINCTRL, | ||
| 2234 | /* volumes */ | ||
| 2235 | YDSXGR_PRIADCLOOPVOL, | ||
| 2236 | YDSXGR_NATIVEDACINVOL, | ||
| 2237 | YDSXGR_NATIVEDACOUTVOL, | ||
| 2238 | YDSXGR_BUF441OUTVOL, | ||
| 2239 | YDSXGR_NATIVEADCINVOL, | ||
| 2240 | YDSXGR_SPDIFLOOPVOL, | ||
| 2241 | YDSXGR_SPDIFOUTVOL, | ||
| 2242 | YDSXGR_ZVOUTVOL, | ||
| 2243 | YDSXGR_LEGACYOUTVOL, | ||
| 2244 | /* address bases */ | ||
| 2245 | YDSXGR_PLAYCTRLBASE, | ||
| 2246 | YDSXGR_RECCTRLBASE, | ||
| 2247 | YDSXGR_EFFCTRLBASE, | ||
| 2248 | YDSXGR_WORKBASE, | ||
| 2249 | /* capture set up */ | ||
| 2250 | YDSXGR_MAPOFREC, | ||
| 2251 | YDSXGR_RECFORMAT, | ||
| 2252 | YDSXGR_RECSLOTSR, | ||
| 2253 | YDSXGR_ADCFORMAT, | ||
| 2254 | YDSXGR_ADCSLOTSR, | ||
| 2255 | }; | ||
| 2256 | #define YDSXGR_NUM_SAVED_REGS ARRAY_SIZE(saved_regs_index) | ||
| 2257 | |||
| 2258 | static int snd_ymfpci_suspend(struct device *dev) | 2223 | static int snd_ymfpci_suspend(struct device *dev) |
| 2259 | { | 2224 | { |
| 2260 | struct snd_card *card = dev_get_drvdata(dev); | 2225 | struct snd_card *card = dev_get_drvdata(dev); |
| 2261 | struct snd_ymfpci *chip = card->private_data; | 2226 | struct snd_ymfpci *chip = card->private_data; |
| 2262 | unsigned int i; | 2227 | unsigned int i, legacy_reg_count = DSXG_PCI_NUM_SAVED_LEGACY_REGS; |
| 2263 | 2228 | ||
| 2229 | if (chip->pci->device >= 0x0010) /* YMF 744/754 */ | ||
| 2230 | legacy_reg_count = DSXG_PCI_NUM_SAVED_REGS; | ||
| 2231 | |||
| 2264 | snd_power_change_state(card, SNDRV_CTL_POWER_D3hot); | 2232 | snd_power_change_state(card, SNDRV_CTL_POWER_D3hot); |
| 2265 | snd_ac97_suspend(chip->ac97); | 2233 | snd_ac97_suspend(chip->ac97); |
| 2234 | |||
| 2266 | for (i = 0; i < YDSXGR_NUM_SAVED_REGS; i++) | 2235 | for (i = 0; i < YDSXGR_NUM_SAVED_REGS; i++) |
| 2267 | chip->saved_regs[i] = snd_ymfpci_readl(chip, saved_regs_index[i]); | 2236 | chip->saved_regs[i] = snd_ymfpci_readl(chip, saved_regs_index[i]); |
| 2237 | |||
| 2268 | chip->saved_ydsxgr_mode = snd_ymfpci_readl(chip, YDSXGR_MODE); | 2238 | chip->saved_ydsxgr_mode = snd_ymfpci_readl(chip, YDSXGR_MODE); |
| 2269 | pci_read_config_word(chip->pci, PCIR_DSXG_LEGACY, | 2239 | |
| 2270 | &chip->saved_dsxg_legacy); | 2240 | for (i = 0; i < legacy_reg_count; i++) |
| 2271 | pci_read_config_word(chip->pci, PCIR_DSXG_ELEGACY, | 2241 | pci_read_config_word(chip->pci, pci_saved_regs_index[i], |
| 2272 | &chip->saved_dsxg_elegacy); | 2242 | chip->saved_dsxg_pci_regs + i); |
| 2243 | |||
| 2273 | snd_ymfpci_writel(chip, YDSXGR_NATIVEDACOUTVOL, 0); | 2244 | snd_ymfpci_writel(chip, YDSXGR_NATIVEDACOUTVOL, 0); |
| 2274 | snd_ymfpci_writel(chip, YDSXGR_BUF441OUTVOL, 0); | 2245 | snd_ymfpci_writel(chip, YDSXGR_BUF441OUTVOL, 0); |
| 2275 | snd_ymfpci_disable_dsp(chip); | 2246 | snd_ymfpci_disable_dsp(chip); |
| @@ -2281,7 +2252,10 @@ static int snd_ymfpci_resume(struct device *dev) · 5 unmodified lines | |||
| 2281 | struct pci_dev *pci = to_pci_dev(dev); | 2252 | struct pci_dev *pci = to_pci_dev(dev); |
| 2282 | struct snd_card *card = dev_get_drvdata(dev); | 2253 | struct snd_card *card = dev_get_drvdata(dev); |
| 2283 | struct snd_ymfpci *chip = card->private_data; | 2254 | struct snd_ymfpci *chip = card->private_data; |
| 2284 | unsigned int i; | 2255 | unsigned int i, legacy_reg_count = DSXG_PCI_NUM_SAVED_LEGACY_REGS; |
| 2256 | |||
| 2257 | if (chip->pci->device >= 0x0010) /* YMF 744/754 */ | ||
| 2258 | legacy_reg_count = DSXG_PCI_NUM_SAVED_REGS; | ||
| 2285 | 2259 | ||
| 2286 | snd_ymfpci_aclink_reset(pci); | 2260 | snd_ymfpci_aclink_reset(pci); |
| 2287 | snd_ymfpci_codec_ready(chip, 0); | 2261 | snd_ymfpci_codec_ready(chip, 0); |
| @@ -2293,10 +2267,9 @@ static int snd_ymfpci_resume(struct device *dev) · 5 unmodified lines | |||
| 2293 | 2267 | ||
| 2294 | snd_ac97_resume(chip->ac97); | 2268 | snd_ac97_resume(chip->ac97); |
| 2295 | 2269 | ||
| 2296 | pci_write_config_word(chip->pci, PCIR_DSXG_LEGACY, | 2270 | for (i = 0; i < legacy_reg_count; i++) |
| 2297 | chip->saved_dsxg_legacy); | 2271 | pci_write_config_word(chip->pci, pci_saved_regs_index[i], |
| 2298 | pci_write_config_word(chip->pci, PCIR_DSXG_ELEGACY, | 2272 | chip->saved_dsxg_pci_regs[i]); |
| 2299 | chip->saved_dsxg_elegacy); | ||
| 2300 | 2273 | ||
| 2301 | /* start hw again */ | 2274 | /* start hw again */ |
| 2302 | if (chip->start_count > 0) { | 2275 | if (chip->start_count > 0) { |
| @@ -2309,12 +2282,11 @@ static int snd_ymfpci_resume(struct device *dev) · 6 unmodified lines | |||
| 2309 | return 0; | 2282 | return 0; |
| 2310 | } | 2283 | } |
| 2311 | 2284 | ||
| 2312 | SIMPLE_DEV_PM_OPS(snd_ymfpci_pm, snd_ymfpci_suspend, snd_ymfpci_resume); | 2285 | DEFINE_SIMPLE_DEV_PM_OPS(snd_ymfpci_pm, snd_ymfpci_suspend, snd_ymfpci_resume); |
| 2313 | #endif /* CONFIG_PM_SLEEP */ | ||
| 2314 | 2286 | ||
| 2315 | int snd_ymfpci_create(struct snd_card *card, | 2287 | int snd_ymfpci_create(struct snd_card *card, |
| 2316 | struct pci_dev *pci, | 2288 | struct pci_dev *pci, |
| 2317 | unsigned short old_legacy_ctrl) | 2289 | u16 old_legacy_ctrl) |
| 2318 | { | 2290 | { |
| 2319 | struct snd_ymfpci *chip = card->private_data; | 2291 | struct snd_ymfpci *chip = card->private_data; |
| 2320 | int err; | 2292 | int err; |
| @@ -2379,13 +2351,6 @@ int snd_ymfpci_create(struct snd_card *card, · 58 unmodified lines | |||
| 2379 | if (err < 0) | 2351 | if (err < 0) |
| 2380 | return err; | 2352 | return err; |
| 2381 | 2353 | ||
| 2382 | #ifdef CONFIG_PM_SLEEP | ||
| 2383 | chip->saved_regs = devm_kmalloc_array(&pci->dev, YDSXGR_NUM_SAVED_REGS, | ||
| 2384 | sizeof(u32), GFP_KERNEL); | ||
| 2385 | if (!chip->saved_regs) | ||
| 2386 | return -ENOMEM; | ||
| 2387 | #endif | ||
| 2388 | |||
| 2389 | snd_ymfpci_proc_init(card, chip); | 2354 | snd_ymfpci_proc_init(card, chip); |
| 2390 | 2355 | ||
| 2391 | return 0; | 2356 | return 0; |
| @@ -130,10 +130,9 @@ __error: · 129 unmodified lines | |||
| 130 | } | 130 | } |
| 131 | 131 | ||
| 132 | 132 | ||
| 133 | static int snd_pmac_remove(struct platform_device *devptr) | 133 | static void snd_pmac_remove(struct platform_device *devptr) |
| 134 | { | 134 | { |
| 135 | snd_card_free(platform_get_drvdata(devptr)); | 135 | snd_card_free(platform_get_drvdata(devptr)); |
| 136 | return 0; | ||
| 137 | } | 136 | } |
| 138 | 137 | ||
| 139 | #ifdef CONFIG_PM_SLEEP | 138 | #ifdef CONFIG_PM_SLEEP |
| @@ -161,7 +160,7 @@ static SIMPLE_DEV_PM_OPS(snd_pmac_pm, snd_pmac_driver_suspend, snd_pmac_driver_r · 21 unmodified lines | |||
| 161 | 160 | ||
| 162 | static struct platform_driver snd_pmac_driver = { | 161 | static struct platform_driver snd_pmac_driver = { |
| 163 | .probe = snd_pmac_probe, | 162 | .probe = snd_pmac_probe, |
| 164 | .remove = snd_pmac_remove, | 163 | .remove_new = snd_pmac_remove, |
| 165 | .driver = { | 164 | .driver = { |
| 166 | .name = SND_PMAC_DRIVER, | 165 | .name = SND_PMAC_DRIVER, |
| 167 | .pm = SND_PMAC_PM_OPS, | 166 | .pm = SND_PMAC_PM_OPS, |
| @@ -1361,9 +1361,9 @@ int snd_pmac_tumbler_init(struct snd_pmac *chip) · 1360 unmodified lines | |||
| 1361 | 1361 | ||
| 1362 | for_each_child_of_node(chip->node, np) { | 1362 | for_each_child_of_node(chip->node, np) { |
| 1363 | if (of_node_name_eq(np, "sound")) { | 1363 | if (of_node_name_eq(np, "sound")) { |
| 1364 | if (of_get_property(np, "has-anded-reset", NULL)) | 1364 | if (of_property_read_bool(np, "has-anded-reset")) |
| 1365 | mix->anded_reset = 1; | 1365 | mix->anded_reset = 1; |
| 1366 | if (of_get_property(np, "layout-id", NULL)) | 1366 | if (of_property_present(np, "layout-id")) |
| 1367 | mix->reset_on_sleep = 0; | 1367 | mix->reset_on_sleep = 0; |
| 1368 | of_node_put(np); | 1368 | of_node_put(np); |
| 1369 | break; | 1369 | break; |
| @@ -539,15 +539,12 @@ static int add_aicamixer_controls(struct snd_card_aica *dreamcastcard) · 538 unmodified lines | |||
| 539 | return 0; | 539 | return 0; |
| 540 | } | 540 | } |
| 541 | 541 | ||
| 542 | static int snd_aica_remove(struct platform_device *devptr) | 542 | static void snd_aica_remove(struct platform_device *devptr) |
| 543 | { | 543 | { |
| 544 | struct snd_card_aica *dreamcastcard; | 544 | struct snd_card_aica *dreamcastcard; |
| 545 | dreamcastcard = platform_get_drvdata(devptr); | 545 | dreamcastcard = platform_get_drvdata(devptr); |
| 546 | if (unlikely(!dreamcastcard)) | ||
| 547 | return -ENODEV; | ||
| 548 | snd_card_free(dreamcastcard->card); | 546 | snd_card_free(dreamcastcard->card); |
| 549 | kfree(dreamcastcard); | 547 | kfree(dreamcastcard); |
| 550 | return 0; | ||
| 551 | } | 548 | } |
| 552 | 549 | ||
| 553 | static int snd_aica_probe(struct platform_device *devptr) | 550 | static int snd_aica_probe(struct platform_device *devptr) |
| @@ -594,7 +591,7 @@ static int snd_aica_probe(struct platform_device *devptr) · 40 unmodified lines | |||
| 594 | 591 | ||
| 595 | static struct platform_driver snd_aica_driver = { | 592 | static struct platform_driver snd_aica_driver = { |
| 596 | .probe = snd_aica_probe, | 593 | .probe = snd_aica_probe, |
| 597 | .remove = snd_aica_remove, | 594 | .remove_new = snd_aica_remove, |
| 598 | .driver = { | 595 | .driver = { |
| 599 | .name = SND_AICA_DRIVER, | 596 | .name = SND_AICA_DRIVER, |
| 600 | }, | 597 | }, |
| @@ -257,10 +257,9 @@ static int snd_sh_dac_pcm(struct snd_sh_dac *chip, int device) · 256 unmodified lines | |||
| 257 | 257 | ||
| 258 | 258 | ||
| 259 | /* driver .remove -- destructor */ | 259 | /* driver .remove -- destructor */ |
| 260 | static int snd_sh_dac_remove(struct platform_device *devptr) | 260 | static void snd_sh_dac_remove(struct platform_device *devptr) |
| 261 | { | 261 | { |
| 262 | snd_card_free(platform_get_drvdata(devptr)); | 262 | snd_card_free(platform_get_drvdata(devptr)); |
| 263 | return 0; | ||
| 264 | } | 263 | } |
| 265 | 264 | ||
| 266 | /* free -- it has been defined by create */ | 265 | /* free -- it has been defined by create */ |
| @@ -403,7 +402,7 @@ probe_error: · 136 unmodified lines | |||
| 403 | */ | 402 | */ |
| 404 | static struct platform_driver sh_dac_driver = { | 403 | static struct platform_driver sh_dac_driver = { |
| 405 | .probe = snd_sh_dac_probe, | 404 | .probe = snd_sh_dac_probe, |
| 406 | .remove = snd_sh_dac_remove, | 405 | .remove_new = snd_sh_dac_remove, |
| 407 | .driver = { | 406 | .driver = { |
| 408 | .name = "dac_audio", | 407 | .name = "dac_audio", |
| 409 | }, | 408 | }, |
| @@ -274,13 +274,11 @@ err_clk_disable: · 273 unmodified lines | |||
| 274 | return ret; | 274 | return ret; |
| 275 | } | 275 | } |
| 276 | 276 | ||
| 277 | static int axi_i2s_dev_remove(struct platform_device *pdev) | 277 | static void axi_i2s_dev_remove(struct platform_device *pdev) |
| 278 | { | 278 | { |
| 279 | struct axi_i2s *i2s = platform_get_drvdata(pdev); | 279 | struct axi_i2s *i2s = platform_get_drvdata(pdev); |
| 280 | 280 | ||
| 281 | clk_disable_unprepare(i2s->clk); | 281 | clk_disable_unprepare(i2s->clk); |
| 282 | |||
| 283 | return 0; | ||
| 284 | } | 282 | } |
| 285 | 283 | ||
| 286 | static const struct of_device_id axi_i2s_of_match[] = { | 284 | static const struct of_device_id axi_i2s_of_match[] = { |
| @@ -295,7 +293,7 @@ static struct platform_driver axi_i2s_driver = { · 8 unmodified lines | |||
| 295 | .of_match_table = axi_i2s_of_match, | 293 | .of_match_table = axi_i2s_of_match, |
| 296 | }, | 294 | }, |
| 297 | .probe = axi_i2s_probe, | 295 | .probe = axi_i2s_probe, |
| 298 | .remove = axi_i2s_dev_remove, | 296 | .remove_new = axi_i2s_dev_remove, |
| 299 | }; | 297 | }; |
| 300 | module_platform_driver(axi_i2s_driver); | 298 | module_platform_driver(axi_i2s_driver); |
| 301 | 299 | ||
| @@ -239,13 +239,11 @@ err_clk_disable: · 238 unmodified lines | |||
| 239 | return ret; | 239 | return ret; |
| 240 | } | 240 | } |
| 241 | 241 | ||
| 242 | static int axi_spdif_dev_remove(struct platform_device *pdev) | 242 | static void axi_spdif_dev_remove(struct platform_device *pdev) |
| 243 | { | 243 | { |
| 244 | struct axi_spdif *spdif = platform_get_drvdata(pdev); | 244 | struct axi_spdif *spdif = platform_get_drvdata(pdev); |
| 245 | 245 | ||
| 246 | clk_disable_unprepare(spdif->clk); | 246 | clk_disable_unprepare(spdif->clk); |
| 247 | |||
| 248 | return 0; | ||
| 249 | } | 247 | } |
| 250 | 248 | ||
| 251 | static const struct of_device_id axi_spdif_of_match[] = { | 249 | static const struct of_device_id axi_spdif_of_match[] = { |
| @@ -260,7 +258,7 @@ static struct platform_driver axi_spdif_driver = { · 8 unmodified lines | |||
| 260 | .of_match_table = axi_spdif_of_match, | 258 | .of_match_table = axi_spdif_of_match, |
| 261 | }, | 259 | }, |
| 262 | .probe = axi_spdif_probe, | 260 | .probe = axi_spdif_probe, |
| 263 | .remove = axi_spdif_dev_remove, | 261 | .remove_new = axi_spdif_dev_remove, |
| 264 | }; | 262 | }; |
| 265 | module_platform_driver(axi_spdif_driver); | 263 | module_platform_driver(axi_spdif_driver); |
| 266 | 264 | ||
| @@ -90,6 +90,7 @@ config SND_SOC_AMD_VANGOGH_MACH · 89 unmodified lines | |||
| 90 | 90 | ||
| 91 | config SND_SOC_AMD_ACP6x | 91 | config SND_SOC_AMD_ACP6x |
| 92 | tristate "AMD Audio Coprocessor-v6.x Yellow Carp support" | 92 | tristate "AMD Audio Coprocessor-v6.x Yellow Carp support" |
| 93 | select SND_AMD_ACP_CONFIG | ||
| 93 | depends on X86 && PCI | 94 | depends on X86 && PCI |
| 94 | help | 95 | help |
| 95 | This option enables Audio Coprocessor i.e ACP v6.x support on | 96 | This option enables Audio Coprocessor i.e ACP v6.x support on |
| @@ -130,6 +131,7 @@ config SND_SOC_AMD_RPL_ACP6x · 34 unmodified lines | |||
| 130 | 131 | ||
| 131 | config SND_SOC_AMD_PS | 132 | config SND_SOC_AMD_PS |
| 132 | tristate "AMD Audio Coprocessor-v6.3 Pink Sardine support" | 133 | tristate "AMD Audio Coprocessor-v6.3 Pink Sardine support" |
| 134 | select SND_AMD_ACP_CONFIG | ||
| 133 | depends on X86 && PCI && ACPI | 135 | depends on X86 && PCI && ACPI |
| 134 | help | 136 | help |
| 135 | This option enables Audio Coprocessor i.e ACP v6.3 support on | 137 | This option enables Audio Coprocessor i.e ACP v6.3 support on |
| @@ -1323,7 +1323,7 @@ static int acp_audio_probe(struct platform_device *pdev) · 1322 unmodified lines | |||
| 1323 | return status; | 1323 | return status; |
| 1324 | } | 1324 | } |
| 1325 | 1325 | ||
| 1326 | static int acp_audio_remove(struct platform_device *pdev) | 1326 | static void acp_audio_remove(struct platform_device *pdev) |
| 1327 | { | 1327 | { |
| 1328 | int status; | 1328 | int status; |
| 1329 | struct audio_drv_data *adata = dev_get_drvdata(&pdev->dev); | 1329 | struct audio_drv_data *adata = dev_get_drvdata(&pdev->dev); |
| @@ -1332,8 +1332,6 @@ static int acp_audio_remove(struct platform_device *pdev) · 2 unmodified lines | |||
| 1332 | if (status) | 1332 | if (status) |
| 1333 | dev_err(&pdev->dev, "ACP Deinit failed status:%d\n", status); | 1333 | dev_err(&pdev->dev, "ACP Deinit failed status:%d\n", status); |
| 1334 | pm_runtime_disable(&pdev->dev); | 1334 | pm_runtime_disable(&pdev->dev); |
| 1335 | |||
| 1336 | return 0; | ||
| 1337 | } | 1335 | } |
| 1338 | 1336 | ||
| 1339 | static int acp_pcm_resume(struct device *dev) | 1337 | static int acp_pcm_resume(struct device *dev) |
| @@ -1428,7 +1426,7 @@ static const struct dev_pm_ops acp_pm_ops = { · 88 unmodified lines | |||
| 1428 | 1426 | ||
| 1429 | static struct platform_driver acp_dma_driver = { | 1427 | static struct platform_driver acp_dma_driver = { |
| 1430 | .probe = acp_audio_probe, | 1428 | .probe = acp_audio_probe, |
| 1431 | .remove = acp_audio_remove, | 1429 | .remove_new = acp_audio_remove, |
| 1432 | .driver = { | 1430 | .driver = { |
| 1433 | .name = DRV_NAME, | 1431 | .name = DRV_NAME, |
| 1434 | .pm = &acp_pm_ops, | 1432 | .pm = &acp_pm_ops, |
| @@ -366,28 +366,21 @@ static int rembrandt_audio_probe(struct platform_device *pdev) · 365 unmodified lines | |||
| 366 | return 0; | 366 | return 0; |
| 367 | } | 367 | } |
| 368 | 368 | ||
| 369 | static int rembrandt_audio_remove(struct platform_device *pdev) | 369 | static void rembrandt_audio_remove(struct platform_device *pdev) |
| 370 | { | 370 | { |
| 371 | struct device *dev = &pdev->dev; | 371 | struct device *dev = &pdev->dev; |
| 372 | struct acp_dev_data *adata = dev_get_drvdata(dev); | 372 | struct acp_dev_data *adata = dev_get_drvdata(dev); |
| 373 | struct acp_chip_info *chip; | 373 | struct acp_chip_info *chip = dev_get_platdata(dev); |
| 374 | |||
| 375 | chip = dev_get_platdata(&pdev->dev); | ||
| 376 | if (!chip || !chip->base) { | ||
| 377 | dev_err(&pdev->dev, "ACP chip data is NULL\n"); | ||
| 378 | return -ENODEV; | ||
| 379 | } | ||
| 380 | 374 | ||
| 381 | rmb_acp_deinit(chip->base); | 375 | rmb_acp_deinit(chip->base); |
| 382 | 376 | ||
| 383 | acp6x_disable_interrupts(adata); | 377 | acp6x_disable_interrupts(adata); |
| 384 | acp_platform_unregister(dev); | 378 | acp_platform_unregister(dev); |
| 385 | return 0; | ||
| 386 | } | 379 | } |
| 387 | 380 | ||
| 388 | static struct platform_driver rembrandt_driver = { | 381 | static struct platform_driver rembrandt_driver = { |
| 389 | .probe = rembrandt_audio_probe, | 382 | .probe = rembrandt_audio_probe, |
| 390 | .remove = rembrandt_audio_remove, | 383 | .remove_new = rembrandt_audio_remove, |
| 391 | .driver = { | 384 | .driver = { |
| 392 | .name = "acp_asoc_rembrandt", | 385 | .name = "acp_asoc_rembrandt", |
| 393 | }, | 386 | }, |
| @@ -313,7 +313,7 @@ static int renoir_audio_probe(struct platform_device *pdev) · 312 unmodified lines | |||
| 313 | return 0; | 313 | return 0; |
| 314 | } | 314 | } |
| 315 | 315 | ||
| 316 | static int renoir_audio_remove(struct platform_device *pdev) | 316 | static void renoir_audio_remove(struct platform_device *pdev) |
| 317 | { | 317 | { |
| 318 | struct device *dev = &pdev->dev; | 318 | struct device *dev = &pdev->dev; |
| 319 | struct acp_dev_data *adata = dev_get_drvdata(dev); | 319 | struct acp_dev_data *adata = dev_get_drvdata(dev); |
| @@ -329,12 +329,11 @@ static int renoir_audio_remove(struct platform_device *pdev) · 9 unmodified lines | |||
| 329 | dev_err(&pdev->dev, "ACP de-init Failed (%pe)\n", ERR_PTR(ret)); | 329 | dev_err(&pdev->dev, "ACP de-init Failed (%pe)\n", ERR_PTR(ret)); |
| 330 | 330 | ||
| 331 | acp_platform_unregister(dev); | 331 | acp_platform_unregister(dev); |
| 332 | return 0; | ||
| 333 | } | 332 | } |
| 334 | 333 | ||
| 335 | static struct platform_driver renoir_driver = { | 334 | static struct platform_driver renoir_driver = { |
| 336 | .probe = renoir_audio_probe, | 335 | .probe = renoir_audio_probe, |
| 337 | .remove = renoir_audio_remove, | 336 | .remove_new = renoir_audio_remove, |
| 338 | .driver = { | 337 | .driver = { |
| 339 | .name = "acp_asoc_renoir", | 338 | .name = "acp_asoc_renoir", |
| 340 | }, | 339 | }, |
| @@ -111,3 +111,5 @@ struct acp63_dev_data { · 110 unmodified lines | |||
| 111 | u16 pdev_count; | 111 | u16 pdev_count; |
| 112 | u16 pdm_dev_index; | 112 | u16 pdm_dev_index; |
| 113 | }; | 113 | }; |
| 114 | |||
| 115 | int snd_amd_acp_find_config(struct pci_dev *pci); | ||
| @@ -91,7 +91,6 @@ static int acp63_init(void __iomem *acp_base, struct device *dev) · 90 unmodified lines | |||
| 91 | dev_err(dev, "ACP reset failed\n"); | 91 | dev_err(dev, "ACP reset failed\n"); |
| 92 | return ret; | 92 | return ret; |
| 93 | } | 93 | } |
| 94 | acp63_writel(0x03, acp_base + ACP_CLKMUX_SEL); | ||
| 95 | acp63_enable_interrupts(acp_base); | 94 | acp63_enable_interrupts(acp_base); |
| 96 | return 0; | 95 | return 0; |
| 97 | } | 96 | } |
| @@ -106,7 +105,6 @@ static int acp63_deinit(void __iomem *acp_base, struct device *dev) · 8 unmodified lines | |||
| 106 | dev_err(dev, "ACP reset failed\n"); | 105 | dev_err(dev, "ACP reset failed\n"); |
| 107 | return ret; | 106 | return ret; |
| 108 | } | 107 | } |
| 109 | acp63_writel(0, acp_base + ACP_CLKMUX_SEL); | ||
| 110 | acp63_writel(0, acp_base + ACP_CONTROL); | 108 | acp63_writel(0, acp_base + ACP_CONTROL); |
| 111 | return 0; | 109 | return 0; |
| 112 | } | 110 | } |
| @@ -249,11 +247,17 @@ static int snd_acp63_probe(struct pci_dev *pci, · 136 unmodified lines | |||
| 249 | { | 247 | { |
| 250 | struct acp63_dev_data *adata; | 248 | struct acp63_dev_data *adata; |
| 251 | u32 addr; | 249 | u32 addr; |
| 252 | u32 irqflags; | 250 | u32 irqflags, flag; |
| 253 | int val; | 251 | int val; |
| 254 | int ret; | 252 | int ret; |
| 255 | 253 | ||
| 256 | irqflags = IRQF_SHARED; | 254 | irqflags = IRQF_SHARED; |
| 255 | |||
| 256 | /* Return if acp config flag is defined */ | ||
| 257 | flag = snd_amd_acp_find_config(pci); | ||
| 258 | if (flag) | ||
| 259 | return -ENODEV; | ||
| 260 | |||
| 257 | /* Pink Sardine device check */ | 261 | /* Pink Sardine device check */ |
| 258 | switch (pci->revision) { | 262 | switch (pci->revision) { |
| 259 | case 0x63: | 263 | case 0x63: |
| @@ -399,10 +399,9 @@ static int acp63_pdm_audio_probe(struct platform_device *pdev) · 398 unmodified lines | |||
| 399 | return 0; | 399 | return 0; |
| 400 | } | 400 | } |
| 401 | 401 | ||
| 402 | static int acp63_pdm_audio_remove(struct platform_device *pdev) | 402 | static void acp63_pdm_audio_remove(struct platform_device *pdev) |
| 403 | { | 403 | { |
| 404 | pm_runtime_disable(&pdev->dev); | 404 | pm_runtime_disable(&pdev->dev); |
| 405 | return 0; | ||
| 406 | } | 405 | } |
| 407 | 406 | ||
| 408 | static int __maybe_unused acp63_pdm_resume(struct device *dev) | 407 | static int __maybe_unused acp63_pdm_resume(struct device *dev) |
| @@ -451,7 +450,7 @@ static const struct dev_pm_ops acp63_pdm_pm_ops = { · 42 unmodified lines | |||
| 451 | 450 | ||
| 452 | static struct platform_driver acp63_pdm_dma_driver = { | 451 | static struct platform_driver acp63_pdm_dma_driver = { |
| 453 | .probe = acp63_pdm_audio_probe, | 452 | .probe = acp63_pdm_audio_probe, |
| 454 | .remove = acp63_pdm_audio_remove, | 453 | .remove_new = acp63_pdm_audio_remove, |
| 455 | .driver = { | 454 | .driver = { |
| 456 | .name = "acp_ps_pdm_dma", | 455 | .name = "acp_ps_pdm_dma", |
| 457 | .pm = &acp63_pdm_pm_ops, | 456 | .pm = &acp63_pdm_pm_ops, |
| @@ -421,10 +421,9 @@ static int acp3x_audio_probe(struct platform_device *pdev) · 420 unmodified lines | |||
| 421 | return 0; | 421 | return 0; |
| 422 | } | 422 | } |
| 423 | 423 | ||
| 424 | static int acp3x_audio_remove(struct platform_device *pdev) | 424 | static void acp3x_audio_remove(struct platform_device *pdev) |
| 425 | { | 425 | { |
| 426 | pm_runtime_disable(&pdev->dev); | 426 | pm_runtime_disable(&pdev->dev); |
| 427 | return 0; | ||
| 428 | } | 427 | } |
| 429 | 428 | ||
| 430 | static int acp3x_resume(struct device *dev) | 429 | static int acp3x_resume(struct device *dev) |
| @@ -509,7 +508,7 @@ static const struct dev_pm_ops acp3x_pm_ops = { · 78 unmodified lines | |||
| 509 | 508 | ||
| 510 | static struct platform_driver acp3x_dma_driver = { | 509 | static struct platform_driver acp3x_dma_driver = { |
| 511 | .probe = acp3x_audio_probe, | 510 | .probe = acp3x_audio_probe, |
| 512 | .remove = acp3x_audio_remove, | 511 | .remove_new = acp3x_audio_remove, |
| 513 | .driver = { | 512 | .driver = { |
| 514 | .name = "acp3x_rv_i2s_dma", | 513 | .name = "acp3x_rv_i2s_dma", |
| 515 | .pm = &acp3x_pm_ops, | 514 | .pm = &acp3x_pm_ops, |
| @@ -435,10 +435,9 @@ static int acp_pdm_audio_probe(struct platform_device *pdev) · 434 unmodified lines | |||
| 435 | return 0; | 435 | return 0; |
| 436 | } | 436 | } |
| 437 | 437 | ||
| 438 | static int acp_pdm_audio_remove(struct platform_device *pdev) | 438 | static void acp_pdm_audio_remove(struct platform_device *pdev) |
| 439 | { | 439 | { |
| 440 | pm_runtime_disable(&pdev->dev); | 440 | pm_runtime_disable(&pdev->dev); |
| 441 | return 0; | ||
| 442 | } | 441 | } |
| 443 | 442 | ||
| 444 | static int acp_pdm_resume(struct device *dev) | 443 | static int acp_pdm_resume(struct device *dev) |
| @@ -489,7 +488,7 @@ static const struct dev_pm_ops acp_pdm_pm_ops = { · 44 unmodified lines | |||
| 489 | 488 | ||
| 490 | static struct platform_driver acp_pdm_dma_driver = { | 489 | static struct platform_driver acp_pdm_dma_driver = { |
| 491 | .probe = acp_pdm_audio_probe, | 490 | .probe = acp_pdm_audio_probe, |
| 492 | .remove = acp_pdm_audio_remove, | 491 | .remove_new = acp_pdm_audio_remove, |
| 493 | .driver = { | 492 | .driver = { |
| 494 | .name = "acp_rn_pdm_dma", | 493 | .name = "acp_rn_pdm_dma", |
| 495 | .pm = &acp_pdm_pm_ops, | 494 | .pm = &acp_pdm_pm_ops, |
| @@ -6,37 +6,40 @@ · 5 unmodified lines | |||
| 6 | * Copyright 2021 Advanced Micro Devices, Inc. | 6 | * Copyright 2021 Advanced Micro Devices, Inc. |
| 7 | */ | 7 | */ |
| 8 | 8 | ||
| 9 | #include <sound/soc.h> | ||
| 10 | #include <sound/soc-dapm.h> | ||
| 11 | #include <linux/module.h> | ||
| 12 | #include <linux/io.h> | ||
| 13 | #include <sound/pcm.h> | ||
| 14 | #include <sound/pcm_params.h> | ||
| 15 | |||
| 16 | #include <sound/jack.h> | ||
| 17 | #include <linux/clk.h> | ||
| 18 | #include <linux/gpio.h> | ||
| 19 | #include <linux/gpio/consumer.h> | ||
| 20 | #include <linux/i2c.h> | ||
| 21 | #include <linux/input.h> | ||
| 22 | #include <linux/acpi.h> | 9 | #include <linux/acpi.h> |
| 23 | #include <linux/dmi.h> | 10 | #include <linux/dmi.h> |
| 11 | #include <linux/gpio/consumer.h> | ||
| 12 | #include <linux/i2c.h> | ||
| 13 | #include <linux/input-event-codes.h> | ||
| 14 | #include <linux/module.h> | ||
| 15 | #include <sound/jack.h> | ||
| 16 | #include <sound/pcm_params.h> | ||
| 17 | #include <sound/soc.h> | ||
| 18 | #include <sound/soc-dapm.h> | ||
| 24 | 19 | ||
| 25 | #include "../../codecs/nau8821.h" | 20 | #include "../../codecs/nau8821.h" |
| 26 | #include "../../codecs/cs35l41.h" | ||
| 27 | |||
| 28 | #include "acp5x.h" | 21 | #include "acp5x.h" |
| 29 | 22 | ||
| 30 | #define DRV_NAME "acp5x_mach" | 23 | #define DRV_NAME "acp5x_mach" |
| 31 | #define DUAL_CHANNEL 2 | 24 | #define DUAL_CHANNEL 2 |
| 32 | #define ACP5X_NUVOTON_CODEC_DAI "nau8821-hifi" | 25 | #define VG_JUPITER 1 |
| 33 | #define VG_JUPITER 1 | 26 | #define ACP5X_NAU8821_BCLK 3072000 |
| 34 | #define ACP5X_NUVOTON_BCLK 3072000 | 27 | #define ACP5X_NAU8821_FREQ_OUT 12288000 |
| 35 | #define ACP5X_NAU8821_FREQ_OUT 12288000 | 28 | #define ACP5X_NAU8821_COMP_NAME "i2c-NVTN2020:00" |
| 29 | #define ACP5X_NAU8821_DAI_NAME "nau8821-hifi" | ||
| 30 | #define ACP5X_CS35L41_COMP_LNAME "spi-VLV1776:00" | ||
| 31 | #define ACP5X_CS35L41_COMP_RNAME "spi-VLV1776:01" | ||
| 32 | #define ACP5X_CS35L41_DAI_NAME "cs35l41-pcm" | ||
| 36 | 33 | ||
| 37 | static unsigned long acp5x_machine_id; | 34 | static unsigned long acp5x_machine_id; |
| 38 | static struct snd_soc_jack vg_headset; | 35 | static struct snd_soc_jack vg_headset; |
| 39 | 36 | ||
| 37 | SND_SOC_DAILINK_DEF(platform, DAILINK_COMP_ARRAY(COMP_PLATFORM("acp5x_i2s_dma.0"))); | ||
| 38 | SND_SOC_DAILINK_DEF(acp5x_i2s, DAILINK_COMP_ARRAY(COMP_CPU("acp5x_i2s_playcap.0"))); | ||
| 39 | SND_SOC_DAILINK_DEF(acp5x_bt, DAILINK_COMP_ARRAY(COMP_CPU("acp5x_i2s_playcap.1"))); | ||
| 40 | SND_SOC_DAILINK_DEF(nau8821, DAILINK_COMP_ARRAY(COMP_CODEC(ACP5X_NAU8821_COMP_NAME, | ||
| 41 | ACP5X_NAU8821_DAI_NAME))); | ||
| 42 | |||
| 40 | static struct snd_soc_jack_pin acp5x_nau8821_jack_pins[] = { | 43 | static struct snd_soc_jack_pin acp5x_nau8821_jack_pins[] = { |
| 41 | { | 44 | { |
| 42 | .pin = "Headphone", | 45 | .pin = "Headphone", |
| @@ -48,18 +51,54 @@ static struct snd_soc_jack_pin acp5x_nau8821_jack_pins[] = { · 5 unmodified lines | |||
| 48 | }, | 51 | }, |
| 49 | }; | 52 | }; |
| 50 | 53 | ||
| 54 | static const struct snd_kcontrol_new acp5x_8821_controls[] = { | ||
| 55 | SOC_DAPM_PIN_SWITCH("Headphone"), | ||
| 56 | SOC_DAPM_PIN_SWITCH("Headset Mic"), | ||
| 57 | SOC_DAPM_PIN_SWITCH("Int Mic"), | ||
| 58 | }; | ||
| 59 | |||
| 60 | static int platform_clock_control(struct snd_soc_dapm_widget *w, | ||
| 61 | struct snd_kcontrol *k, int event) | ||
| 62 | { | ||
| 63 | struct snd_soc_dapm_context *dapm = w->dapm; | ||
| 64 | struct snd_soc_card *card = dapm->card; | ||
| 65 | struct snd_soc_dai *dai; | ||
| 66 | int ret = 0; | ||
| 67 | |||
| 68 | dai = snd_soc_card_get_codec_dai(card, ACP5X_NAU8821_DAI_NAME); | ||
| 69 | if (!dai) { | ||
| 70 | dev_err(card->dev, "Codec dai not found\n"); | ||
| 71 | return -EIO; | ||
| 72 | } | ||
| 73 | |||
| 74 | if (SND_SOC_DAPM_EVENT_OFF(event)) { | ||
| 75 | ret = snd_soc_dai_set_sysclk(dai, NAU8821_CLK_INTERNAL, 0, SND_SOC_CLOCK_IN); | ||
| 76 | if (ret < 0) { | ||
| 77 | dev_err(card->dev, "set sysclk err = %d\n", ret); | ||
| 78 | return -EIO; | ||
| 79 | } | ||
| 80 | } else { | ||
| 81 | ret = snd_soc_dai_set_sysclk(dai, NAU8821_CLK_FLL_BLK, 0, SND_SOC_CLOCK_IN); | ||
| 82 | if (ret < 0) | ||
| 83 | dev_err(dai->dev, "can't set BLK clock %d\n", ret); | ||
| 84 | ret = snd_soc_dai_set_pll(dai, 0, 0, ACP5X_NAU8821_BCLK, ACP5X_NAU8821_FREQ_OUT); | ||
| 85 | if (ret < 0) | ||
| 86 | dev_err(dai->dev, "can't set FLL: %d\n", ret); | ||
| 87 | } | ||
| 88 | |||
| 89 | return ret; | ||
| 90 | } | ||
| 91 | |||
| 51 | static int acp5x_8821_init(struct snd_soc_pcm_runtime *rtd) | 92 | static int acp5x_8821_init(struct snd_soc_pcm_runtime *rtd) |
| 52 | { | 93 | { |
| 94 | struct snd_soc_component *component = asoc_rtd_to_codec(rtd, 0)->component; | ||
| 53 | int ret; | 95 | int ret; |
| 54 | struct snd_soc_card *card = rtd->card; | ||
| 55 | struct snd_soc_component *component = | ||
| 56 | asoc_rtd_to_codec(rtd, 0)->component; | ||
| 57 | 96 | ||
| 58 | /* | 97 | /* |
| 59 | * Headset buttons map to the google Reference headset. | 98 | * Headset buttons map to the google Reference headset. |
| 60 | * These can be configured by userspace. | 99 | * These can be configured by userspace. |
| 61 | */ | 100 | */ |
| 62 | ret = snd_soc_card_jack_new_pins(card, "Headset Jack", | 101 | ret = snd_soc_card_jack_new_pins(rtd->card, "Headset Jack", |
| 63 | SND_JACK_HEADSET | SND_JACK_BTN_0, | 102 | SND_JACK_HEADSET | SND_JACK_BTN_0, |
| 64 | &vg_headset, acp5x_nau8821_jack_pins, | 103 | &vg_headset, acp5x_nau8821_jack_pins, |
| 65 | ARRAY_SIZE(acp5x_nau8821_jack_pins)); | 104 | ARRAY_SIZE(acp5x_nau8821_jack_pins)); |
| @@ -70,12 +109,8 @@ static int acp5x_8821_init(struct snd_soc_pcm_runtime *rtd) · 4 unmodified lines | |||
| 70 | 109 | ||
| 71 | snd_jack_set_key(vg_headset.jack, SND_JACK_BTN_0, KEY_MEDIA); | 110 | snd_jack_set_key(vg_headset.jack, SND_JACK_BTN_0, KEY_MEDIA); |
| 72 | nau8821_enable_jack_detect(component, &vg_headset); | 111 | nau8821_enable_jack_detect(component, &vg_headset); |
| 73 | return ret; | ||
| 74 | } | ||
| 75 | 112 | ||
| 76 | static int acp5x_cs35l41_init(struct snd_soc_pcm_runtime *rtd) | 113 | return ret; |
| 77 | { | ||
| 78 | return 0; | ||
| 79 | } | 114 | } |
| 80 | 115 | ||
| 81 | static const unsigned int rates[] = { | 116 | static const unsigned int rates[] = { |
| @@ -109,8 +144,7 @@ static int acp5x_8821_startup(struct snd_pcm_substream *substream) · 27 unmodified lines | |||
| 109 | { | 144 | { |
| 110 | struct snd_pcm_runtime *runtime = substream->runtime; | 145 | struct snd_pcm_runtime *runtime = substream->runtime; |
| 111 | struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); | 146 | struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); |
| 112 | struct snd_soc_card *card = rtd->card; | 147 | struct acp5x_platform_info *machine = snd_soc_card_get_drvdata(rtd->card); |
| 113 | struct acp5x_platform_info *machine = snd_soc_card_get_drvdata(card); | ||
| 114 | 148 | ||
| 115 | machine->play_i2s_instance = I2S_SP_INSTANCE; | 149 | machine->play_i2s_instance = I2S_SP_INSTANCE; |
| 116 | machine->cap_i2s_instance = I2S_SP_INSTANCE; | 150 | machine->cap_i2s_instance = I2S_SP_INSTANCE; |
| @@ -123,6 +157,7 @@ static int acp5x_8821_startup(struct snd_pcm_substream *substream) · 6 unmodified lines | |||
| 123 | snd_pcm_hw_constraint_list(substream->runtime, 0, | 157 | snd_pcm_hw_constraint_list(substream->runtime, 0, |
| 124 | SNDRV_PCM_HW_PARAM_SAMPLE_BITS, | 158 | SNDRV_PCM_HW_PARAM_SAMPLE_BITS, |
| 125 | &constraints_sample_bits); | 159 | &constraints_sample_bits); |
| 160 | |||
| 126 | return 0; | 161 | return 0; |
| 127 | } | 162 | } |
| 128 | 163 | ||
| @@ -131,29 +166,36 @@ static int acp5x_nau8821_hw_params(struct snd_pcm_substream *substream, · 2 unmodified lines | |||
| 131 | { | 166 | { |
| 132 | struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); | 167 | struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); |
| 133 | struct snd_soc_card *card = rtd->card; | 168 | struct snd_soc_card *card = rtd->card; |
| 134 | struct snd_soc_dai *codec_dai = | 169 | struct snd_soc_dai *dai = snd_soc_card_get_codec_dai(card, ACP5X_NAU8821_DAI_NAME); |
| 135 | snd_soc_card_get_codec_dai(card, | 170 | int ret, bclk; |
| 136 | ACP5X_NUVOTON_CODEC_DAI); | ||
| 137 | int ret; | ||
| 138 | 171 | ||
| 139 | ret = snd_soc_dai_set_sysclk(codec_dai, NAU8821_CLK_FLL_BLK, 0, | 172 | ret = snd_soc_dai_set_sysclk(dai, NAU8821_CLK_FLL_BLK, 0, SND_SOC_CLOCK_IN); |
| 140 | SND_SOC_CLOCK_IN); | ||
| 141 | if (ret < 0) | 173 | if (ret < 0) |
| 142 | dev_err(card->dev, "can't set FS clock %d\n", ret); | 174 | dev_err(card->dev, "can't set FS clock %d\n", ret); |
| 143 | ret = snd_soc_dai_set_pll(codec_dai, 0, 0, snd_soc_params_to_bclk(params), | 175 | |
| 144 | params_rate(params) * 256); | 176 | bclk = snd_soc_params_to_bclk(params); |
| 177 | if (bclk < 0) { | ||
| 178 | dev_err(dai->dev, "Fail to get BCLK rate: %d\n", bclk); | ||
| 179 | return bclk; | ||
| 180 | } | ||
| 181 | |||
| 182 | ret = snd_soc_dai_set_pll(dai, 0, 0, bclk, params_rate(params) * 256); | ||
| 145 | if (ret < 0) | 183 | if (ret < 0) |
| 146 | dev_err(card->dev, "can't set FLL: %d\n", ret); | 184 | dev_err(card->dev, "can't set FLL: %d\n", ret); |
| 147 | 185 | ||
| 148 | return ret; | 186 | return ret; |
| 149 | } | 187 | } |
| 150 | 188 | ||
| 189 | static const struct snd_soc_ops acp5x_8821_ops = { | ||
| 190 | .startup = acp5x_8821_startup, | ||
| 191 | .hw_params = acp5x_nau8821_hw_params, | ||
| 192 | }; | ||
| 193 | |||
| 151 | static int acp5x_cs35l41_startup(struct snd_pcm_substream *substream) | 194 | static int acp5x_cs35l41_startup(struct snd_pcm_substream *substream) |
| 152 | { | 195 | { |
| 153 | struct snd_pcm_runtime *runtime = substream->runtime; | ||
| 154 | struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); | 196 | struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); |
| 155 | struct snd_soc_card *card = rtd->card; | 197 | struct acp5x_platform_info *machine = snd_soc_card_get_drvdata(rtd->card); |
| 156 | struct acp5x_platform_info *machine = snd_soc_card_get_drvdata(card); | 198 | struct snd_pcm_runtime *runtime = substream->runtime; |
| 157 | 199 | ||
| 158 | machine->play_i2s_instance = I2S_HS_INSTANCE; | 200 | machine->play_i2s_instance = I2S_HS_INSTANCE; |
| 159 | 201 | ||
| @@ -162,6 +204,7 @@ static int acp5x_cs35l41_startup(struct snd_pcm_substream *substream) · 2 unmodified lines | |||
| 162 | &constraints_channels); | 204 | &constraints_channels); |
| 163 | snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, | 205 | snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, |
| 164 | &constraints_rates); | 206 | &constraints_rates); |
| 207 | |||
| 165 | return 0; | 208 | return 0; |
| 166 | } | 209 | } |
| 167 | 210 | ||
| @@ -169,80 +212,66 @@ static int acp5x_cs35l41_hw_params(struct snd_pcm_substream *substream, · 1 unmodified line | |||
| 169 | struct snd_pcm_hw_params *params) | 212 | struct snd_pcm_hw_params *params) |
| 170 | { | 213 | { |
| 171 | struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); | 214 | struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); |
| 172 | struct snd_soc_card *card = rtd->card; | 215 | unsigned int bclk, rate = params_rate(params); |
| 173 | struct snd_soc_dai *codec_dai; | 216 | struct snd_soc_component *comp; |
| 174 | int ret, i; | 217 | int ret, i; |
| 175 | unsigned int num_codecs = rtd->dai_link->num_codecs; | 218 | |
| 176 | unsigned int bclk_val; | 219 | switch (rate) { |
| 177 | 220 | case 48000: | |
| 178 | ret = 0; | 221 | bclk = 1536000; |
| 179 | for (i = 0; i < num_codecs; i++) { | 222 | break; |
| 180 | codec_dai = asoc_rtd_to_codec(rtd, i); | 223 | default: |
| 181 | if (strcmp(codec_dai->name, "cs35l41-pcm") == 0) { | 224 | bclk = 0; |
| 182 | switch (params_rate(params)) { | 225 | break; |
| 183 | case 48000: | 226 | } |
| 184 | bclk_val = 1536000; | 227 | |
| 185 | break; | 228 | for_each_rtd_components(rtd, i, comp) { |
| 186 | default: | 229 | if (!(strcmp(comp->name, ACP5X_CS35L41_COMP_LNAME)) || |
| 187 | dev_err(card->dev, "Invalid Samplerate:0x%x\n", | 230 | !(strcmp(comp->name, ACP5X_CS35L41_COMP_RNAME))) { |
| 188 | params_rate(params)); | 231 | if (!bclk) { |
| 232 | dev_err(comp->dev, "Invalid sample rate: 0x%x\n", rate); | ||
| 189 | return -EINVAL; | 233 | return -EINVAL; |
| 190 | } | 234 | } |
| 191 | ret = snd_soc_component_set_sysclk(codec_dai->component, | 235 | |
| 192 | 0, 0, bclk_val, SND_SOC_CLOCK_IN); | 236 | ret = snd_soc_component_set_sysclk(comp, 0, 0, bclk, SND_SOC_CLOCK_IN); |
| 193 | if (ret < 0) { | 237 | if (ret) { |
| 194 | dev_err(card->dev, "failed to set sysclk for CS35l41 dai\n"); | 238 | dev_err(comp->dev, "failed to set SYSCLK: %d\n", ret); |
| 195 | return ret; | 239 | return ret; |
| 196 | } | 240 | } |
| 197 | } | 241 | } |
| 198 | } | 242 | } |
| 199 | 243 | ||
| 200 | return ret; | 244 | return 0; |
| 201 | } | ||
| 202 | 245 | ||
| 203 | static const struct snd_soc_ops acp5x_8821_ops = { | 246 | } |
| 204 | .startup = acp5x_8821_startup, | ||
| 205 | .hw_params = acp5x_nau8821_hw_params, | ||
| 206 | }; | ||
| 207 | 247 | ||
| 208 | static const struct snd_soc_ops acp5x_cs35l41_play_ops = { | 248 | static const struct snd_soc_ops acp5x_cs35l41_play_ops = { |
| 209 | .startup = acp5x_cs35l41_startup, | 249 | .startup = acp5x_cs35l41_startup, |
| 210 | .hw_params = acp5x_cs35l41_hw_params, | 250 | .hw_params = acp5x_cs35l41_hw_params, |
| 211 | }; | 251 | }; |
| 212 | 252 | ||
| 213 | static struct snd_soc_codec_conf cs35l41_conf[] = { | 253 | static struct snd_soc_codec_conf acp5x_cs35l41_conf[] = { |
| 214 | { | 254 | { |
| 215 | .dlc = COMP_CODEC_CONF("spi-VLV1776:00"), | 255 | .dlc = COMP_CODEC_CONF(ACP5X_CS35L41_COMP_LNAME), |
| 216 | .name_prefix = "Left", | 256 | .name_prefix = "Left", |
| 217 | }, | 257 | }, |
| 218 | { | 258 | { |
| 219 | .dlc = COMP_CODEC_CONF("spi-VLV1776:01"), | 259 | .dlc = COMP_CODEC_CONF(ACP5X_CS35L41_COMP_RNAME), |
| 220 | .name_prefix = "Right", | 260 | .name_prefix = "Right", |
| 221 | }, | 261 | }, |
| 222 | }; | 262 | }; |
| 223 | 263 | ||
| 224 | SND_SOC_DAILINK_DEF(acp5x_i2s, | 264 | SND_SOC_DAILINK_DEF(cs35l41, DAILINK_COMP_ARRAY(COMP_CODEC(ACP5X_CS35L41_COMP_LNAME, |
| 225 | DAILINK_COMP_ARRAY(COMP_CPU("acp5x_i2s_playcap.0"))); | 265 | ACP5X_CS35L41_DAI_NAME), |
| 266 | COMP_CODEC(ACP5X_CS35L41_COMP_RNAME, | ||
| 267 | ACP5X_CS35L41_DAI_NAME))); | ||
| 226 | 268 | ||
| 227 | SND_SOC_DAILINK_DEF(acp5x_bt, | 269 | static struct snd_soc_dai_link acp5x_8821_35l41_dai[] = { |
| 228 | DAILINK_COMP_ARRAY(COMP_CPU("acp5x_i2s_playcap.1"))); | ||
| 229 | |||
| 230 | SND_SOC_DAILINK_DEF(nau8821, | ||
| 231 | DAILINK_COMP_ARRAY(COMP_CODEC("i2c-NVTN2020:00", | ||
| 232 | "nau8821-hifi"))); | ||
| 233 | |||
| 234 | SND_SOC_DAILINK_DEF(cs35l41, | ||
| 235 | DAILINK_COMP_ARRAY(COMP_CODEC("spi-VLV1776:00", "cs35l41-pcm"), | ||
| 236 | COMP_CODEC("spi-VLV1776:01", "cs35l41-pcm"))); | ||
| 237 | |||
| 238 | SND_SOC_DAILINK_DEF(platform, | ||
| 239 | DAILINK_COMP_ARRAY(COMP_PLATFORM("acp5x_i2s_dma.0"))); | ||
| 240 | |||
| 241 | static struct snd_soc_dai_link acp5x_dai[] = { | ||
| 242 | { | 270 | { |
| 243 | .name = "acp5x-8821-play", | 271 | .name = "acp5x-8821-play", |
| 244 | .stream_name = "Playback/Capture", | 272 | .stream_name = "Playback/Capture", |
| 245 | .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | | 273 | .dai_fmt = SND_SOC_DAIFMT_I2S | |
| 274 | SND_SOC_DAIFMT_NB_NF | | ||
| 246 | SND_SOC_DAIFMT_CBC_CFC, | 275 | SND_SOC_DAIFMT_CBC_CFC, |
| 247 | .dpcm_playback = 1, | 276 | .dpcm_playback = 1, |
| 248 | .dpcm_capture = 1, | 277 | .dpcm_capture = 1, |
| @@ -253,65 +282,28 @@ static struct snd_soc_dai_link acp5x_dai[] = { · 4 unmodified lines | |||
| 253 | { | 282 | { |
| 254 | .name = "acp5x-CS35L41-Stereo", | 283 | .name = "acp5x-CS35L41-Stereo", |
| 255 | .stream_name = "CS35L41 Stereo Playback", | 284 | .stream_name = "CS35L41 Stereo Playback", |
| 256 | .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | | 285 | .dai_fmt = SND_SOC_DAIFMT_I2S | |
| 286 | SND_SOC_DAIFMT_NB_NF | | ||
| 257 | SND_SOC_DAIFMT_CBC_CFC, | 287 | SND_SOC_DAIFMT_CBC_CFC, |
| 258 | .dpcm_playback = 1, | 288 | .dpcm_playback = 1, |
| 259 | .playback_only = 1, | 289 | .playback_only = 1, |
| 260 | .ops = &acp5x_cs35l41_play_ops, | 290 | .ops = &acp5x_cs35l41_play_ops, |
| 261 | .init = acp5x_cs35l41_init, | ||
| 262 | SND_SOC_DAILINK_REG(acp5x_bt, cs35l41, platform), | 291 | SND_SOC_DAILINK_REG(acp5x_bt, cs35l41, platform), |
| 263 | }, | 292 | }, |
| 264 | }; | 293 | }; |
| 265 | 294 | ||
| 266 | static int platform_clock_control(struct snd_soc_dapm_widget *w, | ||
| 267 | struct snd_kcontrol *k, int event) | ||
| 268 | { | ||
| 269 | struct snd_soc_dapm_context *dapm = w->dapm; | ||
| 270 | struct snd_soc_card *card = dapm->card; | ||
| 271 | struct snd_soc_dai *codec_dai; | ||
| 272 | int ret = 0; | ||
| 273 | 295 | ||
| 274 | codec_dai = snd_soc_card_get_codec_dai(card, ACP5X_NUVOTON_CODEC_DAI); | ||
| 275 | if (!codec_dai) { | ||
| 276 | dev_err(card->dev, "Codec dai not found\n"); | ||
| 277 | return -EIO; | ||
| 278 | } | ||
| 279 | 296 | ||
| 280 | if (SND_SOC_DAPM_EVENT_OFF(event)) { | 297 | static const struct snd_soc_dapm_widget acp5x_8821_35l41_widgets[] = { |
| 281 | ret = snd_soc_dai_set_sysclk(codec_dai, NAU8821_CLK_INTERNAL, | ||
| 282 | 0, SND_SOC_CLOCK_IN); | ||
| 283 | if (ret < 0) { | ||
| 284 | dev_err(card->dev, "set sysclk err = %d\n", ret); | ||
| 285 | return -EIO; | ||
| 286 | } | ||
| 287 | } else { | ||
| 288 | ret = snd_soc_dai_set_sysclk(codec_dai, NAU8821_CLK_FLL_BLK, 0, | ||
| 289 | SND_SOC_CLOCK_IN); | ||
| 290 | if (ret < 0) | ||
| 291 | dev_err(codec_dai->dev, "can't set BLK clock %d\n", ret); | ||
| 292 | ret = snd_soc_dai_set_pll(codec_dai, 0, 0, ACP5X_NUVOTON_BCLK, | ||
| 293 | ACP5X_NAU8821_FREQ_OUT); | ||
| 294 | if (ret < 0) | ||
| 295 | dev_err(codec_dai->dev, "can't set FLL: %d\n", ret); | ||
| 296 | } | ||
| 297 | return ret; | ||
| 298 | } | ||
| 299 | |||
| 300 | static const struct snd_kcontrol_new acp5x_8821_controls[] = { | ||
| 301 | SOC_DAPM_PIN_SWITCH("Headphone"), | ||
| 302 | SOC_DAPM_PIN_SWITCH("Headset Mic"), | ||
| 303 | SOC_DAPM_PIN_SWITCH("Int Mic"), | ||
| 304 | }; | ||
| 305 | |||
| 306 | static const struct snd_soc_dapm_widget acp5x_8821_widgets[] = { | ||
| 307 | SND_SOC_DAPM_HP("Headphone", NULL), | 298 | SND_SOC_DAPM_HP("Headphone", NULL), |
| 308 | SND_SOC_DAPM_MIC("Headset Mic", NULL), | 299 | SND_SOC_DAPM_MIC("Headset Mic", NULL), |
| 309 | SND_SOC_DAPM_MIC("Int Mic", NULL), | 300 | SND_SOC_DAPM_MIC("Int Mic", NULL), |
| 310 | SND_SOC_DAPM_SUPPLY("Platform Clock", SND_SOC_NOPM, 0, 0, | 301 | SND_SOC_DAPM_SUPPLY("Platform Clock", SND_SOC_NOPM, 0, 0, |
| 311 | platform_clock_control, SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), | 302 | platform_clock_control, |
| 303 | SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), | ||
| 312 | }; | 304 | }; |
| 313 | 305 | ||
| 314 | static const struct snd_soc_dapm_route acp5x_8821_audio_route[] = { | 306 | static const struct snd_soc_dapm_route acp5x_8821_35l41_audio_route[] = { |
| 315 | /* HP jack connectors - unknown if we have jack detection */ | 307 | /* HP jack connectors - unknown if we have jack detection */ |
| 316 | { "Headphone", NULL, "HPOL" }, | 308 | { "Headphone", NULL, "HPOL" }, |
| 317 | { "Headphone", NULL, "HPOR" }, | 309 | { "Headphone", NULL, "HPOR" }, |
| @@ -324,17 +316,17 @@ static const struct snd_soc_dapm_route acp5x_8821_audio_route[] = { · 6 unmodified lines | |||
| 324 | { "Int Mic", NULL, "Platform Clock" }, | 316 | { "Int Mic", NULL, "Platform Clock" }, |
| 325 | }; | 317 | }; |
| 326 | 318 | ||
| 327 | static struct snd_soc_card acp5x_card = { | 319 | static struct snd_soc_card acp5x_8821_35l41_card = { |
| 328 | .name = "acp5x", | 320 | .name = "acp5x", |
| 329 | .owner = THIS_MODULE, | 321 | .owner = THIS_MODULE, |
| 330 | .dai_link = acp5x_dai, | 322 | .dai_link = acp5x_8821_35l41_dai, |
| 331 | .num_links = ARRAY_SIZE(acp5x_dai), | 323 | .num_links = ARRAY_SIZE(acp5x_8821_35l41_dai), |
| 332 | .dapm_widgets = acp5x_8821_widgets, | 324 | .dapm_widgets = acp5x_8821_35l41_widgets, |
| 333 | .num_dapm_widgets = ARRAY_SIZE(acp5x_8821_widgets), | 325 | .num_dapm_widgets = ARRAY_SIZE(acp5x_8821_35l41_widgets), |
| 334 | .dapm_routes = acp5x_8821_audio_route, | 326 | .dapm_routes = acp5x_8821_35l41_audio_route, |
| 335 | .num_dapm_routes = ARRAY_SIZE(acp5x_8821_audio_route), | 327 | .num_dapm_routes = ARRAY_SIZE(acp5x_8821_35l41_audio_route), |
| 336 | .codec_conf = cs35l41_conf, | 328 | .codec_conf = acp5x_cs35l41_conf, |
| 337 | .num_configs = ARRAY_SIZE(cs35l41_conf), | 329 | .num_configs = ARRAY_SIZE(acp5x_cs35l41_conf), |
| 338 | .controls = acp5x_8821_controls, | 330 | .controls = acp5x_8821_controls, |
| 339 | .num_controls = ARRAY_SIZE(acp5x_8821_controls), | 331 | .num_controls = ARRAY_SIZE(acp5x_8821_controls), |
| 340 | }; | 332 | }; |
| @@ -342,6 +334,7 @@ static struct snd_soc_card acp5x_card = { · 1 unmodified line | |||
| 342 | static int acp5x_vg_quirk_cb(const struct dmi_system_id *id) | 334 | static int acp5x_vg_quirk_cb(const struct dmi_system_id *id) |
| 343 | { | 335 | { |
| 344 | acp5x_machine_id = VG_JUPITER; | 336 | acp5x_machine_id = VG_JUPITER; |
| 337 | |||
| 345 | return 1; | 338 | return 1; |
| 346 | } | 339 | } |
| 347 | 340 | ||
| @@ -358,33 +351,31 @@ static const struct dmi_system_id acp5x_vg_quirk_table[] = { · 10 unmodified lines | |||
| 358 | 351 | ||
| 359 | static int acp5x_probe(struct platform_device *pdev) | 352 | static int acp5x_probe(struct platform_device *pdev) |
| 360 | { | 353 | { |
| 361 | int ret; | ||
| 362 | struct acp5x_platform_info *machine; | 354 | struct acp5x_platform_info *machine; |
| 355 | struct device *dev = &pdev->dev; | ||
| 363 | struct snd_soc_card *card; | 356 | struct snd_soc_card *card; |
| 357 | int ret; | ||
| 364 | 358 | ||
| 365 | machine = devm_kzalloc(&pdev->dev, sizeof(struct acp5x_platform_info), | 359 | machine = devm_kzalloc(dev, sizeof(*machine), GFP_KERNEL); |
| 366 | GFP_KERNEL); | ||
| 367 | if (!machine) | 360 | if (!machine) |
| 368 | return -ENOMEM; | 361 | return -ENOMEM; |
| 369 | 362 | ||
| 370 | dmi_check_system(acp5x_vg_quirk_table); | 363 | dmi_check_system(acp5x_vg_quirk_table); |
| 371 | switch (acp5x_machine_id) { | 364 | switch (acp5x_machine_id) { |
| 372 | case VG_JUPITER: | 365 | case VG_JUPITER: |
| 373 | card = &acp5x_card; | 366 | card = &acp5x_8821_35l41_card; |
| 374 | acp5x_card.dev = &pdev->dev; | ||
| 375 | break; | 367 | break; |
| 376 | default: | 368 | default: |
| 377 | return -ENODEV; | 369 | return -ENODEV; |
| 378 | } | 370 | } |
| 371 | card->dev = dev; | ||
| 379 | platform_set_drvdata(pdev, card); | 372 | platform_set_drvdata(pdev, card); |
| 380 | snd_soc_card_set_drvdata(card, machine); | 373 | snd_soc_card_set_drvdata(card, machine); |
| 381 | 374 | ||
| 382 | ret = devm_snd_soc_register_card(&pdev->dev, card); | 375 | ret = devm_snd_soc_register_card(dev, card); |
| 383 | if (ret) { | 376 | if (ret) |
| 384 | return dev_err_probe(&pdev->dev, ret, | 377 | return dev_err_probe(dev, ret, "Register card (%s) failed\n", card->name); |
| 385 | "snd_soc_register_card(%s) failed\n", | 378 | |
| 386 | acp5x_card.name); | ||
| 387 | } | ||
| 388 | return 0; | 379 | return 0; |
| 389 | } | 380 | } |
| 390 | 381 | ||
| @@ -415,10 +415,9 @@ static int acp5x_audio_probe(struct platform_device *pdev) · 414 unmodified lines | |||
| 415 | return 0; | 415 | return 0; |
| 416 | } | 416 | } |
| 417 | 417 | ||
| 418 | static int acp5x_audio_remove(struct platform_device *pdev) | 418 | static void acp5x_audio_remove(struct platform_device *pdev) |
| 419 | { | 419 | { |
| 420 | pm_runtime_disable(&pdev->dev); | 420 | pm_runtime_disable(&pdev->dev); |
| 421 | return 0; | ||
| 422 | } | 421 | } |
| 423 | 422 | ||
| 424 | static int __maybe_unused acp5x_pcm_resume(struct device *dev) | 423 | static int __maybe_unused acp5x_pcm_resume(struct device *dev) |
| @@ -500,7 +499,7 @@ static const struct dev_pm_ops acp5x_pm_ops = { · 75 unmodified lines | |||
| 500 | 499 | ||
| 501 | static struct platform_driver acp5x_dma_driver = { | 500 | static struct platform_driver acp5x_dma_driver = { |
| 502 | .probe = acp5x_audio_probe, | 501 | .probe = acp5x_audio_probe, |
| 503 | .remove = acp5x_audio_remove, | 502 | .remove_new = acp5x_audio_remove, |
| 504 | .driver = { | 503 | .driver = { |
| 505 | .name = "acp5x_i2s_dma", | 504 | .name = "acp5x_i2s_dma", |
| 506 | .pm = &acp5x_pm_ops, | 505 | .pm = &acp5x_pm_ops, |
| @@ -45,6 +45,13 @@ static struct snd_soc_card acp6x_card = { · 44 unmodified lines | |||
| 45 | }; | 45 | }; |
| 46 | 46 | ||
| 47 | static const struct dmi_system_id yc_acp_quirk_table[] = { | 47 | static const struct dmi_system_id yc_acp_quirk_table[] = { |
| 48 | { | ||
| 49 | .driver_data = &acp6x_card, | ||
| 50 | .matches = { | ||
| 51 | DMI_MATCH(DMI_BOARD_VENDOR, "Dell Inc."), | ||
| 52 | DMI_MATCH(DMI_PRODUCT_NAME, "Dell G15 5525"), | ||
| 53 | } | ||
| 54 | }, | ||
| 48 | { | 55 | { |
| 49 | .driver_data = &acp6x_card, | 56 | .driver_data = &acp6x_card, |
| 50 | .matches = { | 57 | .matches = { |
| @@ -178,6 +185,13 @@ static const struct dmi_system_id yc_acp_quirk_table[] = { · 127 unmodified lines | |||
| 178 | DMI_MATCH(DMI_PRODUCT_NAME, "21EN"), | 185 | DMI_MATCH(DMI_PRODUCT_NAME, "21EN"), |
| 179 | } | 186 | } |
| 180 | }, | 187 | }, |
| 188 | { | ||
| 189 | .driver_data = &acp6x_card, | ||
| 190 | .matches = { | ||
| 191 | DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"), | ||
| 192 | DMI_MATCH(DMI_PRODUCT_NAME, "21HY"), | ||
| 193 | } | ||
| 194 | }, | ||
| 181 | { | 195 | { |
| 182 | .driver_data = &acp6x_card, | 196 | .driver_data = &acp6x_card, |
| 183 | .matches = { | 197 | .matches = { |
| @@ -262,6 +276,13 @@ static const struct dmi_system_id yc_acp_quirk_table[] = { · 78 unmodified lines | |||
| 262 | DMI_MATCH(DMI_PRODUCT_NAME, "OMEN by HP Gaming Laptop 16z-n000"), | 276 | DMI_MATCH(DMI_PRODUCT_NAME, "OMEN by HP Gaming Laptop 16z-n000"), |
| 263 | } | 277 | } |
| 264 | }, | 278 | }, |
| 279 | { | ||
| 280 | .driver_data = &acp6x_card, | ||
| 281 | .matches = { | ||
| 282 | DMI_MATCH(DMI_BOARD_VENDOR, "HP"), | ||
| 283 | DMI_MATCH(DMI_BOARD_NAME, "8A42"), | ||
| 284 | } | ||
| 285 | }, | ||
| 265 | { | 286 | { |
| 266 | .driver_data = &acp6x_card, | 287 | .driver_data = &acp6x_card, |
| 267 | .matches = { | 288 | .matches = { |
| @@ -388,10 +388,9 @@ static int acp6x_pdm_audio_probe(struct platform_device *pdev) · 387 unmodified lines | |||
| 388 | return 0; | 388 | return 0; |
| 389 | } | 389 | } |
| 390 | 390 | ||
| 391 | static int acp6x_pdm_audio_remove(struct platform_device *pdev) | 391 | static void acp6x_pdm_audio_remove(struct platform_device *pdev) |
| 392 | { | 392 | { |
| 393 | pm_runtime_disable(&pdev->dev); | 393 | pm_runtime_disable(&pdev->dev); |
| 394 | return 0; | ||
| 395 | } | 394 | } |
| 396 | 395 | ||
| 397 | static int __maybe_unused acp6x_pdm_resume(struct device *dev) | 396 | static int __maybe_unused acp6x_pdm_resume(struct device *dev) |
| @@ -440,7 +439,7 @@ static const struct dev_pm_ops acp6x_pdm_pm_ops = { · 42 unmodified lines | |||
| 440 | 439 | ||
| 441 | static struct platform_driver acp6x_pdm_dma_driver = { | 440 | static struct platform_driver acp6x_pdm_dma_driver = { |
| 442 | .probe = acp6x_pdm_audio_probe, | 441 | .probe = acp6x_pdm_audio_probe, |
| 443 | .remove = acp6x_pdm_audio_remove, | 442 | .remove_new = acp6x_pdm_audio_remove, |
| 444 | .driver = { | 443 | .driver = { |
| 445 | .name = "acp_yc_pdm_dma", | 444 | .name = "acp_yc_pdm_dma", |
| 446 | .pm = &acp6x_pdm_pm_ops, | 445 | .pm = &acp6x_pdm_pm_ops, |
| @@ -105,3 +105,6 @@ static inline void acp6x_writel(u32 val, void __iomem *base_addr) · 104 unmodified lines | |||
| 105 | { | 105 | { |
| 106 | writel(val, base_addr - ACP6x_PHY_BASE_ADDRESS); | 106 | writel(val, base_addr - ACP6x_PHY_BASE_ADDRESS); |
| 107 | } | 107 | } |
| 108 | |||
| 109 | int snd_amd_acp_find_config(struct pci_dev *pci); | ||
| 110 | |||
| @@ -149,10 +149,16 @@ static int snd_acp6x_probe(struct pci_dev *pci, · 148 unmodified lines | |||
| 149 | int index = 0; | 149 | int index = 0; |
| 150 | int val = 0x00; | 150 | int val = 0x00; |
| 151 | u32 addr; | 151 | u32 addr; |
| 152 | unsigned int irqflags; | 152 | unsigned int irqflags, flag; |
| 153 | int ret; | 153 | int ret; |
| 154 | 154 | ||
| 155 | irqflags = IRQF_SHARED; | 155 | irqflags = IRQF_SHARED; |
| 156 | |||
| 157 | /* Return if acp config flag is defined */ | ||
| 158 | flag = snd_amd_acp_find_config(pci); | ||
| 159 | if (flag) | ||
| 160 | return -ENODEV; | ||
| 161 | |||
| 156 | /* Yellow Carp device check */ | 162 | /* Yellow Carp device check */ |
| 157 | switch (pci->revision) { | 163 | switch (pci->revision) { |
| 158 | case 0x60: | 164 | case 0x60: |
| @@ -1159,13 +1159,12 @@ err_release: · 1158 unmodified lines | |||
| 1159 | return ret; | 1159 | return ret; |
| 1160 | } | 1160 | } |
| 1161 | 1161 | ||
| 1162 | static int apple_mca_remove(struct platform_device *pdev) | 1162 | static void apple_mca_remove(struct platform_device *pdev) |
| 1163 | { | 1163 | { |
| 1164 | struct mca_data *mca = platform_get_drvdata(pdev); | 1164 | struct mca_data *mca = platform_get_drvdata(pdev); |
| 1165 | 1165 | ||
| 1166 | snd_soc_unregister_component(&pdev->dev); | 1166 | snd_soc_unregister_component(&pdev->dev); |
| 1167 | apple_mca_release(mca); | 1167 | apple_mca_release(mca); |
| 1168 | return 0; | ||
| 1169 | } | 1168 | } |
| 1170 | 1169 | ||
| 1171 | static const struct of_device_id apple_mca_of_match[] = { | 1170 | static const struct of_device_id apple_mca_of_match[] = { |
| @@ -1180,7 +1179,7 @@ static struct platform_driver apple_mca_driver = { · 8 unmodified lines | |||
| 1180 | .of_match_table = apple_mca_of_match, | 1179 | .of_match_table = apple_mca_of_match, |
| 1181 | }, | 1180 | }, |
| 1182 | .probe = apple_mca_probe, | 1181 | .probe = apple_mca_probe, |
| 1183 | .remove = apple_mca_remove, | 1182 | .remove_new = apple_mca_remove, |
| 1184 | }; | 1183 | }; |
| 1185 | module_platform_driver(apple_mca_driver); | 1184 | module_platform_driver(apple_mca_driver); |
| 1186 | 1185 | ||
| @@ -473,24 +473,21 @@ static int atmel_classd_asoc_card_init(struct device *dev, · 472 unmodified lines | |||
| 473 | if (!dai_link) | 473 | if (!dai_link) |
| 474 | return -ENOMEM; | 474 | return -ENOMEM; |
| 475 | 475 | ||
| 476 | comp = devm_kzalloc(dev, 3 * sizeof(*comp), GFP_KERNEL); | 476 | comp = devm_kzalloc(dev, 2 * sizeof(*comp), GFP_KERNEL); |
| 477 | if (!comp) | 477 | if (!comp) |
| 478 | return -ENOMEM; | 478 | return -ENOMEM; |
| 479 | 479 | ||
| 480 | dai_link->cpus = &comp[0]; | 480 | dai_link->cpus = &comp[0]; |
| 481 | dai_link->codecs = &comp[1]; | 481 | dai_link->codecs = &comp[1]; |
| 482 | dai_link->platforms = &comp[2]; | ||
| 483 | 482 | ||
| 484 | dai_link->num_cpus = 1; | 483 | dai_link->num_cpus = 1; |
| 485 | dai_link->num_codecs = 1; | 484 | dai_link->num_codecs = 1; |
| 486 | dai_link->num_platforms = 1; | ||
| 487 | 485 | ||
| 488 | dai_link->name = "CLASSD"; | 486 | dai_link->name = "CLASSD"; |
| 489 | dai_link->stream_name = "CLASSD PCM"; | 487 | dai_link->stream_name = "CLASSD PCM"; |
| 490 | dai_link->codecs->dai_name = "snd-soc-dummy-dai"; | 488 | dai_link->codecs->dai_name = "snd-soc-dummy-dai"; |
| 491 | dai_link->cpus->dai_name = dev_name(dev); | 489 | dai_link->cpus->dai_name = dev_name(dev); |
| 492 | dai_link->codecs->name = "snd-soc-dummy"; | 490 | dai_link->codecs->name = "snd-soc-dummy"; |
| 493 | dai_link->platforms->name = dev_name(dev); | ||
| 494 | 491 | ||
| 495 | card->dai_link = dai_link; | 492 | card->dai_link = dai_link; |
| 496 | card->num_links = 1; | 493 | card->num_links = 1; |
| @@ -717,13 +717,11 @@ static int atmel_i2s_probe(struct platform_device *pdev) · 716 unmodified lines | |||
| 717 | return 0; | 717 | return 0; |
| 718 | } | 718 | } |
| 719 | 719 | ||
| 720 | static int atmel_i2s_remove(struct platform_device *pdev) | 720 | static void atmel_i2s_remove(struct platform_device *pdev) |
| 721 | { | 721 | { |
| 722 | struct atmel_i2s_dev *dev = platform_get_drvdata(pdev); | 722 | struct atmel_i2s_dev *dev = platform_get_drvdata(pdev); |
| 723 | 723 | ||
| 724 | clk_disable_unprepare(dev->pclk); | 724 | clk_disable_unprepare(dev->pclk); |
| 725 | |||
| 726 | return 0; | ||
| 727 | } | 725 | } |
| 728 | 726 | ||
| 729 | static struct platform_driver atmel_i2s_driver = { | 727 | static struct platform_driver atmel_i2s_driver = { |
| @@ -732,7 +730,7 @@ static struct platform_driver atmel_i2s_driver = { · 2 unmodified lines | |||
| 732 | .of_match_table = of_match_ptr(atmel_i2s_dt_ids), | 730 | .of_match_table = of_match_ptr(atmel_i2s_dt_ids), |
| 733 | }, | 731 | }, |
| 734 | .probe = atmel_i2s_probe, | 732 | .probe = atmel_i2s_probe, |
| 735 | .remove = atmel_i2s_remove, | 733 | .remove_new = atmel_i2s_remove, |
| 736 | }; | 734 | }; |
| 737 | module_platform_driver(atmel_i2s_driver); | 735 | module_platform_driver(atmel_i2s_driver); |
| 738 | 736 | ||
| @@ -496,24 +496,21 @@ static int atmel_pdmic_asoc_card_init(struct device *dev, · 495 unmodified lines | |||
| 496 | if (!dai_link) | 496 | if (!dai_link) |
| 497 | return -ENOMEM; | 497 | return -ENOMEM; |
| 498 | 498 | ||
| 499 | comp = devm_kzalloc(dev, 3 * sizeof(*comp), GFP_KERNEL); | 499 | comp = devm_kzalloc(dev, 2 * sizeof(*comp), GFP_KERNEL); |
| 500 | if (!comp) | 500 | if (!comp) |
| 501 | return -ENOMEM; | 501 | return -ENOMEM; |
| 502 | 502 | ||
| 503 | dai_link->cpus = &comp[0]; | 503 | dai_link->cpus = &comp[0]; |
| 504 | dai_link->codecs = &comp[1]; | 504 | dai_link->codecs = &comp[1]; |
| 505 | dai_link->platforms = &comp[2]; | ||
| 506 | 505 | ||
| 507 | dai_link->num_cpus = 1; | 506 | dai_link->num_cpus = 1; |
| 508 | dai_link->num_codecs = 1; | 507 | dai_link->num_codecs = 1; |
| 509 | dai_link->num_platforms = 1; | ||
| 510 | 508 | ||
| 511 | dai_link->name = "PDMIC"; | 509 | dai_link->name = "PDMIC"; |
| 512 | dai_link->stream_name = "PDMIC PCM"; | 510 | dai_link->stream_name = "PDMIC PCM"; |
| 513 | dai_link->codecs->dai_name = "snd-soc-dummy-dai"; | 511 | dai_link->codecs->dai_name = "snd-soc-dummy-dai"; |
| 514 | dai_link->cpus->dai_name = dev_name(dev); | 512 | dai_link->cpus->dai_name = dev_name(dev); |
| 515 | dai_link->codecs->name = "snd-soc-dummy"; | 513 | dai_link->codecs->name = "snd-soc-dummy"; |
| 516 | dai_link->platforms->name = dev_name(dev); | ||
| 517 | 514 | ||
| 518 | card->dai_link = dai_link; | 515 | card->dai_link = dai_link; |
| 519 | card->num_links = 1; | 516 | card->num_links = 1; |
| @@ -161,7 +161,7 @@ err_set_audio: · 160 unmodified lines | |||
| 161 | return ret; | 161 | return ret; |
| 162 | } | 162 | } |
| 163 | 163 | ||
| 164 | static int atmel_asoc_wm8904_remove(struct platform_device *pdev) | 164 | static void atmel_asoc_wm8904_remove(struct platform_device *pdev) |
| 165 | { | 165 | { |
| 166 | struct snd_soc_card *card = platform_get_drvdata(pdev); | 166 | struct snd_soc_card *card = platform_get_drvdata(pdev); |
| 167 | struct snd_soc_dai_link *dailink = &atmel_asoc_wm8904_dailink; | 167 | struct snd_soc_dai_link *dailink = &atmel_asoc_wm8904_dailink; |
| @@ -171,8 +171,6 @@ static int atmel_asoc_wm8904_remove(struct platform_device *pdev) · 3 unmodified lines | |||
| 171 | 171 | ||
| 172 | snd_soc_unregister_card(card); | 172 | snd_soc_unregister_card(card); |
| 173 | atmel_ssc_put_audio(id); | 173 | atmel_ssc_put_audio(id); |
| 174 | |||
| 175 | return 0; | ||
| 176 | } | 174 | } |
| 177 | 175 | ||
| 178 | #ifdef CONFIG_OF | 176 | #ifdef CONFIG_OF |
| @@ -190,7 +188,7 @@ static struct platform_driver atmel_asoc_wm8904_driver = { · 11 unmodified lines | |||
| 190 | .pm = &snd_soc_pm_ops, | 188 | .pm = &snd_soc_pm_ops, |
| 191 | }, | 189 | }, |
| 192 | .probe = atmel_asoc_wm8904_probe, | 190 | .probe = atmel_asoc_wm8904_probe, |
| 193 | .remove = atmel_asoc_wm8904_remove, | 191 | .remove_new = atmel_asoc_wm8904_remove, |
| 194 | }; | 192 | }; |
| 195 | 193 | ||
| 196 | module_platform_driver(atmel_asoc_wm8904_driver); | 194 | module_platform_driver(atmel_asoc_wm8904_driver); |
| @@ -1088,13 +1088,11 @@ static int mchp_i2s_mcc_probe(struct platform_device *pdev) · 1087 unmodified lines | |||
| 1088 | return 0; | 1088 | return 0; |
| 1089 | } | 1089 | } |
| 1090 | 1090 | ||
| 1091 | static int mchp_i2s_mcc_remove(struct platform_device *pdev) | 1091 | static void mchp_i2s_mcc_remove(struct platform_device *pdev) |
| 1092 | { | 1092 | { |
| 1093 | struct mchp_i2s_mcc_dev *dev = platform_get_drvdata(pdev); | 1093 | struct mchp_i2s_mcc_dev *dev = platform_get_drvdata(pdev); |
| 1094 | 1094 | ||
| 1095 | clk_disable_unprepare(dev->pclk); | 1095 | clk_disable_unprepare(dev->pclk); |
| 1096 | |||
| 1097 | return 0; | ||
| 1098 | } | 1096 | } |
| 1099 | 1097 | ||
| 1100 | static struct platform_driver mchp_i2s_mcc_driver = { | 1098 | static struct platform_driver mchp_i2s_mcc_driver = { |
| @@ -1103,7 +1101,7 @@ static struct platform_driver mchp_i2s_mcc_driver = { · 2 unmodified lines | |||
| 1103 | .of_match_table = of_match_ptr(mchp_i2s_mcc_dt_ids), | 1101 | .of_match_table = of_match_ptr(mchp_i2s_mcc_dt_ids), |
| 1104 | }, | 1102 | }, |
| 1105 | .probe = mchp_i2s_mcc_probe, | 1103 | .probe = mchp_i2s_mcc_probe, |
| 1106 | .remove = mchp_i2s_mcc_remove, | 1104 | .remove_new = mchp_i2s_mcc_remove, |
| 1107 | }; | 1105 | }; |
| 1108 | module_platform_driver(mchp_i2s_mcc_driver); | 1106 | module_platform_driver(mchp_i2s_mcc_driver); |
| 1109 | 1107 | ||
| @@ -8,6 +8,7 @@ · 7 unmodified lines | |||
| 8 | 8 | ||
| 9 | #include <dt-bindings/sound/microchip,pdmc.h> | 9 | #include <dt-bindings/sound/microchip,pdmc.h> |
| 10 | 10 | ||
| 11 | #include <linux/bitfield.h> | ||
| 11 | #include <linux/clk.h> | 12 | #include <linux/clk.h> |
| 12 | #include <linux/module.h> | 13 | #include <linux/module.h> |
| 13 | #include <linux/of.h> | 14 | #include <linux/of.h> |
| @@ -49,8 +50,6 @@ · 35 unmodified lines | |||
| 49 | #define MCHP_PDMC_MR_OSR256 (3 << 16) | 50 | #define MCHP_PDMC_MR_OSR256 (3 << 16) |
| 50 | 51 | ||
| 51 | #define MCHP_PDMC_MR_SINCORDER_MASK GENMASK(23, 20) | 52 | #define MCHP_PDMC_MR_SINCORDER_MASK GENMASK(23, 20) |
| 52 | #define MCHP_PDMC_MR_SINCORDER(order) (((order) << 20) & \ | ||
| 53 | MCHP_PDMC_MR_SINCORDER_MASK) | ||
| 54 | 53 | ||
| 55 | #define MCHP_PDMC_MR_SINC_OSR_MASK GENMASK(27, 24) | 54 | #define MCHP_PDMC_MR_SINC_OSR_MASK GENMASK(27, 24) |
| 56 | #define MCHP_PDMC_MR_SINC_OSR_DIS (0 << 24) | 55 | #define MCHP_PDMC_MR_SINC_OSR_DIS (0 << 24) |
| @@ -62,8 +61,6 @@ · 5 unmodified lines | |||
| 62 | #define MCHP_PDMC_MR_SINC_OSR_256 (6 << 24) | 61 | #define MCHP_PDMC_MR_SINC_OSR_256 (6 << 24) |
| 63 | 62 | ||
| 64 | #define MCHP_PDMC_MR_CHUNK_MASK GENMASK(31, 28) | 63 | #define MCHP_PDMC_MR_CHUNK_MASK GENMASK(31, 28) |
| 65 | #define MCHP_PDMC_MR_CHUNK(chunk) (((chunk) << 28) & \ | ||
| 66 | MCHP_PDMC_MR_CHUNK_MASK) | ||
| 67 | 64 | ||
| 68 | /* | 65 | /* |
| 69 | * ---- Configuration Register (Read/Write) ---- | 66 | * ---- Configuration Register (Read/Write) ---- |
| @@ -617,10 +614,10 @@ static int mchp_pdmc_hw_params(struct snd_pcm_substream *substream, · 547 unmodified lines | |||
| 617 | 614 | ||
| 618 | mr_val |= mchp_pdmc_mr_set_osr(dd->audio_filter_en, osr); | 615 | mr_val |= mchp_pdmc_mr_set_osr(dd->audio_filter_en, osr); |
| 619 | 616 | ||
| 620 | mr_val |= MCHP_PDMC_MR_SINCORDER(dd->sinc_order); | 617 | mr_val |= FIELD_PREP(MCHP_PDMC_MR_SINCORDER_MASK, dd->sinc_order); |
| 621 | 618 | ||
| 622 | dd->addr.maxburst = mchp_pdmc_period_to_maxburst(snd_pcm_lib_period_bytes(substream)); | 619 | dd->addr.maxburst = mchp_pdmc_period_to_maxburst(snd_pcm_lib_period_bytes(substream)); |
| 623 | mr_val |= MCHP_PDMC_MR_CHUNK(dd->addr.maxburst); | 620 | mr_val |= FIELD_PREP(MCHP_PDMC_MR_CHUNK_MASK, dd->addr.maxburst); |
| 624 | dev_dbg(comp->dev, "maxburst set to %d\n", dd->addr.maxburst); | 621 | dev_dbg(comp->dev, "maxburst set to %d\n", dd->addr.maxburst); |
| 625 | 622 | ||
| 626 | snd_soc_component_update_bits(comp, MCHP_PDMC_MR, | 623 | snd_soc_component_update_bits(comp, MCHP_PDMC_MR, |
| @@ -762,12 +759,10 @@ static int mchp_pdmc_pcm_new(struct snd_soc_pcm_runtime *rtd, · 135 unmodified lines | |||
| 762 | int ret; | 759 | int ret; |
| 763 | 760 | ||
| 764 | ret = mchp_pdmc_add_chmap_ctls(rtd->pcm, dd); | 761 | ret = mchp_pdmc_add_chmap_ctls(rtd->pcm, dd); |
| 765 | if (ret < 0) { | 762 | if (ret < 0) |
| 766 | dev_err(dd->dev, "failed to add channel map controls: %d\n", ret); | 763 | dev_err(dd->dev, "failed to add channel map controls: %d\n", ret); |
| 767 | return ret; | ||
| 768 | } | ||
| 769 | 764 | ||
| 770 | return 0; | 765 | return ret; |
| 771 | } | 766 | } |
| 772 | 767 | ||
| 773 | static struct snd_soc_dai_driver mchp_pdmc_dai = { | 768 | static struct snd_soc_dai_driver mchp_pdmc_dai = { |
| @@ -788,7 +783,7 @@ static struct snd_soc_dai_driver mchp_pdmc_dai = { · 14 unmodified lines | |||
| 788 | /* PDMC interrupt handler */ | 783 | /* PDMC interrupt handler */ |
| 789 | static irqreturn_t mchp_pdmc_interrupt(int irq, void *dev_id) | 784 | static irqreturn_t mchp_pdmc_interrupt(int irq, void *dev_id) |
| 790 | { | 785 | { |
| 791 | struct mchp_pdmc *dd = (struct mchp_pdmc *)dev_id; | 786 | struct mchp_pdmc *dd = dev_id; |
| 792 | u32 isr, msr, pending; | 787 | u32 isr, msr, pending; |
| 793 | irqreturn_t ret = IRQ_NONE; | 788 | irqreturn_t ret = IRQ_NONE; |
| 794 | 789 | ||
| @@ -1082,7 +1077,7 @@ static int mchp_pdmc_probe(struct platform_device *pdev) · 287 unmodified lines | |||
| 1082 | } | 1077 | } |
| 1083 | 1078 | ||
| 1084 | ret = devm_request_irq(dev, irq, mchp_pdmc_interrupt, 0, | 1079 | ret = devm_request_irq(dev, irq, mchp_pdmc_interrupt, 0, |
| 1085 | dev_name(&pdev->dev), (void *)dd); | 1080 | dev_name(&pdev->dev), dd); |
| 1086 | if (ret < 0) { | 1081 | if (ret < 0) { |
| 1087 | dev_err(dev, "can't register ISR for IRQ %u (ret=%i)\n", | 1082 | dev_err(dev, "can't register ISR for IRQ %u (ret=%i)\n", |
| 1088 | irq, ret); | 1083 | irq, ret); |
| @@ -1134,7 +1129,7 @@ pm_runtime_suspend: · 45 unmodified lines | |||
| 1134 | return ret; | 1129 | return ret; |
| 1135 | } | 1130 | } |
| 1136 | 1131 | ||
| 1137 | static int mchp_pdmc_remove(struct platform_device *pdev) | 1132 | static void mchp_pdmc_remove(struct platform_device *pdev) |
| 1138 | { | 1133 | { |
| 1139 | struct mchp_pdmc *dd = platform_get_drvdata(pdev); | 1134 | struct mchp_pdmc *dd = platform_get_drvdata(pdev); |
| 1140 | 1135 | ||
| @@ -1142,8 +1137,6 @@ static int mchp_pdmc_remove(struct platform_device *pdev) · 1 unmodified line | |||
| 1142 | mchp_pdmc_runtime_suspend(dd->dev); | 1137 | mchp_pdmc_runtime_suspend(dd->dev); |
| 1143 | 1138 | ||
| 1144 | pm_runtime_disable(dd->dev); | 1139 | pm_runtime_disable(dd->dev); |
| 1145 | |||
| 1146 | return 0; | ||
| 1147 | } | 1140 | } |
| 1148 | 1141 | ||
| 1149 | static const struct of_device_id mchp_pdmc_of_match[] = { | 1142 | static const struct of_device_id mchp_pdmc_of_match[] = { |
| @@ -1168,7 +1161,7 @@ static struct platform_driver mchp_pdmc_driver = { · 18 unmodified lines | |||
| 1168 | .pm = pm_ptr(&mchp_pdmc_pm_ops), | 1161 | .pm = pm_ptr(&mchp_pdmc_pm_ops), |
| 1169 | }, | 1162 | }, |
| 1170 | .probe = mchp_pdmc_probe, | 1163 | .probe = mchp_pdmc_probe, |
| 1171 | .remove = mchp_pdmc_remove, | 1164 | .remove_new = mchp_pdmc_remove, |
| 1172 | }; | 1165 | }; |
| 1173 | module_platform_driver(mchp_pdmc_driver); | 1166 | module_platform_driver(mchp_pdmc_driver); |
| 1174 | 1167 | ||
| @@ -1183,20 +1183,18 @@ pm_runtime_disable: · 1182 unmodified lines | |||
| 1183 | return err; | 1183 | return err; |
| 1184 | } | 1184 | } |
| 1185 | 1185 | ||
| 1186 | static int mchp_spdifrx_remove(struct platform_device *pdev) | 1186 | static void mchp_spdifrx_remove(struct platform_device *pdev) |
| 1187 | { | 1187 | { |
| 1188 | struct mchp_spdifrx_dev *dev = platform_get_drvdata(pdev); | 1188 | struct mchp_spdifrx_dev *dev = platform_get_drvdata(pdev); |
| 1189 | 1189 | ||
| 1190 | pm_runtime_disable(dev->dev); | 1190 | pm_runtime_disable(dev->dev); |
| 1191 | if (!pm_runtime_status_suspended(dev->dev)) | 1191 | if (!pm_runtime_status_suspended(dev->dev)) |
| 1192 | mchp_spdifrx_runtime_suspend(dev->dev); | 1192 | mchp_spdifrx_runtime_suspend(dev->dev); |
| 1193 | |||
| 1194 | return 0; | ||
| 1195 | } | 1193 | } |
| 1196 | 1194 | ||
| 1197 | static struct platform_driver mchp_spdifrx_driver = { | 1195 | static struct platform_driver mchp_spdifrx_driver = { |
| 1198 | .probe = mchp_spdifrx_probe, | 1196 | .probe = mchp_spdifrx_probe, |
| 1199 | .remove = mchp_spdifrx_remove, | 1197 | .remove_new = mchp_spdifrx_remove, |
| 1200 | .driver = { | 1198 | .driver = { |
| 1201 | .name = "mchp_spdifrx", | 1199 | .name = "mchp_spdifrx", |
| 1202 | .of_match_table = of_match_ptr(mchp_spdifrx_dt_ids), | 1200 | .of_match_table = of_match_ptr(mchp_spdifrx_dt_ids), |
| @@ -72,11 +72,9 @@ · 71 unmodified lines | |||
| 72 | 72 | ||
| 73 | /* Valid Bits per Sample */ | 73 | /* Valid Bits per Sample */ |
| 74 | #define SPDIFTX_MR_VBPS_MASK GENMASK(13, 8) | 74 | #define SPDIFTX_MR_VBPS_MASK GENMASK(13, 8) |
| 75 | #define SPDIFTX_MR_VBPS(bps) FIELD_PREP(SPDIFTX_MR_VBPS_MASK, bps) | ||
| 76 | 75 | ||
| 77 | /* Chunk Size */ | 76 | /* Chunk Size */ |
| 78 | #define SPDIFTX_MR_CHUNK_MASK GENMASK(19, 16) | 77 | #define SPDIFTX_MR_CHUNK_MASK GENMASK(19, 16) |
| 79 | #define SPDIFTX_MR_CHUNK(size) FIELD_PREP(SPDIFTX_MR_CHUNK_MASK, size) | ||
| 80 | 78 | ||
| 81 | /* Validity Bits for Channels 1 and 2 */ | 79 | /* Validity Bits for Channels 1 and 2 */ |
| 82 | #define SPDIFTX_MR_VALID1 BIT(24) | 80 | #define SPDIFTX_MR_VALID1 BIT(24) |
| @@ -89,7 +87,6 @@ · 6 unmodified lines | |||
| 89 | 87 | ||
| 90 | /* Bytes per Sample */ | 88 | /* Bytes per Sample */ |
| 91 | #define SPDIFTX_MR_BPS_MASK GENMASK(29, 28) | 89 | #define SPDIFTX_MR_BPS_MASK GENMASK(29, 28) |
| 92 | #define SPDIFTX_MR_BPS(bytes) FIELD_PREP(SPDIFTX_MR_BPS_MASK, (bytes - 1)) | ||
| 93 | 90 | ||
| 94 | /* | 91 | /* |
| 95 | * ---- Interrupt Enable/Disable/Mask/Status Register (Write/Read-only) ---- | 92 | * ---- Interrupt Enable/Disable/Mask/Status Register (Write/Read-only) ---- |
| @@ -309,15 +306,10 @@ static int mchp_spdiftx_trigger(struct snd_pcm_substream *substream, int cmd, · 213 unmodified lines | |||
| 309 | { | 306 | { |
| 310 | struct mchp_spdiftx_dev *dev = snd_soc_dai_get_drvdata(dai); | 307 | struct mchp_spdiftx_dev *dev = snd_soc_dai_get_drvdata(dai); |
| 311 | struct mchp_spdiftx_mixer_control *ctrl = &dev->control; | 308 | struct mchp_spdiftx_mixer_control *ctrl = &dev->control; |
| 312 | u32 mr; | ||
| 313 | int running; | ||
| 314 | int ret; | 309 | int ret; |
| 315 | 310 | ||
| 316 | /* do not start/stop while channel status or user data is updated */ | 311 | /* do not start/stop while channel status or user data is updated */ |
| 317 | spin_lock(&ctrl->lock); | 312 | spin_lock(&ctrl->lock); |
| 318 | regmap_read(dev->regmap, SPDIFTX_MR, &mr); | ||
| 319 | running = !!(mr & SPDIFTX_MR_TXEN_ENABLE); | ||
| 320 | |||
| 321 | switch (cmd) { | 313 | switch (cmd) { |
| 322 | case SNDRV_PCM_TRIGGER_RESUME: | 314 | case SNDRV_PCM_TRIGGER_RESUME: |
| 323 | case SNDRV_PCM_TRIGGER_START: | 315 | case SNDRV_PCM_TRIGGER_START: |
| @@ -326,10 +318,8 @@ static int mchp_spdiftx_trigger(struct snd_pcm_substream *substream, int cmd, · 2 unmodified lines | |||
| 326 | dev->suspend_irq = 0; | 318 | dev->suspend_irq = 0; |
| 327 | fallthrough; | 319 | fallthrough; |
| 328 | case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: | 320 | case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: |
| 329 | if (!running) { | 321 | ret = regmap_update_bits(dev->regmap, SPDIFTX_MR, SPDIFTX_MR_TXEN_MASK, |
| 330 | mr &= ~SPDIFTX_MR_TXEN_MASK; | 322 | SPDIFTX_MR_TXEN_ENABLE); |
| 331 | mr |= SPDIFTX_MR_TXEN_ENABLE; | ||
| 332 | } | ||
| 333 | break; | 323 | break; |
| 334 | case SNDRV_PCM_TRIGGER_SUSPEND: | 324 | case SNDRV_PCM_TRIGGER_SUSPEND: |
| 335 | regmap_read(dev->regmap, SPDIFTX_IMR, &dev->suspend_irq); | 325 | regmap_read(dev->regmap, SPDIFTX_IMR, &dev->suspend_irq); |
| @@ -339,20 +329,15 @@ static int mchp_spdiftx_trigger(struct snd_pcm_substream *substream, int cmd, · 3 unmodified lines | |||
| 339 | SPDIFTX_IR_TXUDR | SPDIFTX_IR_TXOVR); | 329 | SPDIFTX_IR_TXUDR | SPDIFTX_IR_TXOVR); |
| 340 | fallthrough; | 330 | fallthrough; |
| 341 | case SNDRV_PCM_TRIGGER_PAUSE_PUSH: | 331 | case SNDRV_PCM_TRIGGER_PAUSE_PUSH: |
| 342 | if (running) { | 332 | ret = regmap_update_bits(dev->regmap, SPDIFTX_MR, SPDIFTX_MR_TXEN_MASK, |
| 343 | mr &= ~SPDIFTX_MR_TXEN_MASK; | 333 | SPDIFTX_MR_TXEN_DISABLE); |
| 344 | mr |= SPDIFTX_MR_TXEN_DISABLE; | ||
| 345 | } | ||
| 346 | break; | 334 | break; |
| 347 | default: | 335 | default: |
| 348 | spin_unlock(&ctrl->lock); | 336 | ret = -EINVAL; |
| 349 | return -EINVAL; | ||
| 350 | } | 337 | } |
| 351 | |||
| 352 | ret = regmap_write(dev->regmap, SPDIFTX_MR, mr); | ||
| 353 | spin_unlock(&ctrl->lock); | 338 | spin_unlock(&ctrl->lock); |
| 354 | if (ret) | 339 | if (ret) |
| 355 | dev_err(dev->dev, "unable to disable TX: %d\n", ret); | 340 | dev_err(dev->dev, "unable to start/stop TX: %d\n", ret); |
| 356 | 341 | ||
| 357 | return ret; | 342 | return ret; |
| 358 | } | 343 | } |
| @@ -402,47 +387,47 @@ static int mchp_spdiftx_hw_params(struct snd_pcm_substream *substream, · 43 unmodified lines | |||
| 402 | params_channels(params)); | 387 | params_channels(params)); |
| 403 | return -EINVAL; | 388 | return -EINVAL; |
| 404 | } | 389 | } |
| 405 | mr |= SPDIFTX_MR_CHUNK(dev->playback.maxburst); | 390 | mr |= FIELD_PREP(SPDIFTX_MR_CHUNK_MASK, dev->playback.maxburst); |
| 406 | 391 | ||
| 407 | switch (params_format(params)) { | 392 | switch (params_format(params)) { |
| 408 | case SNDRV_PCM_FORMAT_S8: | 393 | case SNDRV_PCM_FORMAT_S8: |
| 409 | mr |= SPDIFTX_MR_VBPS(8); | 394 | mr |= FIELD_PREP(SPDIFTX_MR_VBPS_MASK, 8); |
| 410 | break; | 395 | break; |
| 411 | case SNDRV_PCM_FORMAT_S16_BE: | 396 | case SNDRV_PCM_FORMAT_S16_BE: |
| 412 | mr |= SPDIFTX_MR_ENDIAN_BIG; | 397 | mr |= SPDIFTX_MR_ENDIAN_BIG; |
| 413 | fallthrough; | 398 | fallthrough; |
| 414 | case SNDRV_PCM_FORMAT_S16_LE: | 399 | case SNDRV_PCM_FORMAT_S16_LE: |
| 415 | mr |= SPDIFTX_MR_VBPS(16); | 400 | mr |= FIELD_PREP(SPDIFTX_MR_VBPS_MASK, 16); |
| 416 | break; | 401 | break; |
| 417 | case SNDRV_PCM_FORMAT_S18_3BE: | 402 | case SNDRV_PCM_FORMAT_S18_3BE: |
| 418 | mr |= SPDIFTX_MR_ENDIAN_BIG; | 403 | mr |= SPDIFTX_MR_ENDIAN_BIG; |
| 419 | fallthrough; | 404 | fallthrough; |
| 420 | case SNDRV_PCM_FORMAT_S18_3LE: | 405 | case SNDRV_PCM_FORMAT_S18_3LE: |
| 421 | mr |= SPDIFTX_MR_VBPS(18); | 406 | mr |= FIELD_PREP(SPDIFTX_MR_VBPS_MASK, 18); |
| 422 | break; | 407 | break; |
| 423 | case SNDRV_PCM_FORMAT_S20_3BE: | 408 | case SNDRV_PCM_FORMAT_S20_3BE: |
| 424 | mr |= SPDIFTX_MR_ENDIAN_BIG; | 409 | mr |= SPDIFTX_MR_ENDIAN_BIG; |
| 425 | fallthrough; | 410 | fallthrough; |
| 426 | case SNDRV_PCM_FORMAT_S20_3LE: | 411 | case SNDRV_PCM_FORMAT_S20_3LE: |
| 427 | mr |= SPDIFTX_MR_VBPS(20); | 412 | mr |= FIELD_PREP(SPDIFTX_MR_VBPS_MASK, 20); |
| 428 | break; | 413 | break; |
| 429 | case SNDRV_PCM_FORMAT_S24_3BE: | 414 | case SNDRV_PCM_FORMAT_S24_3BE: |
| 430 | mr |= SPDIFTX_MR_ENDIAN_BIG; | 415 | mr |= SPDIFTX_MR_ENDIAN_BIG; |
| 431 | fallthrough; | 416 | fallthrough; |
| 432 | case SNDRV_PCM_FORMAT_S24_3LE: | 417 | case SNDRV_PCM_FORMAT_S24_3LE: |
| 433 | mr |= SPDIFTX_MR_VBPS(24); | 418 | mr |= FIELD_PREP(SPDIFTX_MR_VBPS_MASK, 24); |
| 434 | break; | 419 | break; |
| 435 | case SNDRV_PCM_FORMAT_S24_BE: | 420 | case SNDRV_PCM_FORMAT_S24_BE: |
| 436 | mr |= SPDIFTX_MR_ENDIAN_BIG; | 421 | mr |= SPDIFTX_MR_ENDIAN_BIG; |
| 437 | fallthrough; | 422 | fallthrough; |
| 438 | case SNDRV_PCM_FORMAT_S24_LE: | 423 | case SNDRV_PCM_FORMAT_S24_LE: |
| 439 | mr |= SPDIFTX_MR_VBPS(24); | 424 | mr |= FIELD_PREP(SPDIFTX_MR_VBPS_MASK, 24); |
| 440 | break; | 425 | break; |
| 441 | case SNDRV_PCM_FORMAT_S32_BE: | 426 | case SNDRV_PCM_FORMAT_S32_BE: |
| 442 | mr |= SPDIFTX_MR_ENDIAN_BIG; | 427 | mr |= SPDIFTX_MR_ENDIAN_BIG; |
| 443 | fallthrough; | 428 | fallthrough; |
| 444 | case SNDRV_PCM_FORMAT_S32_LE: | 429 | case SNDRV_PCM_FORMAT_S32_LE: |
| 445 | mr |= SPDIFTX_MR_VBPS(32); | 430 | mr |= FIELD_PREP(SPDIFTX_MR_VBPS_MASK, 32); |
| 446 | break; | 431 | break; |
| 447 | default: | 432 | default: |
| 448 | dev_err(dev->dev, "unsupported PCM format: %d\n", | 433 | dev_err(dev->dev, "unsupported PCM format: %d\n", |
| @@ -450,7 +435,7 @@ static int mchp_spdiftx_hw_params(struct snd_pcm_substream *substream, · 1 unmodified line | |||
| 450 | return -EINVAL; | 435 | return -EINVAL; |
| 451 | } | 436 | } |
| 452 | 437 | ||
| 453 | mr |= SPDIFTX_MR_BPS(bps); | 438 | mr |= FIELD_PREP(SPDIFTX_MR_BPS_MASK, bps - 1); |
| 454 | 439 | ||
| 455 | switch (params_rate(params)) { | 440 | switch (params_rate(params)) { |
| 456 | case 22050: | 441 | case 22050: |
| @@ -891,7 +876,7 @@ pm_runtime_suspend: · 434 unmodified lines | |||
| 891 | return err; | 876 | return err; |
| 892 | } | 877 | } |
| 893 | 878 | ||
| 894 | static int mchp_spdiftx_remove(struct platform_device *pdev) | 879 | static void mchp_spdiftx_remove(struct platform_device *pdev) |
| 895 | { | 880 | { |
| 896 | struct mchp_spdiftx_dev *dev = platform_get_drvdata(pdev); | 881 | struct mchp_spdiftx_dev *dev = platform_get_drvdata(pdev); |
| 897 | 882 | ||
| @@ -899,13 +884,11 @@ static int mchp_spdiftx_remove(struct platform_device *pdev) · 1 unmodified line | |||
| 899 | mchp_spdiftx_runtime_suspend(dev->dev); | 884 | mchp_spdiftx_runtime_suspend(dev->dev); |
| 900 | 885 | ||
| 901 | pm_runtime_disable(dev->dev); | 886 | pm_runtime_disable(dev->dev); |
| 902 | |||
| 903 | return 0; | ||
| 904 | } | 887 | } |
| 905 | 888 | ||
| 906 | static struct platform_driver mchp_spdiftx_driver = { | 889 | static struct platform_driver mchp_spdiftx_driver = { |
| 907 | .probe = mchp_spdiftx_probe, | 890 | .probe = mchp_spdiftx_probe, |
| 908 | .remove = mchp_spdiftx_remove, | 891 | .remove_new = mchp_spdiftx_remove, |
| 909 | .driver = { | 892 | .driver = { |
| 910 | .name = "mchp_spdiftx", | 893 | .name = "mchp_spdiftx", |
| 911 | .of_match_table = of_match_ptr(mchp_spdiftx_dt_ids), | 894 | .of_match_table = of_match_ptr(mchp_spdiftx_dt_ids), |
| @@ -155,11 +155,9 @@ put_codec_node: · 154 unmodified lines | |||
| 155 | return ret; | 155 | return ret; |
| 156 | } | 156 | } |
| 157 | 157 | ||
| 158 | static int snd_proto_remove(struct platform_device *pdev) | 158 | static void snd_proto_remove(struct platform_device *pdev) |
| 159 | { | 159 | { |
| 160 | snd_soc_unregister_card(&snd_proto); | 160 | snd_soc_unregister_card(&snd_proto); |
| 161 | |||
| 162 | return 0; | ||
| 163 | } | 161 | } |
| 164 | 162 | ||
| 165 | static const struct of_device_id snd_proto_of_match[] = { | 163 | static const struct of_device_id snd_proto_of_match[] = { |
| @@ -174,7 +172,7 @@ static struct platform_driver snd_proto_driver = { · 8 unmodified lines | |||
| 174 | .of_match_table = snd_proto_of_match, | 172 | .of_match_table = snd_proto_of_match, |
| 175 | }, | 173 | }, |
| 176 | .probe = snd_proto_probe, | 174 | .probe = snd_proto_probe, |
| 177 | .remove = snd_proto_remove, | 175 | .remove_new = snd_proto_remove, |
| 178 | }; | 176 | }; |
| 179 | 177 | ||
| 180 | module_platform_driver(snd_proto_driver); | 178 | module_platform_driver(snd_proto_driver); |
| @@ -186,14 +186,12 @@ err: · 185 unmodified lines | |||
| 186 | return ret; | 186 | return ret; |
| 187 | } | 187 | } |
| 188 | 188 | ||
| 189 | static int at91sam9g20ek_audio_remove(struct platform_device *pdev) | 189 | static void at91sam9g20ek_audio_remove(struct platform_device *pdev) |
| 190 | { | 190 | { |
| 191 | struct snd_soc_card *card = platform_get_drvdata(pdev); | 191 | struct snd_soc_card *card = platform_get_drvdata(pdev); |
| 192 | 192 | ||
| 193 | snd_soc_unregister_card(card); | 193 | snd_soc_unregister_card(card); |
| 194 | atmel_ssc_put_audio(0); | 194 | atmel_ssc_put_audio(0); |
| 195 | |||
| 196 | return 0; | ||
| 197 | } | 195 | } |
| 198 | 196 | ||
| 199 | #ifdef CONFIG_OF | 197 | #ifdef CONFIG_OF |
| @@ -210,7 +208,7 @@ static struct platform_driver at91sam9g20ek_audio_driver = { · 10 unmodified lines | |||
| 210 | .of_match_table = of_match_ptr(at91sam9g20ek_wm8731_dt_ids), | 208 | .of_match_table = of_match_ptr(at91sam9g20ek_wm8731_dt_ids), |
| 211 | }, | 209 | }, |
| 212 | .probe = at91sam9g20ek_audio_probe, | 210 | .probe = at91sam9g20ek_audio_probe, |
| 213 | .remove = at91sam9g20ek_audio_remove, | 211 | .remove_new = at91sam9g20ek_audio_remove, |
| 214 | }; | 212 | }; |
| 215 | 213 | ||
| 216 | module_platform_driver(at91sam9g20ek_audio_driver); | 214 | module_platform_driver(at91sam9g20ek_audio_driver); |
| @@ -176,14 +176,12 @@ out: · 175 unmodified lines | |||
| 176 | return ret; | 176 | return ret; |
| 177 | } | 177 | } |
| 178 | 178 | ||
| 179 | static int sam9x5_wm8731_driver_remove(struct platform_device *pdev) | 179 | static void sam9x5_wm8731_driver_remove(struct platform_device *pdev) |
| 180 | { | 180 | { |
| 181 | struct snd_soc_card *card = platform_get_drvdata(pdev); | 181 | struct snd_soc_card *card = platform_get_drvdata(pdev); |
| 182 | struct sam9x5_drvdata *priv = card->drvdata; | 182 | struct sam9x5_drvdata *priv = card->drvdata; |
| 183 | 183 | ||
| 184 | atmel_ssc_put_audio(priv->ssc_id); | 184 | atmel_ssc_put_audio(priv->ssc_id); |
| 185 | |||
| 186 | return 0; | ||
| 187 | } | 185 | } |
| 188 | 186 | ||
| 189 | static const struct of_device_id sam9x5_wm8731_of_match[] = { | 187 | static const struct of_device_id sam9x5_wm8731_of_match[] = { |
| @@ -198,7 +196,7 @@ static struct platform_driver sam9x5_wm8731_driver = { · 8 unmodified lines | |||
| 198 | .of_match_table = of_match_ptr(sam9x5_wm8731_of_match), | 196 | .of_match_table = of_match_ptr(sam9x5_wm8731_of_match), |
| 199 | }, | 197 | }, |
| 200 | .probe = sam9x5_wm8731_driver_probe, | 198 | .probe = sam9x5_wm8731_driver_probe, |
| 201 | .remove = sam9x5_wm8731_driver_remove, | 199 | .remove_new = sam9x5_wm8731_driver_remove, |
| 202 | }; | 200 | }; |
| 203 | module_platform_driver(sam9x5_wm8731_driver); | 201 | module_platform_driver(sam9x5_wm8731_driver); |
| 204 | 202 | ||
| @@ -412,15 +412,13 @@ err_disable_ana: · 411 unmodified lines | |||
| 412 | return ret; | 412 | return ret; |
| 413 | } | 413 | } |
| 414 | 414 | ||
| 415 | static int tse850_remove(struct platform_device *pdev) | 415 | static void tse850_remove(struct platform_device *pdev) |
| 416 | { | 416 | { |
| 417 | struct snd_soc_card *card = platform_get_drvdata(pdev); | 417 | struct snd_soc_card *card = platform_get_drvdata(pdev); |
| 418 | struct tse850_priv *tse850 = snd_soc_card_get_drvdata(card); | 418 | struct tse850_priv *tse850 = snd_soc_card_get_drvdata(card); |
| 419 | 419 | ||
| 420 | snd_soc_unregister_card(card); | 420 | snd_soc_unregister_card(card); |
| 421 | regulator_disable(tse850->ana); | 421 | regulator_disable(tse850->ana); |
| 422 | |||
| 423 | return 0; | ||
| 424 | } | 422 | } |
| 425 | 423 | ||
| 426 | static const struct of_device_id tse850_dt_ids[] = { | 424 | static const struct of_device_id tse850_dt_ids[] = { |
| @@ -435,7 +433,7 @@ static struct platform_driver tse850_driver = { · 8 unmodified lines | |||
| 435 | .of_match_table = of_match_ptr(tse850_dt_ids), | 433 | .of_match_table = of_match_ptr(tse850_dt_ids), |
| 436 | }, | 434 | }, |
| 437 | .probe = tse850_probe, | 435 | .probe = tse850_probe, |
| 438 | .remove = tse850_remove, | 436 | .remove_new = tse850_remove, |
| 439 | }; | 437 | }; |
| 440 | 438 | ||
| 441 | module_platform_driver(tse850_driver); | 439 | module_platform_driver(tse850_driver); |
| @@ -285,7 +285,7 @@ static int au1xac97c_drvprobe(struct platform_device *pdev) · 284 unmodified lines | |||
| 285 | return 0; | 285 | return 0; |
| 286 | } | 286 | } |
| 287 | 287 | ||
| 288 | static int au1xac97c_drvremove(struct platform_device *pdev) | 288 | static void au1xac97c_drvremove(struct platform_device *pdev) |
| 289 | { | 289 | { |
| 290 | struct au1xpsc_audio_data *ctx = platform_get_drvdata(pdev); | 290 | struct au1xpsc_audio_data *ctx = platform_get_drvdata(pdev); |
| 291 | 291 | ||
| @@ -294,8 +294,6 @@ static int au1xac97c_drvremove(struct platform_device *pdev) · 2 unmodified lines | |||
| 294 | WR(ctx, AC97_ENABLE, EN_D); /* clock off, disable */ | 294 | WR(ctx, AC97_ENABLE, EN_D); /* clock off, disable */ |
| 295 | 295 | ||
| 296 | ac97c_workdata = NULL; /* MDEV */ | 296 | ac97c_workdata = NULL; /* MDEV */ |
| 297 | |||
| 298 | return 0; | ||
| 299 | } | 297 | } |
| 300 | 298 | ||
| 301 | #ifdef CONFIG_PM | 299 | #ifdef CONFIG_PM |
| @@ -338,7 +336,7 @@ static struct platform_driver au1xac97c_driver = { · 36 unmodified lines | |||
| 338 | .pm = AU1XPSCAC97_PMOPS, | 336 | .pm = AU1XPSCAC97_PMOPS, |
| 339 | }, | 337 | }, |
| 340 | .probe = au1xac97c_drvprobe, | 338 | .probe = au1xac97c_drvprobe, |
| 341 | .remove = au1xac97c_drvremove, | 339 | .remove_new = au1xac97c_drvremove, |
| 342 | }; | 340 | }; |
| 343 | 341 | ||
| 344 | module_platform_driver(au1xac97c_driver); | 342 | module_platform_driver(au1xac97c_driver); |
| @@ -270,15 +270,13 @@ static int au1xi2s_drvprobe(struct platform_device *pdev) · 269 unmodified lines | |||
| 270 | &au1xi2s_dai_driver, 1); | 270 | &au1xi2s_dai_driver, 1); |
| 271 | } | 271 | } |
| 272 | 272 | ||
| 273 | static int au1xi2s_drvremove(struct platform_device *pdev) | 273 | static void au1xi2s_drvremove(struct platform_device *pdev) |
| 274 | { | 274 | { |
| 275 | struct au1xpsc_audio_data *ctx = platform_get_drvdata(pdev); | 275 | struct au1xpsc_audio_data *ctx = platform_get_drvdata(pdev); |
| 276 | 276 | ||
| 277 | snd_soc_unregister_component(&pdev->dev); | 277 | snd_soc_unregister_component(&pdev->dev); |
| 278 | 278 | ||
| 279 | WR(ctx, I2S_ENABLE, EN_D); /* clock off, disable */ | 279 | WR(ctx, I2S_ENABLE, EN_D); /* clock off, disable */ |
| 280 | |||
| 281 | return 0; | ||
| 282 | } | 280 | } |
| 283 | 281 | ||
| 284 | #ifdef CONFIG_PM | 282 | #ifdef CONFIG_PM |
| @@ -315,7 +313,7 @@ static struct platform_driver au1xi2s_driver = { · 30 unmodified lines | |||
| 315 | .pm = AU1XI2SC_PMOPS, | 313 | .pm = AU1XI2SC_PMOPS, |
| 316 | }, | 314 | }, |
| 317 | .probe = au1xi2s_drvprobe, | 315 | .probe = au1xi2s_drvprobe, |
| 318 | .remove = au1xi2s_drvremove, | 316 | .remove_new = au1xi2s_drvremove, |
| 319 | }; | 317 | }; |
| 320 | 318 | ||
| 321 | module_platform_driver(au1xi2s_driver); | 319 | module_platform_driver(au1xi2s_driver); |
| @@ -421,7 +421,7 @@ static int au1xpsc_ac97_drvprobe(struct platform_device *pdev) · 420 unmodified lines | |||
| 421 | return 0; | 421 | return 0; |
| 422 | } | 422 | } |
| 423 | 423 | ||
| 424 | static int au1xpsc_ac97_drvremove(struct platform_device *pdev) | 424 | static void au1xpsc_ac97_drvremove(struct platform_device *pdev) |
| 425 | { | 425 | { |
| 426 | struct au1xpsc_audio_data *wd = platform_get_drvdata(pdev); | 426 | struct au1xpsc_audio_data *wd = platform_get_drvdata(pdev); |
| 427 | 427 | ||
| @@ -434,8 +434,6 @@ static int au1xpsc_ac97_drvremove(struct platform_device *pdev) · 6 unmodified lines | |||
| 434 | wmb(); /* drain writebuffer */ | 434 | wmb(); /* drain writebuffer */ |
| 435 | 435 | ||
| 436 | au1xpsc_ac97_workdata = NULL; /* MDEV */ | 436 | au1xpsc_ac97_workdata = NULL; /* MDEV */ |
| 437 | |||
| 438 | return 0; | ||
| 439 | } | 437 | } |
| 440 | 438 | ||
| 441 | #ifdef CONFIG_PM | 439 | #ifdef CONFIG_PM |
| @@ -488,7 +486,7 @@ static struct platform_driver au1xpsc_ac97_driver = { · 46 unmodified lines | |||
| 488 | .pm = AU1XPSCAC97_PMOPS, | 486 | .pm = AU1XPSCAC97_PMOPS, |
| 489 | }, | 487 | }, |
| 490 | .probe = au1xpsc_ac97_drvprobe, | 488 | .probe = au1xpsc_ac97_drvprobe, |
| 491 | .remove = au1xpsc_ac97_drvremove, | 489 | .remove_new = au1xpsc_ac97_drvremove, |
| 492 | }; | 490 | }; |
| 493 | 491 | ||
| 494 | module_platform_driver(au1xpsc_ac97_driver); | 492 | module_platform_driver(au1xpsc_ac97_driver); |
| @@ -344,7 +344,7 @@ static int au1xpsc_i2s_drvprobe(struct platform_device *pdev) · 343 unmodified lines | |||
| 344 | &au1xpsc_i2s_component, &wd->dai_drv, 1); | 344 | &au1xpsc_i2s_component, &wd->dai_drv, 1); |
| 345 | } | 345 | } |
| 346 | 346 | ||
| 347 | static int au1xpsc_i2s_drvremove(struct platform_device *pdev) | 347 | static void au1xpsc_i2s_drvremove(struct platform_device *pdev) |
| 348 | { | 348 | { |
| 349 | struct au1xpsc_audio_data *wd = platform_get_drvdata(pdev); | 349 | struct au1xpsc_audio_data *wd = platform_get_drvdata(pdev); |
| 350 | 350 | ||
| @@ -352,8 +352,6 @@ static int au1xpsc_i2s_drvremove(struct platform_device *pdev) · 1 unmodified line | |||
| 352 | wmb(); /* drain writebuffer */ | 352 | wmb(); /* drain writebuffer */ |
| 353 | __raw_writel(PSC_CTRL_DISABLE, PSC_CTRL(wd)); | 353 | __raw_writel(PSC_CTRL_DISABLE, PSC_CTRL(wd)); |
| 354 | wmb(); /* drain writebuffer */ | 354 | wmb(); /* drain writebuffer */ |
| 355 | |||
| 356 | return 0; | ||
| 357 | } | 355 | } |
| 358 | 356 | ||
| 359 | #ifdef CONFIG_PM | 357 | #ifdef CONFIG_PM |
| @@ -406,7 +404,7 @@ static struct platform_driver au1xpsc_i2s_driver = { · 46 unmodified lines | |||
| 406 | .pm = AU1XPSCI2S_PMOPS, | 404 | .pm = AU1XPSCI2S_PMOPS, |
| 407 | }, | 405 | }, |
| 408 | .probe = au1xpsc_i2s_drvprobe, | 406 | .probe = au1xpsc_i2s_drvprobe, |
| 409 | .remove = au1xpsc_i2s_drvremove, | 407 | .remove_new = au1xpsc_i2s_drvremove, |
| 410 | }; | 408 | }; |
| 411 | 409 | ||
| 412 | module_platform_driver(au1xpsc_i2s_driver); | 410 | module_platform_driver(au1xpsc_i2s_driver); |
| @@ -289,10 +289,9 @@ static int bcm63xx_i2s_dev_probe(struct platform_device *pdev) · 288 unmodified lines | |||
| 289 | return ret; | 289 | return ret; |
| 290 | } | 290 | } |
| 291 | 291 | ||
| 292 | static int bcm63xx_i2s_dev_remove(struct platform_device *pdev) | 292 | static void bcm63xx_i2s_dev_remove(struct platform_device *pdev) |
| 293 | { | 293 | { |
| 294 | bcm63xx_soc_platform_remove(pdev); | 294 | bcm63xx_soc_platform_remove(pdev); |
| 295 | return 0; | ||
| 296 | } | 295 | } |
| 297 | 296 | ||
| 298 | #ifdef CONFIG_OF | 297 | #ifdef CONFIG_OF |
| @@ -308,7 +307,7 @@ static struct platform_driver bcm63xx_i2s_driver = { · 9 unmodified lines | |||
| 308 | .of_match_table = of_match_ptr(snd_soc_bcm_audio_match), | 307 | .of_match_table = of_match_ptr(snd_soc_bcm_audio_match), |
| 309 | }, | 308 | }, |
| 310 | .probe = bcm63xx_i2s_dev_probe, | 309 | .probe = bcm63xx_i2s_dev_probe, |
| 311 | .remove = bcm63xx_i2s_dev_remove, | 310 | .remove_new = bcm63xx_i2s_dev_remove, |
| 312 | }; | 311 | }; |
| 313 | 312 | ||
| 314 | module_platform_driver(bcm63xx_i2s_driver); | 313 | module_platform_driver(bcm63xx_i2s_driver); |
| @@ -1377,11 +1377,9 @@ static int cygnus_ssp_probe(struct platform_device *pdev) · 1376 unmodified lines | |||
| 1377 | return 0; | 1377 | return 0; |
| 1378 | } | 1378 | } |
| 1379 | 1379 | ||
| 1380 | static int cygnus_ssp_remove(struct platform_device *pdev) | 1380 | static void cygnus_ssp_remove(struct platform_device *pdev) |
| 1381 | { | 1381 | { |
| 1382 | cygnus_soc_platform_unregister(&pdev->dev); | 1382 | cygnus_soc_platform_unregister(&pdev->dev); |
| 1383 | |||
| 1384 | return 0; | ||
| 1385 | } | 1383 | } |
| 1386 | 1384 | ||
| 1387 | static const struct of_device_id cygnus_ssp_of_match[] = { | 1385 | static const struct of_device_id cygnus_ssp_of_match[] = { |
| @@ -1392,7 +1390,7 @@ MODULE_DEVICE_TABLE(of, cygnus_ssp_of_match); · 4 unmodified lines | |||
| 1392 | 1390 | ||
| 1393 | static struct platform_driver cygnus_ssp_driver = { | 1391 | static struct platform_driver cygnus_ssp_driver = { |
| 1394 | .probe = cygnus_ssp_probe, | 1392 | .probe = cygnus_ssp_probe, |
| 1395 | .remove = cygnus_ssp_remove, | 1393 | .remove_new = cygnus_ssp_remove, |
| 1396 | .driver = { | 1394 | .driver = { |
| 1397 | .name = "cygnus-ssp", | 1395 | .name = "cygnus-ssp", |
| 1398 | .of_match_table = cygnus_ssp_of_match, | 1396 | .of_match_table = cygnus_ssp_of_match, |
| @@ -8,7 +8,11 @@ config SND_EP93XX_SOC · 7 unmodified lines | |||
| 8 | the EP93xx I2S or AC97 interfaces. | 8 | the EP93xx I2S or AC97 interfaces. |
| 9 | 9 | ||
| 10 | config SND_EP93XX_SOC_I2S | 10 | config SND_EP93XX_SOC_I2S |
| 11 | tristate | 11 | tristate "I2S controller support for the Cirrus Logic EP93xx series" |
| 12 | depends on SND_EP93XX_SOC | ||
| 13 | help | ||
| 14 | Say Y or M if you want to add support for codecs attached to | ||
| 15 | the EP93xx I2S interface. | ||
| 12 | 16 | ||
| 13 | if SND_EP93XX_SOC_I2S | 17 | if SND_EP93XX_SOC_I2S |
| 14 | 18 | ||
| @@ -93,14 +93,12 @@ static int edb93xx_probe(struct platform_device *pdev) · 92 unmodified lines | |||
| 93 | return ret; | 93 | return ret; |
| 94 | } | 94 | } |
| 95 | 95 | ||
| 96 | static int edb93xx_remove(struct platform_device *pdev) | 96 | static void edb93xx_remove(struct platform_device *pdev) |
| 97 | { | 97 | { |
| 98 | struct snd_soc_card *card = platform_get_drvdata(pdev); | 98 | struct snd_soc_card *card = platform_get_drvdata(pdev); |
| 99 | 99 | ||
| 100 | snd_soc_unregister_card(card); | 100 | snd_soc_unregister_card(card); |
| 101 | ep93xx_i2s_release(); | 101 | ep93xx_i2s_release(); |
| 102 | |||
| 103 | return 0; | ||
| 104 | } | 102 | } |
| 105 | 103 | ||
| 106 | static struct platform_driver edb93xx_driver = { | 104 | static struct platform_driver edb93xx_driver = { |
| @@ -108,7 +106,7 @@ static struct platform_driver edb93xx_driver = { · 1 unmodified line | |||
| 108 | .name = "edb93xx-audio", | 106 | .name = "edb93xx-audio", |
| 109 | }, | 107 | }, |
| 110 | .probe = edb93xx_probe, | 108 | .probe = edb93xx_probe, |
| 111 | .remove = edb93xx_remove, | 109 | .remove_new = edb93xx_remove, |
| 112 | }; | 110 | }; |
| 113 | 111 | ||
| 114 | module_platform_driver(edb93xx_driver); | 112 | module_platform_driver(edb93xx_driver); |
| @@ -15,6 +15,7 @@ · 14 unmodified lines | |||
| 15 | #include <linux/slab.h> | 15 | #include <linux/slab.h> |
| 16 | #include <linux/clk.h> | 16 | #include <linux/clk.h> |
| 17 | #include <linux/io.h> | 17 | #include <linux/io.h> |
| 18 | #include <linux/of.h> | ||
| 18 | 19 | ||
| 19 | #include <sound/core.h> | 20 | #include <sound/core.h> |
| 20 | #include <sound/dmaengine_pcm.h> | 21 | #include <sound/dmaengine_pcm.h> |
| @@ -208,6 +209,16 @@ static int ep93xx_i2s_dai_probe(struct snd_soc_dai *dai) · 187 unmodified lines | |||
| 208 | return 0; | 209 | return 0; |
| 209 | } | 210 | } |
| 210 | 211 | ||
| 212 | static int ep93xx_i2s_startup(struct snd_pcm_substream *substream, | ||
| 213 | struct snd_soc_dai *dai) | ||
| 214 | { | ||
| 215 | struct ep93xx_i2s_info *info = snd_soc_dai_get_drvdata(dai); | ||
| 216 | |||
| 217 | ep93xx_i2s_enable(info, substream->stream); | ||
| 218 | |||
| 219 | return 0; | ||
| 220 | } | ||
| 221 | |||
| 211 | static void ep93xx_i2s_shutdown(struct snd_pcm_substream *substream, | 222 | static void ep93xx_i2s_shutdown(struct snd_pcm_substream *substream, |
| 212 | struct snd_soc_dai *dai) | 223 | struct snd_soc_dai *dai) |
| 213 | { | 224 | { |
| @@ -348,7 +359,6 @@ static int ep93xx_i2s_hw_params(struct snd_pcm_substream *substream, · 134 unmodified lines | |||
| 348 | if (err) | 359 | if (err) |
| 349 | return err; | 360 | return err; |
| 350 | 361 | ||
| 351 | ep93xx_i2s_enable(info, substream->stream); | ||
| 352 | return 0; | 362 | return 0; |
| 353 | } | 363 | } |
| 354 | 364 | ||
| @@ -397,6 +407,7 @@ static int ep93xx_i2s_resume(struct snd_soc_component *component) · 42 unmodified lines | |||
| 397 | #endif | 407 | #endif |
| 398 | 408 | ||
| 399 | static const struct snd_soc_dai_ops ep93xx_i2s_dai_ops = { | 409 | static const struct snd_soc_dai_ops ep93xx_i2s_dai_ops = { |
| 410 | .startup = ep93xx_i2s_startup, | ||
| 400 | .shutdown = ep93xx_i2s_shutdown, | 411 | .shutdown = ep93xx_i2s_shutdown, |
| 401 | .hw_params = ep93xx_i2s_hw_params, | 412 | .hw_params = ep93xx_i2s_hw_params, |
| 402 | .set_sysclk = ep93xx_i2s_set_sysclk, | 413 | .set_sysclk = ep93xx_i2s_set_sysclk, |
| @@ -495,21 +506,27 @@ fail: · 92 unmodified lines | |||
| 495 | return err; | 506 | return err; |
| 496 | } | 507 | } |
| 497 | 508 | ||
| 498 | static int ep93xx_i2s_remove(struct platform_device *pdev) | 509 | static void ep93xx_i2s_remove(struct platform_device *pdev) |
| 499 | { | 510 | { |
| 500 | struct ep93xx_i2s_info *info = dev_get_drvdata(&pdev->dev); | 511 | struct ep93xx_i2s_info *info = dev_get_drvdata(&pdev->dev); |
| 501 | 512 | ||
| 502 | clk_put(info->lrclk); | 513 | clk_put(info->lrclk); |
| 503 | clk_put(info->sclk); | 514 | clk_put(info->sclk); |
| 504 | clk_put(info->mclk); | 515 | clk_put(info->mclk); |
| 505 | return 0; | ||
| 506 | } | 516 | } |
| 507 | 517 | ||
| 518 | static const struct of_device_id ep93xx_i2s_of_ids[] = { | ||
| 519 | { .compatible = "cirrus,ep9301-i2s" }, | ||
| 520 | {} | ||
| 521 | }; | ||
| 522 | MODULE_DEVICE_TABLE(of, ep93xx_i2s_of_ids); | ||
| 523 | |||
| 508 | static struct platform_driver ep93xx_i2s_driver = { | 524 | static struct platform_driver ep93xx_i2s_driver = { |
| 509 | .probe = ep93xx_i2s_probe, | 525 | .probe = ep93xx_i2s_probe, |
| 510 | .remove = ep93xx_i2s_remove, | 526 | .remove_new = ep93xx_i2s_remove, |
| 511 | .driver = { | 527 | .driver = { |
| 512 | .name = "ep93xx-i2s", | 528 | .name = "ep93xx-i2s", |
| 529 | .of_match_table = ep93xx_i2s_of_ids, | ||
| 513 | }, | 530 | }, |
| 514 | }; | 531 | }; |
| 515 | 532 | ||
| @@ -68,6 +68,9 @@ config SND_SOC_ALL_CODECS · 67 unmodified lines | |||
| 68 | imply SND_SOC_CS35L41_I2C | 68 | imply SND_SOC_CS35L41_I2C |
| 69 | imply SND_SOC_CS35L45_I2C | 69 | imply SND_SOC_CS35L45_I2C |
| 70 | imply SND_SOC_CS35L45_SPI | 70 | imply SND_SOC_CS35L45_SPI |
| 71 | imply SND_SOC_CS35L56_I2C | ||
| 72 | imply SND_SOC_CS35L56_SPI | ||
| 73 | imply SND_SOC_CS35L56_SDW | ||
| 71 | imply SND_SOC_CS42L42 | 74 | imply SND_SOC_CS42L42 |
| 72 | imply SND_SOC_CS42L42_SDW | 75 | imply SND_SOC_CS42L42_SDW |
| 73 | imply SND_SOC_CS42L51_I2C | 76 | imply SND_SOC_CS42L51_I2C |
| @@ -130,6 +133,7 @@ config SND_SOC_ALL_CODECS · 56 unmodified lines | |||
| 130 | imply SND_SOC_MAX98925 | 133 | imply SND_SOC_MAX98925 |
| 131 | imply SND_SOC_MAX98926 | 134 | imply SND_SOC_MAX98926 |
| 132 | imply SND_SOC_MAX98927 | 135 | imply SND_SOC_MAX98927 |
| 136 | imply SND_SOC_MAX98363 | ||
| 133 | imply SND_SOC_MAX98373_I2C | 137 | imply SND_SOC_MAX98373_I2C |
| 134 | imply SND_SOC_MAX98373_SDW | 138 | imply SND_SOC_MAX98373_SDW |
| 135 | imply SND_SOC_MAX98390 | 139 | imply SND_SOC_MAX98390 |
| @@ -200,6 +204,7 @@ config SND_SOC_ALL_CODECS · 64 unmodified lines | |||
| 200 | imply SND_SOC_RT711_SDW | 204 | imply SND_SOC_RT711_SDW |
| 201 | imply SND_SOC_RT711_SDCA_SDW | 205 | imply SND_SOC_RT711_SDCA_SDW |
| 202 | imply SND_SOC_RT712_SDCA_SDW | 206 | imply SND_SOC_RT712_SDCA_SDW |
| 207 | imply SND_SOC_RT712_SDCA_DMIC_SDW | ||
| 203 | imply SND_SOC_RT715_SDW | 208 | imply SND_SOC_RT715_SDW |
| 204 | imply SND_SOC_RT715_SDCA_SDW | 209 | imply SND_SOC_RT715_SDCA_SDW |
| 205 | imply SND_SOC_RT1308_SDW | 210 | imply SND_SOC_RT1308_SDW |
| @@ -364,6 +369,9 @@ config SND_SOC_WM_ADSP · 158 unmodified lines | |||
| 364 | default y if SND_SOC_WM2200=y | 369 | default y if SND_SOC_WM2200=y |
| 365 | default y if SND_SOC_CS35L41_SPI=y | 370 | default y if SND_SOC_CS35L41_SPI=y |
| 366 | default y if SND_SOC_CS35L41_I2C=y | 371 | default y if SND_SOC_CS35L41_I2C=y |
| 372 | default y if SND_SOC_CS35L45_SPI=y | ||
| 373 | default y if SND_SOC_CS35L45_I2C=y | ||
| 374 | default y if SND_SOC_CS35L56=y | ||
| 367 | default m if SND_SOC_MADERA=m | 375 | default m if SND_SOC_MADERA=m |
| 368 | default m if SND_SOC_CS47L24=m | 376 | default m if SND_SOC_CS47L24=m |
| 369 | default m if SND_SOC_WM5102=m | 377 | default m if SND_SOC_WM5102=m |
| @@ -371,6 +379,9 @@ config SND_SOC_WM_ADSP · 1 unmodified line | |||
| 371 | default m if SND_SOC_WM2200=m | 379 | default m if SND_SOC_WM2200=m |
| 372 | default m if SND_SOC_CS35L41_SPI=m | 380 | default m if SND_SOC_CS35L41_SPI=m |
| 373 | default m if SND_SOC_CS35L41_I2C=m | 381 | default m if SND_SOC_CS35L41_I2C=m |
| 382 | default m if SND_SOC_CS35L45_SPI=m | ||
| 383 | default m if SND_SOC_CS35L45_I2C=m | ||
| 384 | default m if SND_SOC_CS35L56=m | ||
| 374 | 385 | ||
| 375 | config SND_SOC_AB8500_CODEC | 386 | config SND_SOC_AB8500_CODEC |
| 376 | tristate | 387 | tristate |
| @@ -711,6 +722,41 @@ config SND_SOC_CS35L45_I2C · 334 unmodified lines | |||
| 711 | Enable support for Cirrus Logic CS35L45 smart speaker amplifier | 722 | Enable support for Cirrus Logic CS35L45 smart speaker amplifier |
| 712 | with I2C control. | 723 | with I2C control. |
| 713 | 724 | ||
| 725 | config SND_SOC_CS35L56 | ||
| 726 | tristate | ||
| 727 | |||
| 728 | config SND_SOC_CS35L56_SHARED | ||
| 729 | tristate | ||
| 730 | |||
| 731 | config SND_SOC_CS35L56_I2C | ||
| 732 | tristate "Cirrus Logic CS35L56 CODEC (I2C)" | ||
| 733 | depends on I2C | ||
| 734 | depends on SOUNDWIRE || !SOUNDWIRE | ||
| 735 | select REGMAP_I2C | ||
| 736 | select SND_SOC_CS35L56 | ||
| 737 | select SND_SOC_CS35L56_SHARED | ||
| 738 | help | ||
| 739 | Enable support for Cirrus Logic CS35L56 boosted amplifier with I2C control | ||
| 740 | |||
| 741 | config SND_SOC_CS35L56_SPI | ||
| 742 | tristate "Cirrus Logic CS35L56 CODEC (SPI)" | ||
| 743 | depends on SPI_MASTER | ||
| 744 | depends on SOUNDWIRE || !SOUNDWIRE | ||
| 745 | select REGMAP_SPI | ||
| 746 | select SND_SOC_CS35L56 | ||
| 747 | select SND_SOC_CS35L56_SHARED | ||
| 748 | help | ||
| 749 | Enable support for Cirrus Logic CS35L56 boosted amplifier with SPI control | ||
| 750 | |||
| 751 | config SND_SOC_CS35L56_SDW | ||
| 752 | tristate "Cirrus Logic CS35L56 CODEC (SDW)" | ||
| 753 | depends on SOUNDWIRE | ||
| 754 | select REGMAP | ||
| 755 | select SND_SOC_CS35L56 | ||
| 756 | select SND_SOC_CS35L56_SHARED | ||
| 757 | help | ||
| 758 | Enable support for Cirrus Logic CS35L56 boosted amplifier with SoundWire control | ||
| 759 | |||
| 714 | config SND_SOC_CS42L42_CORE | 760 | config SND_SOC_CS42L42_CORE |
| 715 | tristate | 761 | tristate |
| 716 | 762 | ||
| @@ -1089,6 +1135,16 @@ config SND_SOC_MAX98520 · 372 unmodified lines | |||
| 1089 | 1135 | ||
| 1090 | To compile this driver as a module, choose M here. | 1136 | To compile this driver as a module, choose M here. |
| 1091 | 1137 | ||
| 1138 | config SND_SOC_MAX98363 | ||
| 1139 | tristate "Analog Devices MAX98363 Soundwire Speaker Amplifier" | ||
| 1140 | depends on SOUNDWIRE | ||
| 1141 | select REGMAP_SOUNDWIRE | ||
| 1142 | help | ||
| 1143 | Enable support for Analog Devices MAX98363 Soundwire | ||
| 1144 | amplifier. MAX98363 supports the MIPI SoundWire v1.2 | ||
| 1145 | compatible interface for audio and control data. | ||
| 1146 | This amplifier does not support I2C and I2S. | ||
| 1147 | |||
| 1092 | config SND_SOC_MAX98373 | 1148 | config SND_SOC_MAX98373 |
| 1093 | tristate | 1149 | tristate |
| 1094 | 1150 | ||
| @@ -1477,6 +1533,12 @@ config SND_SOC_RT712_SDCA_SDW · 382 unmodified lines | |||
| 1477 | select REGMAP_SOUNDWIRE | 1533 | select REGMAP_SOUNDWIRE |
| 1478 | select REGMAP_SOUNDWIRE_MBQ | 1534 | select REGMAP_SOUNDWIRE_MBQ |
| 1479 | 1535 | ||
| 1536 | config SND_SOC_RT712_SDCA_DMIC_SDW | ||
| 1537 | tristate "Realtek RT712 SDCA DMIC Codec - SDW" | ||
| 1538 | depends on SOUNDWIRE | ||
| 1539 | select REGMAP_SOUNDWIRE | ||
| 1540 | select REGMAP_SOUNDWIRE_MBQ | ||
| 1541 | |||
| 1480 | config SND_SOC_RT715 | 1542 | config SND_SOC_RT715 |
| 1481 | tristate | 1543 | tristate |
| 1482 | 1544 | ||
| @@ -66,6 +66,11 @@ snd-soc-cs35l41-i2c-objs := cs35l41-i2c.o · 65 unmodified lines | |||
| 66 | snd-soc-cs35l45-objs := cs35l45.o cs35l45-tables.o | 66 | snd-soc-cs35l45-objs := cs35l45.o cs35l45-tables.o |
| 67 | snd-soc-cs35l45-spi-objs := cs35l45-spi.o | 67 | snd-soc-cs35l45-spi-objs := cs35l45-spi.o |
| 68 | snd-soc-cs35l45-i2c-objs := cs35l45-i2c.o | 68 | snd-soc-cs35l45-i2c-objs := cs35l45-i2c.o |
| 69 | snd-soc-cs35l56-objs := cs35l56.o | ||
| 70 | snd-soc-cs35l56-shared-objs := cs35l56-shared.o | ||
| 71 | snd-soc-cs35l56-i2c-objs := cs35l56-i2c.o | ||
| 72 | snd-soc-cs35l56-spi-objs := cs35l56-spi.o | ||
| 73 | snd-soc-cs35l56-sdw-objs := cs35l56-sdw.o | ||
| 69 | snd-soc-cs42l42-objs := cs42l42.o | 74 | snd-soc-cs42l42-objs := cs42l42.o |
| 70 | snd-soc-cs42l42-i2c-objs := cs42l42-i2c.o | 75 | snd-soc-cs42l42-i2c-objs := cs42l42-i2c.o |
| 71 | snd-soc-cs42l42-sdw-objs := cs42l42-sdw.o | 76 | snd-soc-cs42l42-sdw-objs := cs42l42-sdw.o |
| @@ -143,6 +148,7 @@ snd-soc-max98925-objs := max98925.o · 71 unmodified lines | |||
| 143 | snd-soc-max98926-objs := max98926.o | 148 | snd-soc-max98926-objs := max98926.o |
| 144 | snd-soc-max98927-objs := max98927.o | 149 | snd-soc-max98927-objs := max98927.o |
| 145 | snd-soc-max98520-objs := max98520.o | 150 | snd-soc-max98520-objs := max98520.o |
| 151 | snd-soc-max98363-objs := max98363.o | ||
| 146 | snd-soc-max98373-objs := max98373.o | 152 | snd-soc-max98373-objs := max98373.o |
| 147 | snd-soc-max98373-i2c-objs := max98373-i2c.o | 153 | snd-soc-max98373-i2c-objs := max98373-i2c.o |
| 148 | snd-soc-max98373-sdw-objs := max98373-sdw.o | 154 | snd-soc-max98373-sdw-objs := max98373-sdw.o |
| @@ -228,6 +234,7 @@ snd-soc-rt700-objs := rt700.o rt700-sdw.o · 79 unmodified lines | |||
| 228 | snd-soc-rt711-objs := rt711.o rt711-sdw.o | 234 | snd-soc-rt711-objs := rt711.o rt711-sdw.o |
| 229 | snd-soc-rt711-sdca-objs := rt711-sdca.o rt711-sdca-sdw.o | 235 | snd-soc-rt711-sdca-objs := rt711-sdca.o rt711-sdca-sdw.o |
| 230 | snd-soc-rt712-sdca-objs := rt712-sdca.o rt712-sdca-sdw.o | 236 | snd-soc-rt712-sdca-objs := rt712-sdca.o rt712-sdca-sdw.o |
| 237 | snd-soc-rt712-sdca-dmic-objs := rt712-sdca-dmic.o | ||
| 231 | snd-soc-rt715-objs := rt715.o rt715-sdw.o | 238 | snd-soc-rt715-objs := rt715.o rt715-sdw.o |
| 232 | snd-soc-rt715-sdca-objs := rt715-sdca.o rt715-sdca-sdw.o | 239 | snd-soc-rt715-sdca-objs := rt715-sdca.o rt715-sdca-sdw.o |
| 233 | snd-soc-rt9120-objs := rt9120.o | 240 | snd-soc-rt9120-objs := rt9120.o |
| @@ -433,6 +440,11 @@ obj-$(CONFIG_SND_SOC_CS35L41_I2C) += snd-soc-cs35l41-i2c.o · 199 unmodified lines | |||
| 433 | obj-$(CONFIG_SND_SOC_CS35L45) += snd-soc-cs35l45.o | 440 | obj-$(CONFIG_SND_SOC_CS35L45) += snd-soc-cs35l45.o |
| 434 | obj-$(CONFIG_SND_SOC_CS35L45_SPI) += snd-soc-cs35l45-spi.o | 441 | obj-$(CONFIG_SND_SOC_CS35L45_SPI) += snd-soc-cs35l45-spi.o |
| 435 | obj-$(CONFIG_SND_SOC_CS35L45_I2C) += snd-soc-cs35l45-i2c.o | 442 | obj-$(CONFIG_SND_SOC_CS35L45_I2C) += snd-soc-cs35l45-i2c.o |
| 443 | obj-$(CONFIG_SND_SOC_CS35L56) += snd-soc-cs35l56.o | ||
| 444 | obj-$(CONFIG_SND_SOC_CS35L56_SHARED) += snd-soc-cs35l56-shared.o | ||
| 445 | obj-$(CONFIG_SND_SOC_CS35L56_I2C) += snd-soc-cs35l56-i2c.o | ||
| 446 | obj-$(CONFIG_SND_SOC_CS35L56_SPI) += snd-soc-cs35l56-spi.o | ||
| 447 | obj-$(CONFIG_SND_SOC_CS35L56_SDW) += snd-soc-cs35l56-sdw.o | ||
| 436 | obj-$(CONFIG_SND_SOC_CS42L42_CORE) += snd-soc-cs42l42.o | 448 | obj-$(CONFIG_SND_SOC_CS42L42_CORE) += snd-soc-cs42l42.o |
| 437 | obj-$(CONFIG_SND_SOC_CS42L42) += snd-soc-cs42l42-i2c.o | 449 | obj-$(CONFIG_SND_SOC_CS42L42) += snd-soc-cs42l42-i2c.o |
| 438 | obj-$(CONFIG_SND_SOC_CS42L42_SDW) += snd-soc-cs42l42-sdw.o | 450 | obj-$(CONFIG_SND_SOC_CS42L42_SDW) += snd-soc-cs42l42-sdw.o |
| @@ -505,6 +517,7 @@ obj-$(CONFIG_SND_SOC_MAX98925) += snd-soc-max98925.o · 66 unmodified lines | |||
| 505 | obj-$(CONFIG_SND_SOC_MAX98926) += snd-soc-max98926.o | 517 | obj-$(CONFIG_SND_SOC_MAX98926) += snd-soc-max98926.o |
| 506 | obj-$(CONFIG_SND_SOC_MAX98927) += snd-soc-max98927.o | 518 | obj-$(CONFIG_SND_SOC_MAX98927) += snd-soc-max98927.o |
| 507 | obj-$(CONFIG_SND_SOC_MAX98520) += snd-soc-max98520.o | 519 | obj-$(CONFIG_SND_SOC_MAX98520) += snd-soc-max98520.o |
| 520 | obj-$(CONFIG_SND_SOC_MAX98363) += snd-soc-max98363.o | ||
| 508 | obj-$(CONFIG_SND_SOC_MAX98373) += snd-soc-max98373.o | 521 | obj-$(CONFIG_SND_SOC_MAX98373) += snd-soc-max98373.o |
| 509 | obj-$(CONFIG_SND_SOC_MAX98373_I2C) += snd-soc-max98373-i2c.o | 522 | obj-$(CONFIG_SND_SOC_MAX98373_I2C) += snd-soc-max98373-i2c.o |
| 510 | obj-$(CONFIG_SND_SOC_MAX98373_SDW) += snd-soc-max98373-sdw.o | 523 | obj-$(CONFIG_SND_SOC_MAX98373_SDW) += snd-soc-max98373-sdw.o |
| @@ -591,6 +604,7 @@ obj-$(CONFIG_SND_SOC_RT700) += snd-soc-rt700.o · 80 unmodified lines | |||
| 591 | obj-$(CONFIG_SND_SOC_RT711) += snd-soc-rt711.o | 604 | obj-$(CONFIG_SND_SOC_RT711) += snd-soc-rt711.o |
| 592 | obj-$(CONFIG_SND_SOC_RT711_SDCA_SDW) += snd-soc-rt711-sdca.o | 605 | obj-$(CONFIG_SND_SOC_RT711_SDCA_SDW) += snd-soc-rt711-sdca.o |
| 593 | obj-$(CONFIG_SND_SOC_RT712_SDCA_SDW) += snd-soc-rt712-sdca.o | 606 | obj-$(CONFIG_SND_SOC_RT712_SDCA_SDW) += snd-soc-rt712-sdca.o |
| 607 | obj-$(CONFIG_SND_SOC_RT712_SDCA_DMIC_SDW) += snd-soc-rt712-sdca-dmic.o | ||
| 594 | obj-$(CONFIG_SND_SOC_RT715) += snd-soc-rt715.o | 608 | obj-$(CONFIG_SND_SOC_RT715) += snd-soc-rt715.o |
| 595 | obj-$(CONFIG_SND_SOC_RT715_SDCA_SDW) += snd-soc-rt715-sdca.o | 609 | obj-$(CONFIG_SND_SOC_RT715_SDCA_SDW) += snd-soc-rt715-sdca.o |
| 596 | obj-$(CONFIG_SND_SOC_RT9120) += snd-soc-rt9120.o | 610 | obj-$(CONFIG_SND_SOC_RT9120) += snd-soc-rt9120.o |
| @@ -55,7 +55,7 @@ static const struct spi_device_id adau1977_spi_ids[] = { · 54 unmodified lines | |||
| 55 | }; | 55 | }; |
| 56 | MODULE_DEVICE_TABLE(spi, adau1977_spi_ids); | 56 | MODULE_DEVICE_TABLE(spi, adau1977_spi_ids); |
| 57 | 57 | ||
| 58 | static const struct of_device_id adau1977_spi_of_match[] = { | 58 | static const struct of_device_id adau1977_spi_of_match[] __maybe_unused = { |
| 59 | { .compatible = "adi,adau1977" }, | 59 | { .compatible = "adi,adau1977" }, |
| 60 | { .compatible = "adi,adau1978" }, | 60 | { .compatible = "adi,adau1978" }, |
| 61 | { .compatible = "adi,adau1979" }, | 61 | { .compatible = "adi,adau1979" }, |
| @@ -1114,12 +1114,31 @@ static const struct reg_sequence cs35l41_reset_to_safe[] = { · 1113 unmodified lines | |||
| 1114 | { 0x00000040, 0x00000033 }, | 1114 | { 0x00000040, 0x00000033 }, |
| 1115 | }; | 1115 | }; |
| 1116 | 1116 | ||
| 1117 | static const struct reg_sequence cs35l41_actv_seq[] = { | ||
| 1118 | /* SYNC_BST_CTL_RX_EN = 1; SYNC_BST_CTL_TX_EN = 1 */ | ||
| 1119 | {CS35L41_MDSYNC_EN, 0x00003000}, | ||
| 1120 | /* BST_CTL_SEL = MDSYNC */ | ||
| 1121 | {CS35L41_BSTCVRT_VCTRL2, 0x00000002}, | ||
| 1122 | }; | ||
| 1123 | |||
| 1124 | static const struct reg_sequence cs35l41_pass_seq[] = { | ||
| 1125 | /* SYNC_BST_CTL_RX_EN = 0; SYNC_BST_CTL_TX_EN = 1 */ | ||
| 1126 | {CS35L41_MDSYNC_EN, 0x00001000}, | ||
| 1127 | /* BST_EN = 0 */ | ||
| 1128 | {CS35L41_PWR_CTRL2, 0x00003300}, | ||
| 1129 | /* BST_CTL_SEL = MDSYNC */ | ||
| 1130 | {CS35L41_BSTCVRT_VCTRL2, 0x00000002}, | ||
| 1131 | }; | ||
| 1132 | |||
| 1117 | int cs35l41_init_boost(struct device *dev, struct regmap *regmap, | 1133 | int cs35l41_init_boost(struct device *dev, struct regmap *regmap, |
| 1118 | struct cs35l41_hw_cfg *hw_cfg) | 1134 | struct cs35l41_hw_cfg *hw_cfg) |
| 1119 | { | 1135 | { |
| 1120 | int ret; | 1136 | int ret; |
| 1121 | 1137 | ||
| 1122 | switch (hw_cfg->bst_type) { | 1138 | switch (hw_cfg->bst_type) { |
| 1139 | case CS35L41_SHD_BOOST_ACTV: | ||
| 1140 | regmap_multi_reg_write(regmap, cs35l41_actv_seq, ARRAY_SIZE(cs35l41_actv_seq)); | ||
| 1141 | fallthrough; | ||
| 1123 | case CS35L41_INT_BOOST: | 1142 | case CS35L41_INT_BOOST: |
| 1124 | ret = cs35l41_boost_config(dev, regmap, hw_cfg->bst_ind, | 1143 | ret = cs35l41_boost_config(dev, regmap, hw_cfg->bst_ind, |
| 1125 | hw_cfg->bst_cap, hw_cfg->bst_ipk); | 1144 | hw_cfg->bst_cap, hw_cfg->bst_ipk); |
| @@ -1138,6 +1157,10 @@ int cs35l41_init_boost(struct device *dev, struct regmap *regmap, · 12 unmodified lines | |||
| 1138 | ret = regmap_update_bits(regmap, CS35L41_PWR_CTRL2, CS35L41_BST_EN_MASK, | 1157 | ret = regmap_update_bits(regmap, CS35L41_PWR_CTRL2, CS35L41_BST_EN_MASK, |
| 1139 | CS35L41_BST_DIS_FET_OFF << CS35L41_BST_EN_SHIFT); | 1158 | CS35L41_BST_DIS_FET_OFF << CS35L41_BST_EN_SHIFT); |
| 1140 | break; | 1159 | break; |
| 1160 | case CS35L41_SHD_BOOST_PASS: | ||
| 1161 | ret = regmap_multi_reg_write(regmap, cs35l41_pass_seq, | ||
| 1162 | ARRAY_SIZE(cs35l41_pass_seq)); | ||
| 1163 | break; | ||
| 1141 | default: | 1164 | default: |
| 1142 | dev_err(dev, "Boost type %d not supported\n", hw_cfg->bst_type); | 1165 | dev_err(dev, "Boost type %d not supported\n", hw_cfg->bst_type); |
| 1143 | ret = -EINVAL; | 1166 | ret = -EINVAL; |
| @@ -1165,11 +1188,59 @@ bool cs35l41_safe_reset(struct regmap *regmap, enum cs35l41_boost_type b_type) · 21 unmodified lines | |||
| 1165 | } | 1188 | } |
| 1166 | EXPORT_SYMBOL_GPL(cs35l41_safe_reset); | 1189 | EXPORT_SYMBOL_GPL(cs35l41_safe_reset); |
| 1167 | 1190 | ||
| 1168 | int cs35l41_global_enable(struct regmap *regmap, enum cs35l41_boost_type b_type, int enable) | 1191 | int cs35l41_global_enable(struct regmap *regmap, enum cs35l41_boost_type b_type, int enable, |
| 1192 | struct completion *pll_lock) | ||
| 1169 | { | 1193 | { |
| 1170 | int ret; | 1194 | int ret; |
| 1195 | unsigned int gpio1_func, pad_control, pwr_ctrl1, pwr_ctrl3; | ||
| 1196 | struct reg_sequence cs35l41_mdsync_down_seq[] = { | ||
| 1197 | {CS35L41_PWR_CTRL3, 0}, | ||
| 1198 | {CS35L41_GPIO_PAD_CONTROL, 0}, | ||
| 1199 | {CS35L41_PWR_CTRL1, 0, 3000}, | ||
| 1200 | }; | ||
| 1201 | struct reg_sequence cs35l41_mdsync_up_seq[] = { | ||
| 1202 | {CS35L41_PWR_CTRL3, 0}, | ||
| 1203 | {CS35L41_PWR_CTRL1, 0x00000000, 3000}, | ||
| 1204 | {CS35L41_PWR_CTRL1, 0x00000001, 3000}, | ||
| 1205 | }; | ||
| 1171 | 1206 | ||
| 1172 | switch (b_type) { | 1207 | switch (b_type) { |
| 1208 | case CS35L41_SHD_BOOST_ACTV: | ||
| 1209 | case CS35L41_SHD_BOOST_PASS: | ||
| 1210 | regmap_read(regmap, CS35L41_PWR_CTRL3, &pwr_ctrl3); | ||
| 1211 | regmap_read(regmap, CS35L41_GPIO_PAD_CONTROL, &pad_control); | ||
| 1212 | |||
| 1213 | pwr_ctrl3 &= ~CS35L41_SYNC_EN_MASK; | ||
| 1214 | pwr_ctrl1 = enable << CS35L41_GLOBAL_EN_SHIFT; | ||
| 1215 | |||
| 1216 | gpio1_func = enable ? CS35L41_GPIO1_MDSYNC : CS35L41_GPIO1_HIZ; | ||
| 1217 | gpio1_func <<= CS35L41_GPIO1_CTRL_SHIFT; | ||
| 1218 | |||
| 1219 | pad_control &= ~CS35L41_GPIO1_CTRL_MASK; | ||
| 1220 | pad_control |= gpio1_func & CS35L41_GPIO1_CTRL_MASK; | ||
| 1221 | |||
| 1222 | cs35l41_mdsync_down_seq[0].def = pwr_ctrl3; | ||
| 1223 | cs35l41_mdsync_down_seq[1].def = pad_control; | ||
| 1224 | cs35l41_mdsync_down_seq[2].def = pwr_ctrl1; | ||
| 1225 | ret = regmap_multi_reg_write(regmap, cs35l41_mdsync_down_seq, | ||
| 1226 | ARRAY_SIZE(cs35l41_mdsync_down_seq)); | ||
| 1227 | if (!enable) | ||
| 1228 | break; | ||
| 1229 | |||
| 1230 | if (!pll_lock) | ||
| 1231 | return -EINVAL; | ||
| 1232 | |||
| 1233 | ret = wait_for_completion_timeout(pll_lock, msecs_to_jiffies(1000)); | ||
| 1234 | if (ret == 0) { | ||
| 1235 | ret = -ETIMEDOUT; | ||
| 1236 | } else { | ||
| 1237 | regmap_read(regmap, CS35L41_PWR_CTRL3, &pwr_ctrl3); | ||
| 1238 | pwr_ctrl3 |= CS35L41_SYNC_EN_MASK; | ||
| 1239 | cs35l41_mdsync_up_seq[0].def = pwr_ctrl3; | ||
| 1240 | ret = regmap_multi_reg_write(regmap, cs35l41_mdsync_up_seq, | ||
| 1241 | ARRAY_SIZE(cs35l41_mdsync_up_seq)); | ||
| 1242 | } | ||
| 1243 | break; | ||
| 1173 | case CS35L41_INT_BOOST: | 1244 | case CS35L41_INT_BOOST: |
| 1174 | ret = regmap_update_bits(regmap, CS35L41_PWR_CTRL1, CS35L41_GLOBAL_EN_MASK, | 1245 | ret = regmap_update_bits(regmap, CS35L41_PWR_CTRL1, CS35L41_GLOBAL_EN_MASK, |
| 1175 | enable << CS35L41_GLOBAL_EN_SHIFT); | 1246 | enable << CS35L41_GLOBAL_EN_SHIFT); |
| @@ -150,6 +150,7 @@ static const struct cs35l41_fs_mon_config cs35l41_fs_mon[] = { · 149 unmodified lines | |||
| 150 | { 5644800, 16, 24 }, | 150 | { 5644800, 16, 24 }, |
| 151 | { 6000000, 16, 24 }, | 151 | { 6000000, 16, 24 }, |
| 152 | { 6144000, 16, 24 }, | 152 | { 6144000, 16, 24 }, |
| 153 | { 12288000, 0, 0 }, | ||
| 153 | }; | 154 | }; |
| 154 | 155 | ||
| 155 | static int cs35l41_get_fs_mon_config_index(int freq) | 156 | static int cs35l41_get_fs_mon_config_index(int freq) |
| @@ -356,6 +357,30 @@ static const struct snd_kcontrol_new cs35l41_aud_controls[] = { · 200 unmodified lines | |||
| 356 | WM_ADSP_FW_CONTROL("DSP1", 0), | 357 | WM_ADSP_FW_CONTROL("DSP1", 0), |
| 357 | }; | 358 | }; |
| 358 | 359 | ||
| 360 | static void cs35l41_boost_enable(struct cs35l41_private *cs35l41, unsigned int enable) | ||
| 361 | { | ||
| 362 | switch (cs35l41->hw_cfg.bst_type) { | ||
| 363 | case CS35L41_INT_BOOST: | ||
| 364 | case CS35L41_SHD_BOOST_ACTV: | ||
| 365 | enable = enable ? CS35L41_BST_EN_DEFAULT : CS35L41_BST_DIS_FET_OFF; | ||
| 366 | regmap_update_bits(cs35l41->regmap, CS35L41_PWR_CTRL2, CS35L41_BST_EN_MASK, | ||
| 367 | enable << CS35L41_BST_EN_SHIFT); | ||
| 368 | break; | ||
| 369 | default: | ||
| 370 | break; | ||
| 371 | } | ||
| 372 | } | ||
| 373 | |||
| 374 | |||
| 375 | static void cs35l41_error_release(struct cs35l41_private *cs35l41, unsigned int irq_err_bit, | ||
| 376 | unsigned int rel_err_bit) | ||
| 377 | { | ||
| 378 | regmap_write(cs35l41->regmap, CS35L41_IRQ1_STATUS1, irq_err_bit); | ||
| 379 | regmap_write(cs35l41->regmap, CS35L41_PROTECT_REL_ERR_IGN, 0); | ||
| 380 | regmap_update_bits(cs35l41->regmap, CS35L41_PROTECT_REL_ERR_IGN, rel_err_bit, rel_err_bit); | ||
| 381 | regmap_update_bits(cs35l41->regmap, CS35L41_PROTECT_REL_ERR_IGN, rel_err_bit, 0); | ||
| 382 | } | ||
| 383 | |||
| 359 | static irqreturn_t cs35l41_irq(int irq, void *data) | 384 | static irqreturn_t cs35l41_irq(int irq, void *data) |
| 360 | { | 385 | { |
| 361 | struct cs35l41_private *cs35l41 = data; | 386 | struct cs35l41_private *cs35l41 = data; |
| @@ -392,94 +417,49 @@ static irqreturn_t cs35l41_irq(int irq, void *data) · 30 unmodified lines | |||
| 392 | */ | 417 | */ |
| 393 | if (status[0] & CS35L41_AMP_SHORT_ERR) { | 418 | if (status[0] & CS35L41_AMP_SHORT_ERR) { |
| 394 | dev_crit_ratelimited(cs35l41->dev, "Amp short error\n"); | 419 | dev_crit_ratelimited(cs35l41->dev, "Amp short error\n"); |
| 395 | regmap_write(cs35l41->regmap, CS35L41_IRQ1_STATUS1, | 420 | cs35l41_error_release(cs35l41, CS35L41_AMP_SHORT_ERR, CS35L41_AMP_SHORT_ERR_RLS); |
| 396 | CS35L41_AMP_SHORT_ERR); | ||
| 397 | regmap_write(cs35l41->regmap, CS35L41_PROTECT_REL_ERR_IGN, 0); | ||
| 398 | regmap_update_bits(cs35l41->regmap, CS35L41_PROTECT_REL_ERR_IGN, | ||
| 399 | CS35L41_AMP_SHORT_ERR_RLS, | ||
| 400 | CS35L41_AMP_SHORT_ERR_RLS); | ||
| 401 | regmap_update_bits(cs35l41->regmap, CS35L41_PROTECT_REL_ERR_IGN, | ||
| 402 | CS35L41_AMP_SHORT_ERR_RLS, 0); | ||
| 403 | ret = IRQ_HANDLED; | 421 | ret = IRQ_HANDLED; |
| 404 | } | 422 | } |
| 405 | 423 | ||
| 406 | if (status[0] & CS35L41_TEMP_WARN) { | 424 | if (status[0] & CS35L41_TEMP_WARN) { |
| 407 | dev_crit_ratelimited(cs35l41->dev, "Over temperature warning\n"); | 425 | dev_crit_ratelimited(cs35l41->dev, "Over temperature warning\n"); |
| 408 | regmap_write(cs35l41->regmap, CS35L41_IRQ1_STATUS1, | 426 | cs35l41_error_release(cs35l41, CS35L41_TEMP_WARN, CS35L41_TEMP_WARN_ERR_RLS); |
| 409 | CS35L41_TEMP_WARN); | ||
| 410 | regmap_write(cs35l41->regmap, CS35L41_PROTECT_REL_ERR_IGN, 0); | ||
| 411 | regmap_update_bits(cs35l41->regmap, CS35L41_PROTECT_REL_ERR_IGN, | ||
| 412 | CS35L41_TEMP_WARN_ERR_RLS, | ||
| 413 | CS35L41_TEMP_WARN_ERR_RLS); | ||
| 414 | regmap_update_bits(cs35l41->regmap, CS35L41_PROTECT_REL_ERR_IGN, | ||
| 415 | CS35L41_TEMP_WARN_ERR_RLS, 0); | ||
| 416 | ret = IRQ_HANDLED; | 427 | ret = IRQ_HANDLED; |
| 417 | } | 428 | } |
| 418 | 429 | ||
| 419 | if (status[0] & CS35L41_TEMP_ERR) { | 430 | if (status[0] & CS35L41_TEMP_ERR) { |
| 420 | dev_crit_ratelimited(cs35l41->dev, "Over temperature error\n"); | 431 | dev_crit_ratelimited(cs35l41->dev, "Over temperature error\n"); |
| 421 | regmap_write(cs35l41->regmap, CS35L41_IRQ1_STATUS1, | 432 | cs35l41_error_release(cs35l41, CS35L41_TEMP_ERR, CS35L41_TEMP_ERR_RLS); |
| 422 | CS35L41_TEMP_ERR); | ||
| 423 | regmap_write(cs35l41->regmap, CS35L41_PROTECT_REL_ERR_IGN, 0); | ||
| 424 | regmap_update_bits(cs35l41->regmap, CS35L41_PROTECT_REL_ERR_IGN, | ||
| 425 | CS35L41_TEMP_ERR_RLS, | ||
| 426 | CS35L41_TEMP_ERR_RLS); | ||
| 427 | regmap_update_bits(cs35l41->regmap, CS35L41_PROTECT_REL_ERR_IGN, | ||
| 428 | CS35L41_TEMP_ERR_RLS, 0); | ||
| 429 | ret = IRQ_HANDLED; | 433 | ret = IRQ_HANDLED; |
| 430 | } | 434 | } |
| 431 | 435 | ||
| 432 | if (status[0] & CS35L41_BST_OVP_ERR) { | 436 | if (status[0] & CS35L41_BST_OVP_ERR) { |
| 433 | dev_crit_ratelimited(cs35l41->dev, "VBST Over Voltage error\n"); | 437 | dev_crit_ratelimited(cs35l41->dev, "VBST Over Voltage error\n"); |
| 434 | regmap_update_bits(cs35l41->regmap, CS35L41_PWR_CTRL2, | 438 | cs35l41_boost_enable(cs35l41, 0); |
| 435 | CS35L41_BST_EN_MASK, 0); | 439 | cs35l41_error_release(cs35l41, CS35L41_BST_OVP_ERR, CS35L41_BST_OVP_ERR_RLS); |
| 436 | regmap_write(cs35l41->regmap, CS35L41_IRQ1_STATUS1, | 440 | cs35l41_boost_enable(cs35l41, 1); |
| 437 | CS35L41_BST_OVP_ERR); | ||
| 438 | regmap_write(cs35l41->regmap, CS35L41_PROTECT_REL_ERR_IGN, 0); | ||
| 439 | regmap_update_bits(cs35l41->regmap, CS35L41_PROTECT_REL_ERR_IGN, | ||
| 440 | CS35L41_BST_OVP_ERR_RLS, | ||
| 441 | CS35L41_BST_OVP_ERR_RLS); | ||
| 442 | regmap_update_bits(cs35l41->regmap, CS35L41_PROTECT_REL_ERR_IGN, | ||
| 443 | CS35L41_BST_OVP_ERR_RLS, 0); | ||
| 444 | regmap_update_bits(cs35l41->regmap, CS35L41_PWR_CTRL2, | ||
| 445 | CS35L41_BST_EN_MASK, | ||
| 446 | CS35L41_BST_EN_DEFAULT << CS35L41_BST_EN_SHIFT); | ||
| 447 | ret = IRQ_HANDLED; | 441 | ret = IRQ_HANDLED; |
| 448 | } | 442 | } |
| 449 | 443 | ||
| 450 | if (status[0] & CS35L41_BST_DCM_UVP_ERR) { | 444 | if (status[0] & CS35L41_BST_DCM_UVP_ERR) { |
| 451 | dev_crit_ratelimited(cs35l41->dev, "DCM VBST Under Voltage Error\n"); | 445 | dev_crit_ratelimited(cs35l41->dev, "DCM VBST Under Voltage Error\n"); |
| 452 | regmap_update_bits(cs35l41->regmap, CS35L41_PWR_CTRL2, | 446 | cs35l41_boost_enable(cs35l41, 0); |
| 453 | CS35L41_BST_EN_MASK, 0); | 447 | cs35l41_error_release(cs35l41, CS35L41_BST_DCM_UVP_ERR, CS35L41_BST_UVP_ERR_RLS); |
| 454 | regmap_write(cs35l41->regmap, CS35L41_IRQ1_STATUS1, | 448 | cs35l41_boost_enable(cs35l41, 1); |
| 455 | CS35L41_BST_DCM_UVP_ERR); | ||
| 456 | regmap_write(cs35l41->regmap, CS35L41_PROTECT_REL_ERR_IGN, 0); | ||
| 457 | regmap_update_bits(cs35l41->regmap, CS35L41_PROTECT_REL_ERR_IGN, | ||
| 458 | CS35L41_BST_UVP_ERR_RLS, | ||
| 459 | CS35L41_BST_UVP_ERR_RLS); | ||
| 460 | regmap_update_bits(cs35l41->regmap, CS35L41_PROTECT_REL_ERR_IGN, | ||
| 461 | CS35L41_BST_UVP_ERR_RLS, 0); | ||
| 462 | regmap_update_bits(cs35l41->regmap, CS35L41_PWR_CTRL2, | ||
| 463 | CS35L41_BST_EN_MASK, | ||
| 464 | CS35L41_BST_EN_DEFAULT << CS35L41_BST_EN_SHIFT); | ||
| 465 | ret = IRQ_HANDLED; | 449 | ret = IRQ_HANDLED; |
| 466 | } | 450 | } |
| 467 | 451 | ||
| 468 | if (status[0] & CS35L41_BST_SHORT_ERR) { | 452 | if (status[0] & CS35L41_BST_SHORT_ERR) { |
| 469 | dev_crit_ratelimited(cs35l41->dev, "LBST error: powering off!\n"); | 453 | dev_crit_ratelimited(cs35l41->dev, "LBST error: powering off!\n"); |
| 470 | regmap_update_bits(cs35l41->regmap, CS35L41_PWR_CTRL2, | 454 | cs35l41_boost_enable(cs35l41, 0); |
| 471 | CS35L41_BST_EN_MASK, 0); | 455 | cs35l41_error_release(cs35l41, CS35L41_BST_SHORT_ERR, CS35L41_BST_SHORT_ERR_RLS); |
| 472 | regmap_write(cs35l41->regmap, CS35L41_IRQ1_STATUS1, | 456 | cs35l41_boost_enable(cs35l41, 1); |
| 473 | CS35L41_BST_SHORT_ERR); | 457 | ret = IRQ_HANDLED; |
| 474 | regmap_write(cs35l41->regmap, CS35L41_PROTECT_REL_ERR_IGN, 0); | 458 | } |
| 475 | regmap_update_bits(cs35l41->regmap, CS35L41_PROTECT_REL_ERR_IGN, | 459 | |
| 476 | CS35L41_BST_SHORT_ERR_RLS, | 460 | if (status[2] & CS35L41_PLL_LOCK) { |
| 477 | CS35L41_BST_SHORT_ERR_RLS); | 461 | regmap_write(cs35l41->regmap, CS35L41_IRQ1_STATUS3, CS35L41_PLL_LOCK); |
| 478 | regmap_update_bits(cs35l41->regmap, CS35L41_PROTECT_REL_ERR_IGN, | 462 | complete(&cs35l41->pll_lock); |
| 479 | CS35L41_BST_SHORT_ERR_RLS, 0); | ||
| 480 | regmap_update_bits(cs35l41->regmap, CS35L41_PWR_CTRL2, | ||
| 481 | CS35L41_BST_EN_MASK, | ||
| 482 | CS35L41_BST_EN_DEFAULT << CS35L41_BST_EN_SHIFT); | ||
| 483 | ret = IRQ_HANDLED; | 463 | ret = IRQ_HANDLED; |
| 484 | } | 464 | } |
| 485 | 465 | ||
| @@ -520,10 +500,12 @@ static int cs35l41_main_amp_event(struct snd_soc_dapm_widget *w, · 34 unmodified lines | |||
| 520 | cs35l41_pup_patch, | 500 | cs35l41_pup_patch, |
| 521 | ARRAY_SIZE(cs35l41_pup_patch)); | 501 | ARRAY_SIZE(cs35l41_pup_patch)); |
| 522 | 502 | ||
| 523 | cs35l41_global_enable(cs35l41->regmap, cs35l41->hw_cfg.bst_type, 1); | 503 | cs35l41_global_enable(cs35l41->regmap, cs35l41->hw_cfg.bst_type, 1, |
| 504 | &cs35l41->pll_lock); | ||
| 524 | break; | 505 | break; |
| 525 | case SND_SOC_DAPM_POST_PMD: | 506 | case SND_SOC_DAPM_POST_PMD: |
| 526 | cs35l41_global_enable(cs35l41->regmap, cs35l41->hw_cfg.bst_type, 0); | 507 | cs35l41_global_enable(cs35l41->regmap, cs35l41->hw_cfg.bst_type, 0, |
| 508 | &cs35l41->pll_lock); | ||
| 527 | 509 | ||
| 528 | ret = regmap_read_poll_timeout(cs35l41->regmap, CS35L41_IRQ1_STATUS1, | 510 | ret = regmap_read_poll_timeout(cs35l41->regmap, CS35L41_IRQ1_STATUS1, |
| 529 | val, val & CS35L41_PDN_DONE_MASK, | 511 | val, val & CS35L41_PDN_DONE_MASK, |
| @@ -830,6 +812,10 @@ static const struct snd_pcm_hw_constraint_list cs35l41_constraints = { · 300 unmodified lines | |||
| 830 | static int cs35l41_pcm_startup(struct snd_pcm_substream *substream, | 812 | static int cs35l41_pcm_startup(struct snd_pcm_substream *substream, |
| 831 | struct snd_soc_dai *dai) | 813 | struct snd_soc_dai *dai) |
| 832 | { | 814 | { |
| 815 | struct cs35l41_private *cs35l41 = snd_soc_component_get_drvdata(dai->component); | ||
| 816 | |||
| 817 | reinit_completion(&cs35l41->pll_lock); | ||
| 818 | |||
| 833 | if (substream->runtime) | 819 | if (substream->runtime) |
| 834 | return snd_pcm_hw_constraint_list(substream->runtime, 0, | 820 | return snd_pcm_hw_constraint_list(substream->runtime, 0, |
| 835 | SNDRV_PCM_HW_PARAM_RATE, | 821 | SNDRV_PCM_HW_PARAM_RATE, |
| @@ -1037,9 +1023,21 @@ static int cs35l41_handle_pdata(struct device *dev, struct cs35l41_hw_cfg *hw_cf · 201 unmodified lines | |||
| 1037 | unsigned int val; | 1023 | unsigned int val; |
| 1038 | int ret; | 1024 | int ret; |
| 1039 | 1025 | ||
| 1040 | ret = device_property_read_u32(dev, "cirrus,boost-type", &val); | 1026 | /* Some ACPI systems received the Shared Boost feature before the upstream driver, |
| 1041 | if (ret >= 0) | 1027 | * leaving those systems with deprecated _DSD properties. |
| 1042 | hw_cfg->bst_type = val; | 1028 | * To correctly configure those systems add shared-boost-active and shared-boost-passive |
| 1029 | * properties mapped to the correct value in boost-type. | ||
| 1030 | * These two are not DT properties and should not be used in new systems designs. | ||
| 1031 | */ | ||
| 1032 | if (device_property_read_bool(dev, "cirrus,shared-boost-active")) { | ||
| 1033 | hw_cfg->bst_type = CS35L41_SHD_BOOST_ACTV; | ||
| 1034 | } else if (device_property_read_bool(dev, "cirrus,shared-boost-passive")) { | ||
| 1035 | hw_cfg->bst_type = CS35L41_SHD_BOOST_PASS; | ||
| 1036 | } else { | ||
| 1037 | ret = device_property_read_u32(dev, "cirrus,boost-type", &val); | ||
| 1038 | if (ret >= 0) | ||
| 1039 | hw_cfg->bst_type = val; | ||
| 1040 | } | ||
| 1043 | 1041 | ||
| 1044 | ret = device_property_read_u32(dev, "cirrus,boost-peak-milliamp", &val); | 1042 | ret = device_property_read_u32(dev, "cirrus,boost-peak-milliamp", &val); |
| 1045 | if (ret >= 0) | 1043 | if (ret >= 0) |
| @@ -1280,6 +1278,10 @@ int cs35l41_probe(struct cs35l41_private *cs35l41, const struct cs35l41_hw_cfg * · 234 unmodified lines | |||
| 1280 | /* Set interrupt masks for critical errors */ | 1278 | /* Set interrupt masks for critical errors */ |
| 1281 | regmap_write(cs35l41->regmap, CS35L41_IRQ1_MASK1, | 1279 | regmap_write(cs35l41->regmap, CS35L41_IRQ1_MASK1, |
| 1282 | CS35L41_INT1_MASK_DEFAULT); | 1280 | CS35L41_INT1_MASK_DEFAULT); |
| 1281 | if (cs35l41->hw_cfg.bst_type == CS35L41_SHD_BOOST_PASS || | ||
| 1282 | cs35l41->hw_cfg.bst_type == CS35L41_SHD_BOOST_ACTV) | ||
| 1283 | regmap_update_bits(cs35l41->regmap, CS35L41_IRQ1_MASK3, CS35L41_INT3_PLL_LOCK_MASK, | ||
| 1284 | 0 << CS35L41_INT3_PLL_LOCK_SHIFT); | ||
| 1283 | 1285 | ||
| 1284 | ret = devm_request_threaded_irq(cs35l41->dev, cs35l41->irq, NULL, cs35l41_irq, | 1286 | ret = devm_request_threaded_irq(cs35l41->dev, cs35l41->irq, NULL, cs35l41_irq, |
| 1285 | IRQF_ONESHOT | IRQF_SHARED | irq_pol, | 1287 | IRQF_ONESHOT | IRQF_SHARED | irq_pol, |
| @@ -1303,6 +1305,8 @@ int cs35l41_probe(struct cs35l41_private *cs35l41, const struct cs35l41_hw_cfg * · 17 unmodified lines | |||
| 1303 | if (ret < 0) | 1305 | if (ret < 0) |
| 1304 | goto err; | 1306 | goto err; |
| 1305 | 1307 | ||
| 1308 | init_completion(&cs35l41->pll_lock); | ||
| 1309 | |||
| 1306 | pm_runtime_set_autosuspend_delay(cs35l41->dev, 3000); | 1310 | pm_runtime_set_autosuspend_delay(cs35l41->dev, 3000); |
| 1307 | pm_runtime_use_autosuspend(cs35l41->dev); | 1311 | pm_runtime_use_autosuspend(cs35l41->dev); |
| 1308 | pm_runtime_mark_last_busy(cs35l41->dev); | 1312 | pm_runtime_mark_last_busy(cs35l41->dev); |
| @@ -1345,6 +1349,10 @@ void cs35l41_remove(struct cs35l41_private *cs35l41) · 36 unmodified lines | |||
| 1345 | pm_runtime_disable(cs35l41->dev); | 1349 | pm_runtime_disable(cs35l41->dev); |
| 1346 | 1350 | ||
| 1347 | regmap_write(cs35l41->regmap, CS35L41_IRQ1_MASK1, 0xFFFFFFFF); | 1351 | regmap_write(cs35l41->regmap, CS35L41_IRQ1_MASK1, 0xFFFFFFFF); |
| 1352 | if (cs35l41->hw_cfg.bst_type == CS35L41_SHD_BOOST_PASS || | ||
| 1353 | cs35l41->hw_cfg.bst_type == CS35L41_SHD_BOOST_ACTV) | ||
| 1354 | regmap_update_bits(cs35l41->regmap, CS35L41_IRQ1_MASK3, CS35L41_INT3_PLL_LOCK_MASK, | ||
| 1355 | 1 << CS35L41_INT3_PLL_LOCK_SHIFT); | ||
| 1348 | kfree(cs35l41->dsp.system_name); | 1356 | kfree(cs35l41->dsp.system_name); |
| 1349 | wm_adsp2_remove(&cs35l41->dsp); | 1357 | wm_adsp2_remove(&cs35l41->dsp); |
| 1350 | cs35l41_safe_reset(cs35l41->regmap, cs35l41->hw_cfg.bst_type); | 1358 | cs35l41_safe_reset(cs35l41->regmap, cs35l41->hw_cfg.bst_type); |
| @@ -33,6 +33,7 @@ struct cs35l41_private { · 32 unmodified lines | |||
| 33 | int irq; | 33 | int irq; |
| 34 | /* GPIO for /RST */ | 34 | /* GPIO for /RST */ |
| 35 | struct gpio_desc *reset_gpio; | 35 | struct gpio_desc *reset_gpio; |
| 36 | struct completion pll_lock; | ||
| 36 | }; | 37 | }; |
| 37 | 38 | ||
| 38 | int cs35l41_probe(struct cs35l41_private *cs35l41, const struct cs35l41_hw_cfg *hw_cfg); | 39 | int cs35l41_probe(struct cs35l41_private *cs35l41, const struct cs35l41_hw_cfg *hw_cfg); |
| @@ -32,6 +32,9 @@ static int cs35l45_i2c_probe(struct i2c_client *client) · 31 unmodified lines | |||
| 32 | } | 32 | } |
| 33 | 33 | ||
| 34 | cs35l45->dev = dev; | 34 | cs35l45->dev = dev; |
| 35 | cs35l45->irq = client->irq; | ||
| 36 | cs35l45->bus_type = CONTROL_BUS_I2C; | ||
| 37 | cs35l45->i2c_addr = client->addr; | ||
| 35 | 38 | ||
| 36 | return cs35l45_probe(cs35l45); | 39 | return cs35l45_probe(cs35l45); |
| 37 | } | 40 | } |
| @@ -23,6 +23,9 @@ static int cs35l45_spi_probe(struct spi_device *spi) · 22 unmodified lines | |||
| 23 | if (cs35l45 == NULL) | 23 | if (cs35l45 == NULL) |
| 24 | return -ENOMEM; | 24 | return -ENOMEM; |
| 25 | 25 | ||
| 26 | spi->max_speed_hz = CS35L45_SPI_MAX_FREQ; | ||
| 27 | spi_setup(spi); | ||
| 28 | |||
| 26 | spi_set_drvdata(spi, cs35l45); | 29 | spi_set_drvdata(spi, cs35l45); |
| 27 | cs35l45->regmap = devm_regmap_init_spi(spi, &cs35l45_spi_regmap); | 30 | cs35l45->regmap = devm_regmap_init_spi(spi, &cs35l45_spi_regmap); |
| 28 | if (IS_ERR(cs35l45->regmap)) { | 31 | if (IS_ERR(cs35l45->regmap)) { |
| @@ -32,6 +35,8 @@ static int cs35l45_spi_probe(struct spi_device *spi) · 3 unmodified lines | |||
| 32 | } | 35 | } |
| 33 | 36 | ||
| 34 | cs35l45->dev = dev; | 37 | cs35l45->dev = dev; |
| 38 | cs35l45->irq = spi->irq; | ||
| 39 | cs35l45->bus_type = CONTROL_BUS_SPI; | ||
| 35 | 40 | ||
| 36 | return cs35l45_probe(cs35l45); | 41 | return cs35l45_probe(cs35l45); |
| 37 | } | 42 | } |
| @@ -43,6 +43,12 @@ EXPORT_SYMBOL_NS_GPL(cs35l45_apply_patch, SND_SOC_CS35L45); · 42 unmodified lines | |||
| 43 | static const struct reg_default cs35l45_defaults[] = { | 43 | static const struct reg_default cs35l45_defaults[] = { |
| 44 | { CS35L45_BLOCK_ENABLES, 0x00003323 }, | 44 | { CS35L45_BLOCK_ENABLES, 0x00003323 }, |
| 45 | { CS35L45_BLOCK_ENABLES2, 0x00000010 }, | 45 | { CS35L45_BLOCK_ENABLES2, 0x00000010 }, |
| 46 | { CS35L45_SYNC_GPIO1, 0x00000007 }, | ||
| 47 | { CS35L45_INTB_GPIO2_MCLK_REF, 0x00000005 }, | ||
| 48 | { CS35L45_GPIO3, 0x00000005 }, | ||
| 49 | { CS35L45_PWRMGT_CTL, 0x00000000 }, | ||
| 50 | { CS35L45_WAKESRC_CTL, 0x00000008 }, | ||
| 51 | { CS35L45_WKI2C_CTL, 0x00000030 }, | ||
| 46 | { CS35L45_REFCLK_INPUT, 0x00000510 }, | 52 | { CS35L45_REFCLK_INPUT, 0x00000510 }, |
| 47 | { CS35L45_GLOBAL_SAMPLE_RATE, 0x00000003 }, | 53 | { CS35L45_GLOBAL_SAMPLE_RATE, 0x00000003 }, |
| 48 | { CS35L45_ASP_ENABLES1, 0x00000000 }, | 54 | { CS35L45_ASP_ENABLES1, 0x00000000 }, |
| @@ -60,7 +66,53 @@ static const struct reg_default cs35l45_defaults[] = { · 11 unmodified lines | |||
| 60 | { CS35L45_ASPTX3_INPUT, 0x00000020 }, | 66 | { CS35L45_ASPTX3_INPUT, 0x00000020 }, |
| 61 | { CS35L45_ASPTX4_INPUT, 0x00000028 }, | 67 | { CS35L45_ASPTX4_INPUT, 0x00000028 }, |
| 62 | { CS35L45_ASPTX5_INPUT, 0x00000048 }, | 68 | { CS35L45_ASPTX5_INPUT, 0x00000048 }, |
| 69 | { CS35L45_DSP1_RX1_RATE, 0x00000001 }, | ||
| 70 | { CS35L45_DSP1_RX2_RATE, 0x00000001 }, | ||
| 71 | { CS35L45_DSP1_RX3_RATE, 0x00000001 }, | ||
| 72 | { CS35L45_DSP1_RX4_RATE, 0x00000001 }, | ||
| 73 | { CS35L45_DSP1_RX5_RATE, 0x00000001 }, | ||
| 74 | { CS35L45_DSP1_RX6_RATE, 0x00000001 }, | ||
| 75 | { CS35L45_DSP1_RX7_RATE, 0x00000001 }, | ||
| 76 | { CS35L45_DSP1_RX8_RATE, 0x00000001 }, | ||
| 77 | { CS35L45_DSP1_TX1_RATE, 0x00000001 }, | ||
| 78 | { CS35L45_DSP1_TX2_RATE, 0x00000001 }, | ||
| 79 | { CS35L45_DSP1_TX3_RATE, 0x00000001 }, | ||
| 80 | { CS35L45_DSP1_TX4_RATE, 0x00000001 }, | ||
| 81 | { CS35L45_DSP1_TX5_RATE, 0x00000001 }, | ||
| 82 | { CS35L45_DSP1_TX6_RATE, 0x00000001 }, | ||
| 83 | { CS35L45_DSP1_TX7_RATE, 0x00000001 }, | ||
| 84 | { CS35L45_DSP1_TX8_RATE, 0x00000001 }, | ||
| 85 | { CS35L45_DSP1RX1_INPUT, 0x00000008 }, | ||
| 86 | { CS35L45_DSP1RX2_INPUT, 0x00000009 }, | ||
| 87 | { CS35L45_DSP1RX3_INPUT, 0x00000018 }, | ||
| 88 | { CS35L45_DSP1RX4_INPUT, 0x00000019 }, | ||
| 89 | { CS35L45_DSP1RX5_INPUT, 0x00000020 }, | ||
| 90 | { CS35L45_DSP1RX6_INPUT, 0x00000028 }, | ||
| 91 | { CS35L45_DSP1RX7_INPUT, 0x0000003A }, | ||
| 92 | { CS35L45_DSP1RX8_INPUT, 0x00000028 }, | ||
| 63 | { CS35L45_AMP_PCM_CONTROL, 0x00100000 }, | 93 | { CS35L45_AMP_PCM_CONTROL, 0x00100000 }, |
| 94 | { CS35L45_IRQ1_CFG, 0x00000000 }, | ||
| 95 | { CS35L45_IRQ1_MASK_1, 0xBFEFFFBF }, | ||
| 96 | { CS35L45_IRQ1_MASK_2, 0xFFFFFFFF }, | ||
| 97 | { CS35L45_IRQ1_MASK_3, 0xFFFF87FF }, | ||
| 98 | { CS35L45_IRQ1_MASK_4, 0xF8FFFFFF }, | ||
| 99 | { CS35L45_IRQ1_MASK_5, 0x0EF80000 }, | ||
| 100 | { CS35L45_IRQ1_MASK_6, 0x00000000 }, | ||
| 101 | { CS35L45_IRQ1_MASK_7, 0xFFFFFF78 }, | ||
| 102 | { CS35L45_IRQ1_MASK_8, 0x00003FFF }, | ||
| 103 | { CS35L45_IRQ1_MASK_9, 0x00000000 }, | ||
| 104 | { CS35L45_IRQ1_MASK_10, 0x00000000 }, | ||
| 105 | { CS35L45_IRQ1_MASK_11, 0x00000000 }, | ||
| 106 | { CS35L45_IRQ1_MASK_12, 0x00000000 }, | ||
| 107 | { CS35L45_IRQ1_MASK_13, 0x00000000 }, | ||
| 108 | { CS35L45_IRQ1_MASK_14, 0x00000001 }, | ||
| 109 | { CS35L45_IRQ1_MASK_15, 0x00000000 }, | ||
| 110 | { CS35L45_IRQ1_MASK_16, 0x00000000 }, | ||
| 111 | { CS35L45_IRQ1_MASK_17, 0x00000000 }, | ||
| 112 | { CS35L45_IRQ1_MASK_18, 0x3FE5D0FF }, | ||
| 113 | { CS35L45_GPIO1_CTRL1, 0x81000001 }, | ||
| 114 | { CS35L45_GPIO2_CTRL1, 0x81000001 }, | ||
| 115 | { CS35L45_GPIO3_CTRL1, 0x81000001 }, | ||
| 64 | }; | 116 | }; |
| 65 | 117 | ||
| 66 | static bool cs35l45_readable_reg(struct device *dev, unsigned int reg) | 118 | static bool cs35l45_readable_reg(struct device *dev, unsigned int reg) |
| @@ -72,6 +124,13 @@ static bool cs35l45_readable_reg(struct device *dev, unsigned int reg) · 5 unmodified lines | |||
| 72 | case CS35L45_BLOCK_ENABLES: | 124 | case CS35L45_BLOCK_ENABLES: |
| 73 | case CS35L45_BLOCK_ENABLES2: | 125 | case CS35L45_BLOCK_ENABLES2: |
| 74 | case CS35L45_ERROR_RELEASE: | 126 | case CS35L45_ERROR_RELEASE: |
| 127 | case CS35L45_SYNC_GPIO1: | ||
| 128 | case CS35L45_INTB_GPIO2_MCLK_REF: | ||
| 129 | case CS35L45_GPIO3: | ||
| 130 | case CS35L45_PWRMGT_CTL: | ||
| 131 | case CS35L45_WAKESRC_CTL: | ||
| 132 | case CS35L45_WKI2C_CTL: | ||
| 133 | case CS35L45_PWRMGT_STS: | ||
| 75 | case CS35L45_REFCLK_INPUT: | 134 | case CS35L45_REFCLK_INPUT: |
| 76 | case CS35L45_GLOBAL_SAMPLE_RATE: | 135 | case CS35L45_GLOBAL_SAMPLE_RATE: |
| 77 | case CS35L45_ASP_ENABLES1: | 136 | case CS35L45_ASP_ENABLES1: |
| @@ -89,9 +148,59 @@ static bool cs35l45_readable_reg(struct device *dev, unsigned int reg) · 11 unmodified lines | |||
| 89 | case CS35L45_ASPTX3_INPUT: | 148 | case CS35L45_ASPTX3_INPUT: |
| 90 | case CS35L45_ASPTX4_INPUT: | 149 | case CS35L45_ASPTX4_INPUT: |
| 91 | case CS35L45_ASPTX5_INPUT: | 150 | case CS35L45_ASPTX5_INPUT: |
| 151 | case CS35L45_DSP1RX1_INPUT: | ||
| 152 | case CS35L45_DSP1RX2_INPUT: | ||
| 153 | case CS35L45_DSP1RX3_INPUT: | ||
| 154 | case CS35L45_DSP1RX4_INPUT: | ||
| 155 | case CS35L45_DSP1RX5_INPUT: | ||
| 156 | case CS35L45_DSP1RX6_INPUT: | ||
| 157 | case CS35L45_DSP1RX7_INPUT: | ||
| 158 | case CS35L45_DSP1RX8_INPUT: | ||
| 92 | case CS35L45_AMP_PCM_CONTROL: | 159 | case CS35L45_AMP_PCM_CONTROL: |
| 93 | case CS35L45_AMP_PCM_HPF_TST: | 160 | case CS35L45_AMP_PCM_HPF_TST: |
| 94 | case CS35L45_IRQ1_EINT_4: | 161 | case CS35L45_IRQ1_CFG: |
| 162 | case CS35L45_IRQ1_STATUS: | ||
| 163 | case CS35L45_IRQ1_EINT_1 ... CS35L45_IRQ1_EINT_18: | ||
| 164 | case CS35L45_IRQ1_STS_1 ... CS35L45_IRQ1_STS_18: | ||
| 165 | case CS35L45_IRQ1_MASK_1 ... CS35L45_IRQ1_MASK_18: | ||
| 166 | case CS35L45_GPIO_STATUS1: | ||
| 167 | case CS35L45_GPIO1_CTRL1: | ||
| 168 | case CS35L45_GPIO2_CTRL1: | ||
| 169 | case CS35L45_GPIO3_CTRL1: | ||
| 170 | case CS35L45_DSP_MBOX_1: | ||
| 171 | case CS35L45_DSP_MBOX_2: | ||
| 172 | case CS35L45_DSP_VIRT1_MBOX_1 ... CS35L45_DSP_VIRT1_MBOX_4: | ||
| 173 | case CS35L45_DSP_VIRT2_MBOX_1 ... CS35L45_DSP_VIRT2_MBOX_4: | ||
| 174 | case CS35L45_DSP1_SYS_ID: | ||
| 175 | case CS35L45_DSP1_CLOCK_FREQ: | ||
| 176 | case CS35L45_DSP1_RX1_RATE: | ||
| 177 | case CS35L45_DSP1_RX2_RATE: | ||
| 178 | case CS35L45_DSP1_RX3_RATE: | ||
| 179 | case CS35L45_DSP1_RX4_RATE: | ||
| 180 | case CS35L45_DSP1_RX5_RATE: | ||
| 181 | case CS35L45_DSP1_RX6_RATE: | ||
| 182 | case CS35L45_DSP1_RX7_RATE: | ||
| 183 | case CS35L45_DSP1_RX8_RATE: | ||
| 184 | case CS35L45_DSP1_TX1_RATE: | ||
| 185 | case CS35L45_DSP1_TX2_RATE: | ||
| 186 | case CS35L45_DSP1_TX3_RATE: | ||
| 187 | case CS35L45_DSP1_TX4_RATE: | ||
| 188 | case CS35L45_DSP1_TX5_RATE: | ||
| 189 | case CS35L45_DSP1_TX6_RATE: | ||
| 190 | case CS35L45_DSP1_TX7_RATE: | ||
| 191 | case CS35L45_DSP1_TX8_RATE: | ||
| 192 | case CS35L45_DSP1_SCRATCH1: | ||
| 193 | case CS35L45_DSP1_SCRATCH2: | ||
| 194 | case CS35L45_DSP1_SCRATCH3: | ||
| 195 | case CS35L45_DSP1_SCRATCH4: | ||
| 196 | case CS35L45_DSP1_CCM_CORE_CONTROL: | ||
| 197 | case CS35L45_DSP1_XMEM_PACK_0 ... CS35L45_DSP1_XMEM_PACK_4607: | ||
| 198 | case CS35L45_DSP1_XMEM_UNPACK32_0 ... CS35L45_DSP1_XMEM_UNPACK32_3071: | ||
| 199 | case CS35L45_DSP1_XMEM_UNPACK24_0 ... CS35L45_DSP1_XMEM_UNPACK24_6143: | ||
| 200 | case CS35L45_DSP1_YMEM_PACK_0 ... CS35L45_DSP1_YMEM_PACK_1532: | ||
| 201 | case CS35L45_DSP1_YMEM_UNPACK32_0 ... CS35L45_DSP1_YMEM_UNPACK32_1022: | ||
| 202 | case CS35L45_DSP1_YMEM_UNPACK24_0 ... CS35L45_DSP1_YMEM_UNPACK24_2043: | ||
| 203 | case CS35L45_DSP1_PMEM_0 ... CS35L45_DSP1_PMEM_3834: | ||
| 95 | return true; | 204 | return true; |
| 96 | default: | 205 | default: |
| 97 | return false; | 206 | return false; |
| @@ -106,7 +215,29 @@ static bool cs35l45_volatile_reg(struct device *dev, unsigned int reg) · 8 unmodified lines | |||
| 106 | case CS35L45_GLOBAL_ENABLES: | 215 | case CS35L45_GLOBAL_ENABLES: |
| 107 | case CS35L45_ERROR_RELEASE: | 216 | case CS35L45_ERROR_RELEASE: |
| 108 | case CS35L45_AMP_PCM_HPF_TST: /* not cachable */ | 217 | case CS35L45_AMP_PCM_HPF_TST: /* not cachable */ |
| 109 | case CS35L45_IRQ1_EINT_4: | 218 | case CS35L45_PWRMGT_STS: |
| 219 | case CS35L45_IRQ1_STATUS: | ||
| 220 | case CS35L45_IRQ1_EINT_1 ... CS35L45_IRQ1_EINT_18: | ||
| 221 | case CS35L45_IRQ1_STS_1 ... CS35L45_IRQ1_STS_18: | ||
| 222 | case CS35L45_GPIO_STATUS1: | ||
| 223 | case CS35L45_DSP_MBOX_1: | ||
| 224 | case CS35L45_DSP_MBOX_2: | ||
| 225 | case CS35L45_DSP_VIRT1_MBOX_1 ... CS35L45_DSP_VIRT1_MBOX_4: | ||
| 226 | case CS35L45_DSP_VIRT2_MBOX_1 ... CS35L45_DSP_VIRT2_MBOX_4: | ||
| 227 | case CS35L45_DSP1_SYS_ID: | ||
| 228 | case CS35L45_DSP1_CLOCK_FREQ: | ||
| 229 | case CS35L45_DSP1_SCRATCH1: | ||
| 230 | case CS35L45_DSP1_SCRATCH2: | ||
| 231 | case CS35L45_DSP1_SCRATCH3: | ||
| 232 | case CS35L45_DSP1_SCRATCH4: | ||
| 233 | case CS35L45_DSP1_CCM_CORE_CONTROL: | ||
| 234 | case CS35L45_DSP1_XMEM_PACK_0 ... CS35L45_DSP1_XMEM_PACK_4607: | ||
| 235 | case CS35L45_DSP1_XMEM_UNPACK32_0 ... CS35L45_DSP1_XMEM_UNPACK32_3071: | ||
| 236 | case CS35L45_DSP1_XMEM_UNPACK24_0 ... CS35L45_DSP1_XMEM_UNPACK24_6143: | ||
| 237 | case CS35L45_DSP1_YMEM_PACK_0 ... CS35L45_DSP1_YMEM_PACK_1532: | ||
| 238 | case CS35L45_DSP1_YMEM_UNPACK32_0 ... CS35L45_DSP1_YMEM_UNPACK32_1022: | ||
| 239 | case CS35L45_DSP1_YMEM_UNPACK24_0 ... CS35L45_DSP1_YMEM_UNPACK24_2043: | ||
| 240 | case CS35L45_DSP1_PMEM_0 ... CS35L45_DSP1_PMEM_3834: | ||
| 110 | return true; | 241 | return true; |
| 111 | default: | 242 | default: |
| 112 | return false; | 243 | return false; |
| @@ -10,6 +10,7 @@ · 9 unmodified lines | |||
| 10 | #include <linux/module.h> | 10 | #include <linux/module.h> |
| 11 | #include <linux/pm_runtime.h> | 11 | #include <linux/pm_runtime.h> |
| 12 | #include <linux/property.h> | 12 | #include <linux/property.h> |
| 13 | #include <linux/firmware.h> | ||
| 13 | #include <linux/regulator/consumer.h> | 14 | #include <linux/regulator/consumer.h> |
| 14 | #include <sound/core.h> | 15 | #include <sound/core.h> |
| 15 | #include <sound/pcm.h> | 16 | #include <sound/pcm.h> |
| @@ -19,6 +20,71 @@ · 3 unmodified lines | |||
| 19 | 20 | ||
| 20 | #include "cs35l45.h" | 21 | #include "cs35l45.h" |
| 21 | 22 | ||
| 23 | static bool cs35l45_check_cspl_mbox_sts(const enum cs35l45_cspl_mboxcmd cmd, | ||
| 24 | enum cs35l45_cspl_mboxstate sts) | ||
| 25 | { | ||
| 26 | switch (cmd) { | ||
| 27 | case CSPL_MBOX_CMD_NONE: | ||
| 28 | case CSPL_MBOX_CMD_UNKNOWN_CMD: | ||
| 29 | return true; | ||
| 30 | case CSPL_MBOX_CMD_PAUSE: | ||
| 31 | case CSPL_MBOX_CMD_OUT_OF_HIBERNATE: | ||
| 32 | return (sts == CSPL_MBOX_STS_PAUSED); | ||
| 33 | case CSPL_MBOX_CMD_RESUME: | ||
| 34 | return (sts == CSPL_MBOX_STS_RUNNING); | ||
| 35 | case CSPL_MBOX_CMD_REINIT: | ||
| 36 | return (sts == CSPL_MBOX_STS_RUNNING); | ||
| 37 | case CSPL_MBOX_CMD_STOP_PRE_REINIT: | ||
| 38 | return (sts == CSPL_MBOX_STS_RDY_FOR_REINIT); | ||
| 39 | case CSPL_MBOX_CMD_HIBERNATE: | ||
| 40 | return (sts == CSPL_MBOX_STS_HIBERNATE); | ||
| 41 | default: | ||
| 42 | return false; | ||
| 43 | } | ||
| 44 | } | ||
| 45 | |||
| 46 | static int cs35l45_set_cspl_mbox_cmd(struct cs35l45_private *cs35l45, | ||
| 47 | struct regmap *regmap, | ||
| 48 | const enum cs35l45_cspl_mboxcmd cmd) | ||
| 49 | { | ||
| 50 | unsigned int sts = 0, i; | ||
| 51 | int ret; | ||
| 52 | |||
| 53 | if (!cs35l45->dsp.cs_dsp.running) { | ||
| 54 | dev_err(cs35l45->dev, "DSP not running\n"); | ||
| 55 | return -EPERM; | ||
| 56 | } | ||
| 57 | |||
| 58 | // Set mailbox cmd | ||
| 59 | ret = regmap_write(regmap, CS35L45_DSP_VIRT1_MBOX_1, cmd); | ||
| 60 | if (ret < 0) { | ||
| 61 | if (cmd != CSPL_MBOX_CMD_OUT_OF_HIBERNATE) | ||
| 62 | dev_err(cs35l45->dev, "Failed to write MBOX: %d\n", ret); | ||
| 63 | return ret; | ||
| 64 | } | ||
| 65 | |||
| 66 | // Read mailbox status and verify it is appropriate for the given cmd | ||
| 67 | for (i = 0; i < 5; i++) { | ||
| 68 | usleep_range(1000, 1100); | ||
| 69 | |||
| 70 | ret = regmap_read(regmap, CS35L45_DSP_MBOX_2, &sts); | ||
| 71 | if (ret < 0) { | ||
| 72 | dev_err(cs35l45->dev, "Failed to read MBOX STS: %d\n", ret); | ||
| 73 | continue; | ||
| 74 | } | ||
| 75 | |||
| 76 | if (!cs35l45_check_cspl_mbox_sts(cmd, sts)) | ||
| 77 | dev_dbg(cs35l45->dev, "[%u] cmd %u returned invalid sts %u", i, cmd, sts); | ||
| 78 | else | ||
| 79 | return 0; | ||
| 80 | } | ||
| 81 | |||
| 82 | if (cmd != CSPL_MBOX_CMD_OUT_OF_HIBERNATE) | ||
| 83 | dev_err(cs35l45->dev, "Failed to set mailbox cmd %u (status %u)\n", cmd, sts); | ||
| 84 | |||
| 85 | return -ENOMSG; | ||
| 86 | } | ||
| 87 | |||
| 22 | static int cs35l45_global_en_ev(struct snd_soc_dapm_widget *w, | 88 | static int cs35l45_global_en_ev(struct snd_soc_dapm_widget *w, |
| 23 | struct snd_kcontrol *kcontrol, int event) | 89 | struct snd_kcontrol *kcontrol, int event) |
| 24 | { | 90 | { |
| @@ -46,10 +112,68 @@ static int cs35l45_global_en_ev(struct snd_soc_dapm_widget *w, · 21 unmodified lines | |||
| 46 | return 0; | 112 | return 0; |
| 47 | } | 113 | } |
| 48 | 114 | ||
| 115 | static int cs35l45_dsp_preload_ev(struct snd_soc_dapm_widget *w, | ||
| 116 | struct snd_kcontrol *kcontrol, int event) | ||
| 117 | { | ||
| 118 | struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm); | ||
| 119 | struct cs35l45_private *cs35l45 = snd_soc_component_get_drvdata(component); | ||
| 120 | int ret; | ||
| 121 | |||
| 122 | switch (event) { | ||
| 123 | case SND_SOC_DAPM_PRE_PMU: | ||
| 124 | if (cs35l45->dsp.cs_dsp.booted) | ||
| 125 | return 0; | ||
| 126 | |||
| 127 | return wm_adsp_early_event(w, kcontrol, event); | ||
| 128 | case SND_SOC_DAPM_POST_PMU: | ||
| 129 | if (cs35l45->dsp.cs_dsp.running) | ||
| 130 | return 0; | ||
| 131 | |||
| 132 | regmap_set_bits(cs35l45->regmap, CS35L45_PWRMGT_CTL, | ||
| 133 | CS35L45_MEM_RDY_MASK); | ||
| 134 | |||
| 135 | return wm_adsp_event(w, kcontrol, event); | ||
| 136 | case SND_SOC_DAPM_PRE_PMD: | ||
| 137 | if (cs35l45->dsp.preloaded) | ||
| 138 | return 0; | ||
| 139 | |||
| 140 | if (cs35l45->dsp.cs_dsp.running) { | ||
| 141 | ret = wm_adsp_event(w, kcontrol, event); | ||
| 142 | if (ret) | ||
| 143 | return ret; | ||
| 144 | } | ||
| 145 | |||
| 146 | return wm_adsp_early_event(w, kcontrol, event); | ||
| 147 | default: | ||
| 148 | return 0; | ||
| 149 | } | ||
| 150 | } | ||
| 151 | |||
| 152 | static int cs35l45_dsp_audio_ev(struct snd_soc_dapm_widget *w, | ||
| 153 | struct snd_kcontrol *kcontrol, int event) | ||
| 154 | { | ||
| 155 | struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm); | ||
| 156 | struct cs35l45_private *cs35l45 = snd_soc_component_get_drvdata(component); | ||
| 157 | |||
| 158 | switch (event) { | ||
| 159 | case SND_SOC_DAPM_POST_PMU: | ||
| 160 | return cs35l45_set_cspl_mbox_cmd(cs35l45, cs35l45->regmap, | ||
| 161 | CSPL_MBOX_CMD_RESUME); | ||
| 162 | case SND_SOC_DAPM_PRE_PMD: | ||
| 163 | return cs35l45_set_cspl_mbox_cmd(cs35l45, cs35l45->regmap, | ||
| 164 | CSPL_MBOX_CMD_PAUSE); | ||
| 165 | default: | ||
| 166 | return 0; | ||
| 167 | } | ||
| 168 | |||
| 169 | return 0; | ||
| 170 | } | ||
| 171 | |||
| 49 | static const char * const cs35l45_asp_tx_txt[] = { | 172 | static const char * const cs35l45_asp_tx_txt[] = { |
| 50 | "Zero", "ASP_RX1", "ASP_RX2", | 173 | "Zero", "ASP_RX1", "ASP_RX2", |
| 51 | "VMON", "IMON", "ERR_VOL", | 174 | "VMON", "IMON", "ERR_VOL", |
| 52 | "VDD_BATTMON", "VDD_BSTMON", | 175 | "VDD_BATTMON", "VDD_BSTMON", |
| 176 | "DSP_TX1", "DSP_TX2", | ||
| 53 | "Interpolator", "IL_TARGET", | 177 | "Interpolator", "IL_TARGET", |
| 54 | }; | 178 | }; |
| 55 | 179 | ||
| @@ -57,6 +181,7 @@ static const unsigned int cs35l45_asp_tx_val[] = { · 1 unmodified line | |||
| 57 | CS35L45_PCM_SRC_ZERO, CS35L45_PCM_SRC_ASP_RX1, CS35L45_PCM_SRC_ASP_RX2, | 181 | CS35L45_PCM_SRC_ZERO, CS35L45_PCM_SRC_ASP_RX1, CS35L45_PCM_SRC_ASP_RX2, |
| 58 | CS35L45_PCM_SRC_VMON, CS35L45_PCM_SRC_IMON, CS35L45_PCM_SRC_ERR_VOL, | 182 | CS35L45_PCM_SRC_VMON, CS35L45_PCM_SRC_IMON, CS35L45_PCM_SRC_ERR_VOL, |
| 59 | CS35L45_PCM_SRC_VDD_BATTMON, CS35L45_PCM_SRC_VDD_BSTMON, | 183 | CS35L45_PCM_SRC_VDD_BATTMON, CS35L45_PCM_SRC_VDD_BSTMON, |
| 184 | CS35L45_PCM_SRC_DSP_TX1, CS35L45_PCM_SRC_DSP_TX2, | ||
| 60 | CS35L45_PCM_SRC_INTERPOLATOR, CS35L45_PCM_SRC_IL_TARGET, | 185 | CS35L45_PCM_SRC_INTERPOLATOR, CS35L45_PCM_SRC_IL_TARGET, |
| 61 | }; | 186 | }; |
| 62 | 187 | ||
| @@ -78,12 +203,54 @@ static const struct soc_enum cs35l45_asp_tx_enums[] = { · 15 unmodified lines | |||
| 78 | cs35l45_asp_tx_val), | 203 | cs35l45_asp_tx_val), |
| 79 | }; | 204 | }; |
| 80 | 205 | ||
| 206 | static const char * const cs35l45_dsp_rx_txt[] = { | ||
| 207 | "Zero", "ASP_RX1", "ASP_RX2", | ||
| 208 | "VMON", "IMON", "ERR_VOL", | ||
| 209 | "CLASSH_TGT", "VDD_BATTMON", | ||
| 210 | "VDD_BSTMON", "TEMPMON", | ||
| 211 | }; | ||
| 212 | |||
| 213 | static const unsigned int cs35l45_dsp_rx_val[] = { | ||
| 214 | CS35L45_PCM_SRC_ZERO, CS35L45_PCM_SRC_ASP_RX1, CS35L45_PCM_SRC_ASP_RX2, | ||
| 215 | CS35L45_PCM_SRC_VMON, CS35L45_PCM_SRC_IMON, CS35L45_PCM_SRC_ERR_VOL, | ||
| 216 | CS35L45_PCM_SRC_CLASSH_TGT, CS35L45_PCM_SRC_VDD_BATTMON, | ||
| 217 | CS35L45_PCM_SRC_VDD_BSTMON, CS35L45_PCM_SRC_TEMPMON, | ||
| 218 | }; | ||
| 219 | |||
| 220 | static const struct soc_enum cs35l45_dsp_rx_enums[] = { | ||
| 221 | SOC_VALUE_ENUM_SINGLE(CS35L45_DSP1RX1_INPUT, 0, CS35L45_PCM_SRC_MASK, | ||
| 222 | ARRAY_SIZE(cs35l45_dsp_rx_txt), cs35l45_dsp_rx_txt, | ||
| 223 | cs35l45_dsp_rx_val), | ||
| 224 | SOC_VALUE_ENUM_SINGLE(CS35L45_DSP1RX2_INPUT, 0, CS35L45_PCM_SRC_MASK, | ||
| 225 | ARRAY_SIZE(cs35l45_dsp_rx_txt), cs35l45_dsp_rx_txt, | ||
| 226 | cs35l45_dsp_rx_val), | ||
| 227 | SOC_VALUE_ENUM_SINGLE(CS35L45_DSP1RX3_INPUT, 0, CS35L45_PCM_SRC_MASK, | ||
| 228 | ARRAY_SIZE(cs35l45_dsp_rx_txt), cs35l45_dsp_rx_txt, | ||
| 229 | cs35l45_dsp_rx_val), | ||
| 230 | SOC_VALUE_ENUM_SINGLE(CS35L45_DSP1RX4_INPUT, 0, CS35L45_PCM_SRC_MASK, | ||
| 231 | ARRAY_SIZE(cs35l45_dsp_rx_txt), cs35l45_dsp_rx_txt, | ||
| 232 | cs35l45_dsp_rx_val), | ||
| 233 | SOC_VALUE_ENUM_SINGLE(CS35L45_DSP1RX5_INPUT, 0, CS35L45_PCM_SRC_MASK, | ||
| 234 | ARRAY_SIZE(cs35l45_dsp_rx_txt), cs35l45_dsp_rx_txt, | ||
| 235 | cs35l45_dsp_rx_val), | ||
| 236 | SOC_VALUE_ENUM_SINGLE(CS35L45_DSP1RX6_INPUT, 0, CS35L45_PCM_SRC_MASK, | ||
| 237 | ARRAY_SIZE(cs35l45_dsp_rx_txt), cs35l45_dsp_rx_txt, | ||
| 238 | cs35l45_dsp_rx_val), | ||
| 239 | SOC_VALUE_ENUM_SINGLE(CS35L45_DSP1RX7_INPUT, 0, CS35L45_PCM_SRC_MASK, | ||
| 240 | ARRAY_SIZE(cs35l45_dsp_rx_txt), cs35l45_dsp_rx_txt, | ||
| 241 | cs35l45_dsp_rx_val), | ||
| 242 | SOC_VALUE_ENUM_SINGLE(CS35L45_DSP1RX8_INPUT, 0, CS35L45_PCM_SRC_MASK, | ||
| 243 | ARRAY_SIZE(cs35l45_dsp_rx_txt), cs35l45_dsp_rx_txt, | ||
| 244 | cs35l45_dsp_rx_val), | ||
| 245 | }; | ||
| 246 | |||
| 81 | static const char * const cs35l45_dac_txt[] = { | 247 | static const char * const cs35l45_dac_txt[] = { |
| 82 | "Zero", "ASP_RX1", "ASP_RX2" | 248 | "Zero", "ASP_RX1", "ASP_RX2", "DSP_TX1", "DSP_TX2" |
| 83 | }; | 249 | }; |
| 84 | 250 | ||
| 85 | static const unsigned int cs35l45_dac_val[] = { | 251 | static const unsigned int cs35l45_dac_val[] = { |
| 86 | CS35L45_PCM_SRC_ZERO, CS35L45_PCM_SRC_ASP_RX1, CS35L45_PCM_SRC_ASP_RX2 | 252 | CS35L45_PCM_SRC_ZERO, CS35L45_PCM_SRC_ASP_RX1, CS35L45_PCM_SRC_ASP_RX2, |
| 253 | CS35L45_PCM_SRC_DSP_TX1, CS35L45_PCM_SRC_DSP_TX2 | ||
| 87 | }; | 254 | }; |
| 88 | 255 | ||
| 89 | static const struct soc_enum cs35l45_dacpcm_enums[] = { | 256 | static const struct soc_enum cs35l45_dacpcm_enums[] = { |
| @@ -100,11 +267,29 @@ static const struct snd_kcontrol_new cs35l45_asp_muxes[] = { · 10 unmodified lines | |||
| 100 | SOC_DAPM_ENUM("ASP_TX5 Source", cs35l45_asp_tx_enums[4]), | 267 | SOC_DAPM_ENUM("ASP_TX5 Source", cs35l45_asp_tx_enums[4]), |
| 101 | }; | 268 | }; |
| 102 | 269 | ||
| 270 | static const struct snd_kcontrol_new cs35l45_dsp_muxes[] = { | ||
| 271 | SOC_DAPM_ENUM("DSP_RX1 Source", cs35l45_dsp_rx_enums[0]), | ||
| 272 | SOC_DAPM_ENUM("DSP_RX2 Source", cs35l45_dsp_rx_enums[1]), | ||
| 273 | SOC_DAPM_ENUM("DSP_RX3 Source", cs35l45_dsp_rx_enums[2]), | ||
| 274 | SOC_DAPM_ENUM("DSP_RX4 Source", cs35l45_dsp_rx_enums[3]), | ||
| 275 | SOC_DAPM_ENUM("DSP_RX5 Source", cs35l45_dsp_rx_enums[4]), | ||
| 276 | SOC_DAPM_ENUM("DSP_RX6 Source", cs35l45_dsp_rx_enums[5]), | ||
| 277 | SOC_DAPM_ENUM("DSP_RX7 Source", cs35l45_dsp_rx_enums[6]), | ||
| 278 | SOC_DAPM_ENUM("DSP_RX8 Source", cs35l45_dsp_rx_enums[7]), | ||
| 279 | }; | ||
| 280 | |||
| 103 | static const struct snd_kcontrol_new cs35l45_dac_muxes[] = { | 281 | static const struct snd_kcontrol_new cs35l45_dac_muxes[] = { |
| 104 | SOC_DAPM_ENUM("DACPCM1 Source", cs35l45_dacpcm_enums[0]), | 282 | SOC_DAPM_ENUM("DACPCM1 Source", cs35l45_dacpcm_enums[0]), |
| 105 | }; | 283 | }; |
| 106 | 284 | ||
| 107 | static const struct snd_soc_dapm_widget cs35l45_dapm_widgets[] = { | 285 | static const struct snd_soc_dapm_widget cs35l45_dapm_widgets[] = { |
| 286 | SND_SOC_DAPM_SPK("DSP1 Preload", NULL), | ||
| 287 | SND_SOC_DAPM_SUPPLY_S("DSP1 Preloader", 100, SND_SOC_NOPM, 0, 0, | ||
| 288 | cs35l45_dsp_preload_ev, | ||
| 289 | SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD), | ||
| 290 | SND_SOC_DAPM_OUT_DRV_E("DSP1", SND_SOC_NOPM, 0, 0, NULL, 0, | ||
| 291 | cs35l45_dsp_audio_ev, | ||
| 292 | SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD), | ||
| 108 | SND_SOC_DAPM_SUPPLY("GLOBAL_EN", SND_SOC_NOPM, 0, 0, | 293 | SND_SOC_DAPM_SUPPLY("GLOBAL_EN", SND_SOC_NOPM, 0, 0, |
| 109 | cs35l45_global_en_ev, | 294 | cs35l45_global_en_ev, |
| 110 | SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD), | 295 | SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD), |
| @@ -139,6 +324,15 @@ static const struct snd_soc_dapm_widget cs35l45_dapm_widgets[] = { · 28 unmodified lines | |||
| 139 | SND_SOC_DAPM_MUX("ASP_TX4 Source", SND_SOC_NOPM, 0, 0, &cs35l45_asp_muxes[3]), | 324 | SND_SOC_DAPM_MUX("ASP_TX4 Source", SND_SOC_NOPM, 0, 0, &cs35l45_asp_muxes[3]), |
| 140 | SND_SOC_DAPM_MUX("ASP_TX5 Source", SND_SOC_NOPM, 0, 0, &cs35l45_asp_muxes[4]), | 325 | SND_SOC_DAPM_MUX("ASP_TX5 Source", SND_SOC_NOPM, 0, 0, &cs35l45_asp_muxes[4]), |
| 141 | 326 | ||
| 327 | SND_SOC_DAPM_MUX("DSP_RX1 Source", SND_SOC_NOPM, 0, 0, &cs35l45_dsp_muxes[0]), | ||
| 328 | SND_SOC_DAPM_MUX("DSP_RX2 Source", SND_SOC_NOPM, 0, 0, &cs35l45_dsp_muxes[1]), | ||
| 329 | SND_SOC_DAPM_MUX("DSP_RX3 Source", SND_SOC_NOPM, 0, 0, &cs35l45_dsp_muxes[2]), | ||
| 330 | SND_SOC_DAPM_MUX("DSP_RX4 Source", SND_SOC_NOPM, 0, 0, &cs35l45_dsp_muxes[3]), | ||
| 331 | SND_SOC_DAPM_MUX("DSP_RX5 Source", SND_SOC_NOPM, 0, 0, &cs35l45_dsp_muxes[4]), | ||
| 332 | SND_SOC_DAPM_MUX("DSP_RX6 Source", SND_SOC_NOPM, 0, 0, &cs35l45_dsp_muxes[5]), | ||
| 333 | SND_SOC_DAPM_MUX("DSP_RX7 Source", SND_SOC_NOPM, 0, 0, &cs35l45_dsp_muxes[6]), | ||
| 334 | SND_SOC_DAPM_MUX("DSP_RX8 Source", SND_SOC_NOPM, 0, 0, &cs35l45_dsp_muxes[7]), | ||
| 335 | |||
| 142 | SND_SOC_DAPM_MUX("DACPCM1 Source", SND_SOC_NOPM, 0, 0, &cs35l45_dac_muxes[0]), | 336 | SND_SOC_DAPM_MUX("DACPCM1 Source", SND_SOC_NOPM, 0, 0, &cs35l45_dac_muxes[0]), |
| 143 | 337 | ||
| 144 | SND_SOC_DAPM_OUT_DRV("AMP", SND_SOC_NOPM, 0, 0, NULL, 0), | 338 | SND_SOC_DAPM_OUT_DRV("AMP", SND_SOC_NOPM, 0, 0, NULL, 0), |
| @@ -149,6 +343,8 @@ static const struct snd_soc_dapm_widget cs35l45_dapm_widgets[] = { · 4 unmodified lines | |||
| 149 | #define CS35L45_ASP_MUX_ROUTE(name) \ | 343 | #define CS35L45_ASP_MUX_ROUTE(name) \ |
| 150 | { name" Source", "ASP_RX1", "ASP_RX1" }, \ | 344 | { name" Source", "ASP_RX1", "ASP_RX1" }, \ |
| 151 | { name" Source", "ASP_RX2", "ASP_RX2" }, \ | 345 | { name" Source", "ASP_RX2", "ASP_RX2" }, \ |
| 346 | { name" Source", "DSP_TX1", "DSP1" }, \ | ||
| 347 | { name" Source", "DSP_TX2", "DSP1" }, \ | ||
| 152 | { name" Source", "VMON", "VMON" }, \ | 348 | { name" Source", "VMON", "VMON" }, \ |
| 153 | { name" Source", "IMON", "IMON" }, \ | 349 | { name" Source", "IMON", "IMON" }, \ |
| 154 | { name" Source", "ERR_VOL", "ERR_VOL" }, \ | 350 | { name" Source", "ERR_VOL", "ERR_VOL" }, \ |
| @@ -157,10 +353,16 @@ static const struct snd_soc_dapm_widget cs35l45_dapm_widgets[] = { · 2 unmodified lines | |||
| 157 | { name" Source", "Interpolator", "AMP_INTP" }, \ | 353 | { name" Source", "Interpolator", "AMP_INTP" }, \ |
| 158 | { name" Source", "IL_TARGET", "IL_TARGET" } | 354 | { name" Source", "IL_TARGET", "IL_TARGET" } |
| 159 | 355 | ||
| 160 | #define CS35L45_DAC_MUX_ROUTE(name) \ | 356 | #define CS35L45_DSP_MUX_ROUTE(name) \ |
| 161 | { name" Source", "ASP_RX1", "ASP_RX1" }, \ | 357 | { name" Source", "ASP_RX1", "ASP_RX1" }, \ |
| 162 | { name" Source", "ASP_RX2", "ASP_RX2" } | 358 | { name" Source", "ASP_RX2", "ASP_RX2" } |
| 163 | 359 | ||
| 360 | #define CS35L45_DAC_MUX_ROUTE(name) \ | ||
| 361 | { name" Source", "ASP_RX1", "ASP_RX1" }, \ | ||
| 362 | { name" Source", "ASP_RX2", "ASP_RX2" }, \ | ||
| 363 | { name" Source", "DSP_TX1", "DSP1" }, \ | ||
| 364 | { name" Source", "DSP_TX2", "DSP1" } | ||
| 365 | |||
| 164 | static const struct snd_soc_dapm_route cs35l45_dapm_routes[] = { | 366 | static const struct snd_soc_dapm_route cs35l45_dapm_routes[] = { |
| 165 | /* Feedback */ | 367 | /* Feedback */ |
| 166 | { "VMON", NULL, "VMON_SRC" }, | 368 | { "VMON", NULL, "VMON_SRC" }, |
| @@ -204,6 +406,27 @@ static const struct snd_soc_dapm_route cs35l45_dapm_routes[] = { · 37 unmodified lines | |||
| 204 | { "AMP", NULL, "DACPCM1 Source"}, | 406 | { "AMP", NULL, "DACPCM1 Source"}, |
| 205 | { "AMP", NULL, "GLOBAL_EN"}, | 407 | { "AMP", NULL, "GLOBAL_EN"}, |
| 206 | 408 | ||
| 409 | CS35L45_DSP_MUX_ROUTE("DSP_RX1"), | ||
| 410 | CS35L45_DSP_MUX_ROUTE("DSP_RX2"), | ||
| 411 | CS35L45_DSP_MUX_ROUTE("DSP_RX3"), | ||
| 412 | CS35L45_DSP_MUX_ROUTE("DSP_RX4"), | ||
| 413 | CS35L45_DSP_MUX_ROUTE("DSP_RX5"), | ||
| 414 | CS35L45_DSP_MUX_ROUTE("DSP_RX6"), | ||
| 415 | CS35L45_DSP_MUX_ROUTE("DSP_RX7"), | ||
| 416 | CS35L45_DSP_MUX_ROUTE("DSP_RX8"), | ||
| 417 | |||
| 418 | {"DSP1", NULL, "DSP_RX1 Source"}, | ||
| 419 | {"DSP1", NULL, "DSP_RX2 Source"}, | ||
| 420 | {"DSP1", NULL, "DSP_RX3 Source"}, | ||
| 421 | {"DSP1", NULL, "DSP_RX4 Source"}, | ||
| 422 | {"DSP1", NULL, "DSP_RX5 Source"}, | ||
| 423 | {"DSP1", NULL, "DSP_RX6 Source"}, | ||
| 424 | {"DSP1", NULL, "DSP_RX7 Source"}, | ||
| 425 | {"DSP1", NULL, "DSP_RX8 Source"}, | ||
| 426 | |||
| 427 | {"DSP1 Preload", NULL, "DSP1 Preloader"}, | ||
| 428 | {"DSP1", NULL, "DSP1 Preloader"}, | ||
| 429 | |||
| 207 | CS35L45_DAC_MUX_ROUTE("DACPCM1"), | 430 | CS35L45_DAC_MUX_ROUTE("DACPCM1"), |
| 208 | 431 | ||
| 209 | { "SPK", NULL, "AMP"}, | 432 | { "SPK", NULL, "AMP"}, |
| @@ -219,6 +442,8 @@ static const struct snd_kcontrol_new cs35l45_controls[] = { · 9 unmodified lines | |||
| 219 | -409, 48, | 442 | -409, 48, |
| 220 | (CS35L45_AMP_VOL_PCM_WIDTH - 1) - 1, | 443 | (CS35L45_AMP_VOL_PCM_WIDTH - 1) - 1, |
| 221 | 0, cs35l45_dig_pcm_vol_tlv), | 444 | 0, cs35l45_dig_pcm_vol_tlv), |
| 445 | WM_ADSP2_PRELOAD_SWITCH("DSP1", 1), | ||
| 446 | WM_ADSP_FW_CONTROL("DSP1", 0), | ||
| 222 | }; | 447 | }; |
| 223 | 448 | ||
| 224 | static int cs35l45_set_pll(struct cs35l45_private *cs35l45, unsigned int freq) | 449 | static int cs35l45_set_pll(struct cs35l45_private *cs35l45, unsigned int freq) |
| @@ -489,7 +714,24 @@ static struct snd_soc_dai_driver cs35l45_dai[] = { · 264 unmodified lines | |||
| 489 | }, | 714 | }, |
| 490 | }; | 715 | }; |
| 491 | 716 | ||
| 717 | static int cs35l45_component_probe(struct snd_soc_component *component) | ||
| 718 | { | ||
| 719 | struct cs35l45_private *cs35l45 = snd_soc_component_get_drvdata(component); | ||
| 720 | |||
| 721 | return wm_adsp2_component_probe(&cs35l45->dsp, component); | ||
| 722 | } | ||
| 723 | |||
| 724 | static void cs35l45_component_remove(struct snd_soc_component *component) | ||
| 725 | { | ||
| 726 | struct cs35l45_private *cs35l45 = snd_soc_component_get_drvdata(component); | ||
| 727 | |||
| 728 | wm_adsp2_component_remove(&cs35l45->dsp, component); | ||
| 729 | } | ||
| 730 | |||
| 492 | static const struct snd_soc_component_driver cs35l45_component = { | 731 | static const struct snd_soc_component_driver cs35l45_component = { |
| 732 | .probe = cs35l45_component_probe, | ||
| 733 | .remove = cs35l45_component_remove, | ||
| 734 | |||
| 493 | .dapm_widgets = cs35l45_dapm_widgets, | 735 | .dapm_widgets = cs35l45_dapm_widgets, |
| 494 | .num_dapm_widgets = ARRAY_SIZE(cs35l45_dapm_widgets), | 736 | .num_dapm_widgets = ARRAY_SIZE(cs35l45_dapm_widgets), |
| 495 | 737 | ||
| @@ -504,11 +746,81 @@ static const struct snd_soc_component_driver cs35l45_component = { · 8 unmodified lines | |||
| 504 | .endianness = 1, | 746 | .endianness = 1, |
| 505 | }; | 747 | }; |
| 506 | 748 | ||
| 749 | static void cs35l45_setup_hibernate(struct cs35l45_private *cs35l45) | ||
| 750 | { | ||
| 751 | unsigned int wksrc; | ||
| 752 | |||
| 753 | if (cs35l45->bus_type == CONTROL_BUS_I2C) | ||
| 754 | wksrc = CS35L45_WKSRC_I2C; | ||
| 755 | else | ||
| 756 | wksrc = CS35L45_WKSRC_SPI; | ||
| 757 | |||
| 758 | regmap_update_bits(cs35l45->regmap, CS35L45_WAKESRC_CTL, | ||
| 759 | CS35L45_WKSRC_EN_MASK, | ||
| 760 | wksrc << CS35L45_WKSRC_EN_SHIFT); | ||
| 761 | |||
| 762 | regmap_set_bits(cs35l45->regmap, CS35L45_WAKESRC_CTL, | ||
| 763 | CS35L45_UPDT_WKCTL_MASK); | ||
| 764 | |||
| 765 | regmap_update_bits(cs35l45->regmap, CS35L45_WKI2C_CTL, | ||
| 766 | CS35L45_WKI2C_ADDR_MASK, cs35l45->i2c_addr); | ||
| 767 | |||
| 768 | regmap_set_bits(cs35l45->regmap, CS35L45_WKI2C_CTL, | ||
| 769 | CS35L45_UPDT_WKI2C_MASK); | ||
| 770 | } | ||
| 771 | |||
| 772 | static int cs35l45_enter_hibernate(struct cs35l45_private *cs35l45) | ||
| 773 | { | ||
| 774 | dev_dbg(cs35l45->dev, "Enter hibernate\n"); | ||
| 775 | |||
| 776 | cs35l45_setup_hibernate(cs35l45); | ||
| 777 | |||
| 778 | // Don't wait for ACK since bus activity would wake the device | ||
| 779 | regmap_write(cs35l45->regmap, CS35L45_DSP_VIRT1_MBOX_1, CSPL_MBOX_CMD_HIBERNATE); | ||
| 780 | |||
| 781 | return 0; | ||
| 782 | } | ||
| 783 | |||
| 784 | static int cs35l45_exit_hibernate(struct cs35l45_private *cs35l45) | ||
| 785 | { | ||
| 786 | const int wake_retries = 20; | ||
| 787 | const int sleep_retries = 5; | ||
| 788 | int ret, i, j; | ||
| 789 | |||
| 790 | for (i = 0; i < sleep_retries; i++) { | ||
| 791 | dev_dbg(cs35l45->dev, "Exit hibernate\n"); | ||
| 792 | |||
| 793 | for (j = 0; j < wake_retries; j++) { | ||
| 794 | ret = cs35l45_set_cspl_mbox_cmd(cs35l45, cs35l45->regmap, | ||
| 795 | CSPL_MBOX_CMD_OUT_OF_HIBERNATE); | ||
| 796 | if (!ret) { | ||
| 797 | dev_dbg(cs35l45->dev, "Wake success at cycle: %d\n", j); | ||
| 798 | return 0; | ||
| 799 | } | ||
| 800 | usleep_range(100, 200); | ||
| 801 | } | ||
| 802 | |||
| 803 | dev_err(cs35l45->dev, "Wake failed, re-enter hibernate: %d\n", ret); | ||
| 804 | |||
| 805 | cs35l45_setup_hibernate(cs35l45); | ||
| 806 | } | ||
| 807 | |||
| 808 | dev_err(cs35l45->dev, "Timed out waking device\n"); | ||
| 809 | |||
| 810 | return -ETIMEDOUT; | ||
| 811 | } | ||
| 812 | |||
| 507 | static int __maybe_unused cs35l45_runtime_suspend(struct device *dev) | 813 | static int __maybe_unused cs35l45_runtime_suspend(struct device *dev) |
| 508 | { | 814 | { |
| 509 | struct cs35l45_private *cs35l45 = dev_get_drvdata(dev); | 815 | struct cs35l45_private *cs35l45 = dev_get_drvdata(dev); |
| 510 | 816 | ||
| 817 | if (!cs35l45->dsp.preloaded || !cs35l45->dsp.cs_dsp.running) | ||
| 818 | return 0; | ||
| 819 | |||
| 820 | cs35l45_enter_hibernate(cs35l45); | ||
| 821 | |||
| 511 | regcache_cache_only(cs35l45->regmap, true); | 822 | regcache_cache_only(cs35l45->regmap, true); |
| 823 | regcache_mark_dirty(cs35l45->regmap); | ||
| 512 | 824 | ||
| 513 | dev_dbg(cs35l45->dev, "Runtime suspended\n"); | 825 | dev_dbg(cs35l45->dev, "Runtime suspended\n"); |
| 514 | 826 | ||
| @@ -520,9 +832,17 @@ static int __maybe_unused cs35l45_runtime_resume(struct device *dev) · 5 unmodified lines | |||
| 520 | struct cs35l45_private *cs35l45 = dev_get_drvdata(dev); | 832 | struct cs35l45_private *cs35l45 = dev_get_drvdata(dev); |
| 521 | int ret; | 833 | int ret; |
| 522 | 834 | ||
| 835 | if (!cs35l45->dsp.preloaded || !cs35l45->dsp.cs_dsp.running) | ||
| 836 | return 0; | ||
| 837 | |||
| 523 | dev_dbg(cs35l45->dev, "Runtime resume\n"); | 838 | dev_dbg(cs35l45->dev, "Runtime resume\n"); |
| 524 | 839 | ||
| 525 | regcache_cache_only(cs35l45->regmap, false); | 840 | regcache_cache_only(cs35l45->regmap, false); |
| 841 | |||
| 842 | ret = cs35l45_exit_hibernate(cs35l45); | ||
| 843 | if (ret) | ||
| 844 | return ret; | ||
| 845 | |||
| 526 | ret = regcache_sync(cs35l45->regmap); | 846 | ret = regcache_sync(cs35l45->regmap); |
| 527 | if (ret != 0) | 847 | if (ret != 0) |
| 528 | dev_warn(cs35l45->dev, "regcache_sync failed: %d\n", ret); | 848 | dev_warn(cs35l45->dev, "regcache_sync failed: %d\n", ret); |
| @@ -536,7 +856,66 @@ static int __maybe_unused cs35l45_runtime_resume(struct device *dev) · 7 unmodified lines | |||
| 536 | 856 | ||
| 537 | static int cs35l45_apply_property_config(struct cs35l45_private *cs35l45) | 857 | static int cs35l45_apply_property_config(struct cs35l45_private *cs35l45) |
| 538 | { | 858 | { |
| 859 | struct device_node *node = cs35l45->dev->of_node; | ||
| 860 | unsigned int gpio_regs[] = {CS35L45_GPIO1_CTRL1, CS35L45_GPIO2_CTRL1, | ||
| 861 | CS35L45_GPIO3_CTRL1}; | ||
| 862 | unsigned int pad_regs[] = {CS35L45_SYNC_GPIO1, | ||
| 863 | CS35L45_INTB_GPIO2_MCLK_REF, CS35L45_GPIO3}; | ||
| 864 | struct device_node *child; | ||
| 539 | unsigned int val; | 865 | unsigned int val; |
| 866 | char of_name[32]; | ||
| 867 | int ret, i; | ||
| 868 | |||
| 869 | if (!node) | ||
| 870 | return 0; | ||
| 871 | |||
| 872 | for (i = 0; i < CS35L45_NUM_GPIOS; i++) { | ||
| 873 | sprintf(of_name, "cirrus,gpio-ctrl%d", i + 1); | ||
| 874 | child = of_get_child_by_name(node, of_name); | ||
| 875 | if (!child) | ||
| 876 | continue; | ||
| 877 | |||
| 878 | ret = of_property_read_u32(child, "gpio-dir", &val); | ||
| 879 | if (!ret) | ||
| 880 | regmap_update_bits(cs35l45->regmap, gpio_regs[i], | ||
| 881 | CS35L45_GPIO_DIR_MASK, | ||
| 882 | val << CS35L45_GPIO_DIR_SHIFT); | ||
| 883 | |||
| 884 | ret = of_property_read_u32(child, "gpio-lvl", &val); | ||
| 885 | if (!ret) | ||
| 886 | regmap_update_bits(cs35l45->regmap, gpio_regs[i], | ||
| 887 | CS35L45_GPIO_LVL_MASK, | ||
| 888 | val << CS35L45_GPIO_LVL_SHIFT); | ||
| 889 | |||
| 890 | ret = of_property_read_u32(child, "gpio-op-cfg", &val); | ||
| 891 | if (!ret) | ||
| 892 | regmap_update_bits(cs35l45->regmap, gpio_regs[i], | ||
| 893 | CS35L45_GPIO_OP_CFG_MASK, | ||
| 894 | val << CS35L45_GPIO_OP_CFG_SHIFT); | ||
| 895 | |||
| 896 | ret = of_property_read_u32(child, "gpio-pol", &val); | ||
| 897 | if (!ret) | ||
| 898 | regmap_update_bits(cs35l45->regmap, gpio_regs[i], | ||
| 899 | CS35L45_GPIO_POL_MASK, | ||
| 900 | val << CS35L45_GPIO_POL_SHIFT); | ||
| 901 | |||
| 902 | ret = of_property_read_u32(child, "gpio-ctrl", &val); | ||
| 903 | if (!ret) | ||
| 904 | regmap_update_bits(cs35l45->regmap, pad_regs[i], | ||
| 905 | CS35L45_GPIO_CTRL_MASK, | ||
| 906 | val << CS35L45_GPIO_CTRL_SHIFT); | ||
| 907 | |||
| 908 | ret = of_property_read_u32(child, "gpio-invert", &val); | ||
| 909 | if (!ret) { | ||
| 910 | regmap_update_bits(cs35l45->regmap, pad_regs[i], | ||
| 911 | CS35L45_GPIO_INVERT_MASK, | ||
| 912 | val << CS35L45_GPIO_INVERT_SHIFT); | ||
| 913 | if (i == 1) | ||
| 914 | cs35l45->irq_invert = val; | ||
| 915 | } | ||
| 916 | |||
| 917 | of_node_put(child); | ||
| 918 | } | ||
| 540 | 919 | ||
| 541 | if (device_property_read_u32(cs35l45->dev, | 920 | if (device_property_read_u32(cs35l45->dev, |
| 542 | "cirrus,asp-sdout-hiz-ctrl", &val) == 0) { | 921 | "cirrus,asp-sdout-hiz-ctrl", &val) == 0) { |
| @@ -548,6 +927,134 @@ static int cs35l45_apply_property_config(struct cs35l45_private *cs35l45) · 5 unmodified lines | |||
| 548 | return 0; | 927 | return 0; |
| 549 | } | 928 | } |
| 550 | 929 | ||
| 930 | static int cs35l45_dsp_virt2_mbox3_irq_handle(struct cs35l45_private *cs35l45, | ||
| 931 | const unsigned int cmd, | ||
| 932 | unsigned int data) | ||
| 933 | { | ||
| 934 | static char *speak_status = "Unknown"; | ||
| 935 | |||
| 936 | switch (cmd) { | ||
| 937 | case EVENT_SPEAKER_STATUS: | ||
| 938 | switch (data) { | ||
| 939 | case 1: | ||
| 940 | speak_status = "All Clear"; | ||
| 941 | break; | ||
| 942 | case 2: | ||
| 943 | speak_status = "Open Circuit"; | ||
| 944 | break; | ||
| 945 | case 4: | ||
| 946 | speak_status = "Short Circuit"; | ||
| 947 | break; | ||
| 948 | } | ||
| 949 | |||
| 950 | dev_info(cs35l45->dev, "MBOX event (SPEAKER_STATUS): %s\n", | ||
| 951 | speak_status); | ||
| 952 | break; | ||
| 953 | case EVENT_BOOT_DONE: | ||
| 954 | dev_dbg(cs35l45->dev, "MBOX event (BOOT_DONE)\n"); | ||
| 955 | break; | ||
| 956 | default: | ||
| 957 | dev_err(cs35l45->dev, "MBOX event not supported %u\n", cmd); | ||
| 958 | return -EINVAL; | ||
| 959 | } | ||
| 960 | |||
| 961 | return 0; | ||
| 962 | } | ||
| 963 | |||
| 964 | static irqreturn_t cs35l45_dsp_virt2_mbox_cb(int irq, void *data) | ||
| 965 | { | ||
| 966 | struct cs35l45_private *cs35l45 = data; | ||
| 967 | unsigned int mbox_val; | ||
| 968 | int ret = 0; | ||
| 969 | |||
| 970 | ret = regmap_read(cs35l45->regmap, CS35L45_DSP_VIRT2_MBOX_3, &mbox_val); | ||
| 971 | if (!ret && mbox_val) | ||
| 972 | ret = cs35l45_dsp_virt2_mbox3_irq_handle(cs35l45, mbox_val & CS35L45_MBOX3_CMD_MASK, | ||
| 973 | (mbox_val & CS35L45_MBOX3_DATA_MASK) >> CS35L45_MBOX3_DATA_SHIFT); | ||
| 974 | |||
| 975 | /* Handle DSP trace log IRQ */ | ||
| 976 | ret = regmap_read(cs35l45->regmap, CS35L45_DSP_VIRT2_MBOX_4, &mbox_val); | ||
| 977 | if (!ret && mbox_val != 0) { | ||
| 978 | dev_err(cs35l45->dev, "Spurious DSP MBOX4 IRQ\n"); | ||
| 979 | } | ||
| 980 | |||
| 981 | return IRQ_RETVAL(ret); | ||
| 982 | } | ||
| 983 | |||
| 984 | static irqreturn_t cs35l45_pll_unlock(int irq, void *data) | ||
| 985 | { | ||
| 986 | struct cs35l45_private *cs35l45 = data; | ||
| 987 | |||
| 988 | dev_dbg(cs35l45->dev, "PLL unlock detected!"); | ||
| 989 | |||
| 990 | return IRQ_HANDLED; | ||
| 991 | } | ||
| 992 | |||
| 993 | static irqreturn_t cs35l45_pll_lock(int irq, void *data) | ||
| 994 | { | ||
| 995 | struct cs35l45_private *cs35l45 = data; | ||
| 996 | |||
| 997 | dev_dbg(cs35l45->dev, "PLL lock detected!"); | ||
| 998 | |||
| 999 | return IRQ_HANDLED; | ||
| 1000 | } | ||
| 1001 | |||
| 1002 | static irqreturn_t cs35l45_spk_safe_err(int irq, void *data); | ||
| 1003 | |||
| 1004 | static const struct cs35l45_irq cs35l45_irqs[] = { | ||
| 1005 | CS35L45_IRQ(AMP_SHORT_ERR, "Amplifier short error", cs35l45_spk_safe_err), | ||
| 1006 | CS35L45_IRQ(UVLO_VDDBATT_ERR, "VDDBATT undervoltage error", cs35l45_spk_safe_err), | ||
| 1007 | CS35L45_IRQ(BST_SHORT_ERR, "Boost inductor error", cs35l45_spk_safe_err), | ||
| 1008 | CS35L45_IRQ(BST_UVP_ERR, "Boost undervoltage error", cs35l45_spk_safe_err), | ||
| 1009 | CS35L45_IRQ(TEMP_ERR, "Overtemperature error", cs35l45_spk_safe_err), | ||
| 1010 | CS35L45_IRQ(AMP_CAL_ERR, "Amplifier calibration error", cs35l45_spk_safe_err), | ||
| 1011 | CS35L45_IRQ(UVLO_VDDLV_ERR, "LV threshold detector error", cs35l45_spk_safe_err), | ||
| 1012 | CS35L45_IRQ(GLOBAL_ERROR, "Global error", cs35l45_spk_safe_err), | ||
| 1013 | CS35L45_IRQ(DSP_WDT_EXPIRE, "DSP Watchdog Timer", cs35l45_spk_safe_err), | ||
| 1014 | CS35L45_IRQ(PLL_UNLOCK_FLAG_RISE, "PLL unlock", cs35l45_pll_unlock), | ||
| 1015 | CS35L45_IRQ(PLL_LOCK_FLAG, "PLL lock", cs35l45_pll_lock), | ||
| 1016 | CS35L45_IRQ(DSP_VIRT2_MBOX, "DSP virtual MBOX 2 write flag", cs35l45_dsp_virt2_mbox_cb), | ||
| 1017 | }; | ||
| 1018 | |||
| 1019 | static irqreturn_t cs35l45_spk_safe_err(int irq, void *data) | ||
| 1020 | { | ||
| 1021 | struct cs35l45_private *cs35l45 = data; | ||
| 1022 | int i; | ||
| 1023 | |||
| 1024 | i = irq - regmap_irq_get_virq(cs35l45->irq_data, 0); | ||
| 1025 | |||
| 1026 | dev_err(cs35l45->dev, "%s condition detected!\n", cs35l45_irqs[i].name); | ||
| 1027 | |||
| 1028 | return IRQ_HANDLED; | ||
| 1029 | } | ||
| 1030 | |||
| 1031 | static const struct regmap_irq cs35l45_reg_irqs[] = { | ||
| 1032 | CS35L45_REG_IRQ(IRQ1_EINT_1, AMP_SHORT_ERR), | ||
| 1033 | CS35L45_REG_IRQ(IRQ1_EINT_1, UVLO_VDDBATT_ERR), | ||
| 1034 | CS35L45_REG_IRQ(IRQ1_EINT_1, BST_SHORT_ERR), | ||
| 1035 | CS35L45_REG_IRQ(IRQ1_EINT_1, BST_UVP_ERR), | ||
| 1036 | CS35L45_REG_IRQ(IRQ1_EINT_1, TEMP_ERR), | ||
| 1037 | CS35L45_REG_IRQ(IRQ1_EINT_3, AMP_CAL_ERR), | ||
| 1038 | CS35L45_REG_IRQ(IRQ1_EINT_18, UVLO_VDDLV_ERR), | ||
| 1039 | CS35L45_REG_IRQ(IRQ1_EINT_18, GLOBAL_ERROR), | ||
| 1040 | CS35L45_REG_IRQ(IRQ1_EINT_2, DSP_WDT_EXPIRE), | ||
| 1041 | CS35L45_REG_IRQ(IRQ1_EINT_3, PLL_UNLOCK_FLAG_RISE), | ||
| 1042 | CS35L45_REG_IRQ(IRQ1_EINT_3, PLL_LOCK_FLAG), | ||
| 1043 | CS35L45_REG_IRQ(IRQ1_EINT_2, DSP_VIRT2_MBOX), | ||
| 1044 | }; | ||
| 1045 | |||
| 1046 | static const struct regmap_irq_chip cs35l45_regmap_irq_chip = { | ||
| 1047 | .name = "cs35l45 IRQ1 Controller", | ||
| 1048 | .main_status = CS35L45_IRQ1_STATUS, | ||
| 1049 | .status_base = CS35L45_IRQ1_EINT_1, | ||
| 1050 | .mask_base = CS35L45_IRQ1_MASK_1, | ||
| 1051 | .ack_base = CS35L45_IRQ1_EINT_1, | ||
| 1052 | .num_regs = 18, | ||
| 1053 | .irqs = cs35l45_reg_irqs, | ||
| 1054 | .num_irqs = ARRAY_SIZE(cs35l45_reg_irqs), | ||
| 1055 | .runtime_pm = true, | ||
| 1056 | }; | ||
| 1057 | |||
| 551 | static int cs35l45_initialize(struct cs35l45_private *cs35l45) | 1058 | static int cs35l45_initialize(struct cs35l45_private *cs35l45) |
| 552 | { | 1059 | { |
| 553 | struct device *dev = cs35l45->dev; | 1060 | struct device *dev = cs35l45->dev; |
| @@ -593,18 +1100,68 @@ static int cs35l45_initialize(struct cs35l45_private *cs35l45) · 39 unmodified lines | |||
| 593 | if (ret < 0) | 1100 | if (ret < 0) |
| 594 | return ret; | 1101 | return ret; |
| 595 | 1102 | ||
| 596 | pm_runtime_set_autosuspend_delay(cs35l45->dev, 3000); | ||
| 597 | pm_runtime_use_autosuspend(cs35l45->dev); | ||
| 598 | pm_runtime_set_active(cs35l45->dev); | ||
| 599 | pm_runtime_enable(cs35l45->dev); | ||
| 600 | |||
| 601 | return 0; | 1103 | return 0; |
| 602 | } | 1104 | } |
| 603 | 1105 | ||
| 1106 | static const struct reg_sequence cs35l45_fs_errata_patch[] = { | ||
| 1107 | {0x02B80080, 0x00000001}, | ||
| 1108 | {0x02B80088, 0x00000001}, | ||
| 1109 | {0x02B80090, 0x00000001}, | ||
| 1110 | {0x02B80098, 0x00000001}, | ||
| 1111 | {0x02B800A0, 0x00000001}, | ||
| 1112 | {0x02B800A8, 0x00000001}, | ||
| 1113 | {0x02B800B0, 0x00000001}, | ||
| 1114 | {0x02B800B8, 0x00000001}, | ||
| 1115 | {0x02B80280, 0x00000001}, | ||
| 1116 | {0x02B80288, 0x00000001}, | ||
| 1117 | {0x02B80290, 0x00000001}, | ||
| 1118 | {0x02B80298, 0x00000001}, | ||
| 1119 | {0x02B802A0, 0x00000001}, | ||
| 1120 | {0x02B802A8, 0x00000001}, | ||
| 1121 | {0x02B802B0, 0x00000001}, | ||
| 1122 | {0x02B802B8, 0x00000001}, | ||
| 1123 | }; | ||
| 1124 | |||
| 1125 | static const struct cs_dsp_region cs35l45_dsp1_regions[] = { | ||
| 1126 | { .type = WMFW_HALO_PM_PACKED, .base = CS35L45_DSP1_PMEM_0 }, | ||
| 1127 | { .type = WMFW_HALO_XM_PACKED, .base = CS35L45_DSP1_XMEM_PACK_0 }, | ||
| 1128 | { .type = WMFW_HALO_YM_PACKED, .base = CS35L45_DSP1_YMEM_PACK_0 }, | ||
| 1129 | {. type = WMFW_ADSP2_XM, .base = CS35L45_DSP1_XMEM_UNPACK24_0}, | ||
| 1130 | {. type = WMFW_ADSP2_YM, .base = CS35L45_DSP1_YMEM_UNPACK24_0}, | ||
| 1131 | }; | ||
| 1132 | |||
| 1133 | static int cs35l45_dsp_init(struct cs35l45_private *cs35l45) | ||
| 1134 | { | ||
| 1135 | struct wm_adsp *dsp = &cs35l45->dsp; | ||
| 1136 | int ret; | ||
| 1137 | |||
| 1138 | dsp->part = "cs35l45"; | ||
| 1139 | dsp->fw = 9; /* 9 is WM_ADSP_FW_SPK_PROT in wm_adsp.c */ | ||
| 1140 | dsp->toggle_preload = true; | ||
| 1141 | dsp->cs_dsp.num = 1; | ||
| 1142 | dsp->cs_dsp.type = WMFW_HALO; | ||
| 1143 | dsp->cs_dsp.rev = 0; | ||
| 1144 | dsp->cs_dsp.dev = cs35l45->dev; | ||
| 1145 | dsp->cs_dsp.regmap = cs35l45->regmap; | ||
| 1146 | dsp->cs_dsp.base = CS35L45_DSP1_CLOCK_FREQ; | ||
| 1147 | dsp->cs_dsp.base_sysinfo = CS35L45_DSP1_SYS_ID; | ||
| 1148 | dsp->cs_dsp.mem = cs35l45_dsp1_regions; | ||
| 1149 | dsp->cs_dsp.num_mems = ARRAY_SIZE(cs35l45_dsp1_regions); | ||
| 1150 | dsp->cs_dsp.lock_regions = 0xFFFFFFFF; | ||
| 1151 | |||
| 1152 | ret = wm_halo_init(dsp); | ||
| 1153 | |||
| 1154 | regmap_multi_reg_write(cs35l45->regmap, cs35l45_fs_errata_patch, | ||
| 1155 | ARRAY_SIZE(cs35l45_fs_errata_patch)); | ||
| 1156 | |||
| 1157 | return ret; | ||
| 1158 | } | ||
| 1159 | |||
| 604 | int cs35l45_probe(struct cs35l45_private *cs35l45) | 1160 | int cs35l45_probe(struct cs35l45_private *cs35l45) |
| 605 | { | 1161 | { |
| 606 | struct device *dev = cs35l45->dev; | 1162 | struct device *dev = cs35l45->dev; |
| 607 | int ret; | 1163 | unsigned long irq_pol = IRQF_ONESHOT | IRQF_SHARED; |
| 1164 | int ret, i, irq; | ||
| 608 | 1165 | ||
| 609 | cs35l45->vdd_batt = devm_regulator_get(dev, "vdd-batt"); | 1166 | cs35l45->vdd_batt = devm_regulator_get(dev, "vdd-batt"); |
| 610 | if (IS_ERR(cs35l45->vdd_batt)) | 1167 | if (IS_ERR(cs35l45->vdd_batt)) |
| @@ -649,14 +1206,63 @@ int cs35l45_probe(struct cs35l45_private *cs35l45) · 38 unmodified lines | |||
| 649 | if (ret < 0) | 1206 | if (ret < 0) |
| 650 | goto err_reset; | 1207 | goto err_reset; |
| 651 | 1208 | ||
| 1209 | ret = cs35l45_dsp_init(cs35l45); | ||
| 1210 | if (ret < 0) | ||
| 1211 | goto err_reset; | ||
| 1212 | |||
| 1213 | pm_runtime_set_autosuspend_delay(cs35l45->dev, 3000); | ||
| 1214 | pm_runtime_use_autosuspend(cs35l45->dev); | ||
| 1215 | pm_runtime_mark_last_busy(cs35l45->dev); | ||
| 1216 | pm_runtime_set_active(cs35l45->dev); | ||
| 1217 | pm_runtime_get_noresume(cs35l45->dev); | ||
| 1218 | pm_runtime_enable(cs35l45->dev); | ||
| 1219 | |||
| 1220 | if (cs35l45->irq) { | ||
| 1221 | if (cs35l45->irq_invert) | ||
| 1222 | irq_pol |= IRQF_TRIGGER_HIGH; | ||
| 1223 | else | ||
| 1224 | irq_pol |= IRQF_TRIGGER_LOW; | ||
| 1225 | |||
| 1226 | ret = devm_regmap_add_irq_chip(dev, cs35l45->regmap, cs35l45->irq, irq_pol, 0, | ||
| 1227 | &cs35l45_regmap_irq_chip, &cs35l45->irq_data); | ||
| 1228 | if (ret) { | ||
| 1229 | dev_err(dev, "Failed to register IRQ chip: %d\n", ret); | ||
| 1230 | goto err_dsp; | ||
| 1231 | } | ||
| 1232 | |||
| 1233 | for (i = 0; i < ARRAY_SIZE(cs35l45_irqs); i++) { | ||
| 1234 | irq = regmap_irq_get_virq(cs35l45->irq_data, cs35l45_irqs[i].irq); | ||
| 1235 | if (irq < 0) { | ||
| 1236 | dev_err(dev, "Failed to get %s\n", cs35l45_irqs[i].name); | ||
| 1237 | ret = irq; | ||
| 1238 | goto err_dsp; | ||
| 1239 | } | ||
| 1240 | |||
| 1241 | ret = devm_request_threaded_irq(dev, irq, NULL, cs35l45_irqs[i].handler, | ||
| 1242 | irq_pol, cs35l45_irqs[i].name, cs35l45); | ||
| 1243 | if (ret) { | ||
| 1244 | dev_err(dev, "Failed to request IRQ %s: %d\n", | ||
| 1245 | cs35l45_irqs[i].name, ret); | ||
| 1246 | goto err_dsp; | ||
| 1247 | } | ||
| 1248 | } | ||
| 1249 | } | ||
| 1250 | |||
| 652 | ret = devm_snd_soc_register_component(dev, &cs35l45_component, | 1251 | ret = devm_snd_soc_register_component(dev, &cs35l45_component, |
| 653 | cs35l45_dai, | 1252 | cs35l45_dai, |
| 654 | ARRAY_SIZE(cs35l45_dai)); | 1253 | ARRAY_SIZE(cs35l45_dai)); |
| 655 | if (ret < 0) | 1254 | if (ret < 0) |
| 656 | goto err_reset; | 1255 | goto err_dsp; |
| 1256 | |||
| 1257 | pm_runtime_put_autosuspend(cs35l45->dev); | ||
| 657 | 1258 | ||
| 658 | return 0; | 1259 | return 0; |
| 659 | 1260 | ||
| 1261 | err_dsp: | ||
| 1262 | pm_runtime_disable(cs35l45->dev); | ||
| 1263 | pm_runtime_put_noidle(cs35l45->dev); | ||
| 1264 | wm_adsp2_remove(&cs35l45->dsp); | ||
| 1265 | |||
| 660 | err_reset: | 1266 | err_reset: |
| 661 | gpiod_set_value_cansleep(cs35l45->reset_gpio, 0); | 1267 | gpiod_set_value_cansleep(cs35l45->reset_gpio, 0); |
| 662 | err: | 1268 | err: |
| @@ -669,9 +1275,13 @@ EXPORT_SYMBOL_NS_GPL(cs35l45_probe, SND_SOC_CS35L45); · 6 unmodified lines | |||
| 669 | 1275 | ||
| 670 | void cs35l45_remove(struct cs35l45_private *cs35l45) | 1276 | void cs35l45_remove(struct cs35l45_private *cs35l45) |
| 671 | { | 1277 | { |
| 1278 | pm_runtime_get_sync(cs35l45->dev); | ||
| 672 | pm_runtime_disable(cs35l45->dev); | 1279 | pm_runtime_disable(cs35l45->dev); |
| 1280 | wm_adsp2_remove(&cs35l45->dsp); | ||
| 673 | 1281 | ||
| 674 | gpiod_set_value_cansleep(cs35l45->reset_gpio, 0); | 1282 | gpiod_set_value_cansleep(cs35l45->reset_gpio, 0); |
| 1283 | |||
| 1284 | pm_runtime_put_noidle(cs35l45->dev); | ||
| 675 | regulator_disable(cs35l45->vdd_a); | 1285 | regulator_disable(cs35l45->vdd_a); |
| 676 | /* VDD_BATT must be the last to power-off */ | 1286 | /* VDD_BATT must be the last to power-off */ |
| 677 | regulator_disable(cs35l45->vdd_batt); | 1287 | regulator_disable(cs35l45->vdd_batt); |
| @@ -14,6 +14,8 @@ · 13 unmodified lines | |||
| 14 | #include <linux/pm_runtime.h> | 14 | #include <linux/pm_runtime.h> |
| 15 | #include <linux/regmap.h> | 15 | #include <linux/regmap.h> |
| 16 | #include <linux/regulator/consumer.h> | 16 | #include <linux/regulator/consumer.h> |
| 17 | #include <dt-bindings/sound/cs35l45.h> | ||
| 18 | #include "wm_adsp.h" | ||
| 17 | 19 | ||
| 18 | #define CS35L45_DEVID 0x00000000 | 20 | #define CS35L45_DEVID 0x00000000 |
| 19 | #define CS35L45_REVID 0x00000004 | 21 | #define CS35L45_REVID 0x00000004 |
| @@ -24,6 +26,13 @@ · 4 unmodified lines | |||
| 24 | #define CS35L45_BLOCK_ENABLES 0x00002018 | 26 | #define CS35L45_BLOCK_ENABLES 0x00002018 |
| 25 | #define CS35L45_BLOCK_ENABLES2 0x0000201C | 27 | #define CS35L45_BLOCK_ENABLES2 0x0000201C |
| 26 | #define CS35L45_ERROR_RELEASE 0x00002034 | 28 | #define CS35L45_ERROR_RELEASE 0x00002034 |
| 29 | #define CS35L45_SYNC_GPIO1 0x00002430 | ||
| 30 | #define CS35L45_INTB_GPIO2_MCLK_REF 0x00002434 | ||
| 31 | #define CS35L45_GPIO3 0x00002438 | ||
| 32 | #define CS35L45_PWRMGT_CTL 0x00002900 | ||
| 33 | #define CS35L45_WAKESRC_CTL 0x00002904 | ||
| 34 | #define CS35L45_WKI2C_CTL 0x00002908 | ||
| 35 | #define CS35L45_PWRMGT_STS 0x0000290C | ||
| 27 | #define CS35L45_REFCLK_INPUT 0x00002C04 | 36 | #define CS35L45_REFCLK_INPUT 0x00002C04 |
| 28 | #define CS35L45_GLOBAL_SAMPLE_RATE 0x00002C0C | 37 | #define CS35L45_GLOBAL_SAMPLE_RATE 0x00002C0C |
| 29 | #define CS35L45_BOOST_CCM_CFG 0x00003808 | 38 | #define CS35L45_BOOST_CCM_CFG 0x00003808 |
| @@ -44,11 +53,105 @@ · 14 unmodified lines | |||
| 44 | #define CS35L45_ASPTX3_INPUT 0x00004C28 | 53 | #define CS35L45_ASPTX3_INPUT 0x00004C28 |
| 45 | #define CS35L45_ASPTX4_INPUT 0x00004C2C | 54 | #define CS35L45_ASPTX4_INPUT 0x00004C2C |
| 46 | #define CS35L45_ASPTX5_INPUT 0x00004C30 | 55 | #define CS35L45_ASPTX5_INPUT 0x00004C30 |
| 56 | #define CS35L45_DSP1RX1_INPUT 0x00004C40 | ||
| 57 | #define CS35L45_DSP1RX2_INPUT 0x00004C44 | ||
| 58 | #define CS35L45_DSP1RX3_INPUT 0x00004C48 | ||
| 59 | #define CS35L45_DSP1RX4_INPUT 0x00004C4C | ||
| 60 | #define CS35L45_DSP1RX5_INPUT 0x00004C50 | ||
| 61 | #define CS35L45_DSP1RX6_INPUT 0x00004C54 | ||
| 62 | #define CS35L45_DSP1RX7_INPUT 0x00004C58 | ||
| 63 | #define CS35L45_DSP1RX8_INPUT 0x00004C5C | ||
| 47 | #define CS35L45_LDPM_CONFIG 0x00006404 | 64 | #define CS35L45_LDPM_CONFIG 0x00006404 |
| 48 | #define CS35L45_AMP_PCM_CONTROL 0x00007000 | 65 | #define CS35L45_AMP_PCM_CONTROL 0x00007000 |
| 49 | #define CS35L45_AMP_PCM_HPF_TST 0x00007004 | 66 | #define CS35L45_AMP_PCM_HPF_TST 0x00007004 |
| 67 | #define CS35L45_IRQ1_CFG 0x0000E000 | ||
| 68 | #define CS35L45_IRQ1_STATUS 0x0000E004 | ||
| 69 | #define CS35L45_IRQ1_EINT_1 0x0000E010 | ||
| 70 | #define CS35L45_IRQ1_EINT_2 0x0000E014 | ||
| 71 | #define CS35L45_IRQ1_EINT_3 0x0000E018 | ||
| 50 | #define CS35L45_IRQ1_EINT_4 0x0000E01C | 72 | #define CS35L45_IRQ1_EINT_4 0x0000E01C |
| 51 | #define CS35L45_LASTREG 0x0000E01C | 73 | #define CS35L45_IRQ1_EINT_5 0x0000E020 |
| 74 | #define CS35L45_IRQ1_EINT_7 0x0000E028 | ||
| 75 | #define CS35L45_IRQ1_EINT_8 0x0000E02C | ||
| 76 | #define CS35L45_IRQ1_EINT_18 0x0000E054 | ||
| 77 | #define CS35L45_IRQ1_STS_1 0x0000E090 | ||
| 78 | #define CS35L45_IRQ1_STS_2 0x0000E094 | ||
| 79 | #define CS35L45_IRQ1_STS_3 0x0000E098 | ||
| 80 | #define CS35L45_IRQ1_STS_4 0x0000E09C | ||
| 81 | #define CS35L45_IRQ1_STS_5 0x0000E0A0 | ||
| 82 | #define CS35L45_IRQ1_STS_7 0x0000E0A8 | ||
| 83 | #define CS35L45_IRQ1_STS_8 0x0000E0AC | ||
| 84 | #define CS35L45_IRQ1_STS_18 0x0000E0D4 | ||
| 85 | #define CS35L45_IRQ1_MASK_1 0x0000E110 | ||
| 86 | #define CS35L45_IRQ1_MASK_2 0x0000E114 | ||
| 87 | #define CS35L45_IRQ1_MASK_3 0x0000E118 | ||
| 88 | #define CS35L45_IRQ1_MASK_4 0x0000E11C | ||
| 89 | #define CS35L45_IRQ1_MASK_5 0x0000E120 | ||
| 90 | #define CS35L45_IRQ1_MASK_6 0x0000E124 | ||
| 91 | #define CS35L45_IRQ1_MASK_7 0x0000E128 | ||
| 92 | #define CS35L45_IRQ1_MASK_8 0x0000E12C | ||
| 93 | #define CS35L45_IRQ1_MASK_9 0x0000E130 | ||
| 94 | #define CS35L45_IRQ1_MASK_10 0x0000E134 | ||
| 95 | #define CS35L45_IRQ1_MASK_11 0x0000E138 | ||
| 96 | #define CS35L45_IRQ1_MASK_12 0x0000E13C | ||
| 97 | #define CS35L45_IRQ1_MASK_13 0x0000E140 | ||
| 98 | #define CS35L45_IRQ1_MASK_14 0x0000E144 | ||
| 99 | #define CS35L45_IRQ1_MASK_15 0x0000E148 | ||
| 100 | #define CS35L45_IRQ1_MASK_16 0x0000E14C | ||
| 101 | #define CS35L45_IRQ1_MASK_17 0x0000E150 | ||
| 102 | #define CS35L45_IRQ1_MASK_18 0x0000E154 | ||
| 103 | #define CS35L45_GPIO_STATUS1 0x0000F000 | ||
| 104 | #define CS35L45_GPIO1_CTRL1 0x0000F008 | ||
| 105 | #define CS35L45_GPIO2_CTRL1 0x0000F00C | ||
| 106 | #define CS35L45_GPIO3_CTRL1 0x0000F010 | ||
| 107 | #define CS35L45_DSP_MBOX_1 0x00011000 | ||
| 108 | #define CS35L45_DSP_MBOX_2 0x00011004 | ||
| 109 | #define CS35L45_DSP_VIRT1_MBOX_1 0x00011020 | ||
| 110 | #define CS35L45_DSP_VIRT1_MBOX_2 0x00011024 | ||
| 111 | #define CS35L45_DSP_VIRT1_MBOX_3 0x00011028 | ||
| 112 | #define CS35L45_DSP_VIRT1_MBOX_4 0x0001102C | ||
| 113 | #define CS35L45_DSP_VIRT2_MBOX_1 0x00011040 | ||
| 114 | #define CS35L45_DSP_VIRT2_MBOX_2 0x00011044 | ||
| 115 | #define CS35L45_DSP_VIRT2_MBOX_3 0x00011048 | ||
| 116 | #define CS35L45_DSP_VIRT2_MBOX_4 0x0001104C | ||
| 117 | #define CS35L45_DSP1_XMEM_PACK_0 0x02000000 | ||
| 118 | #define CS35L45_DSP1_XMEM_PACK_4607 0x020047FC | ||
| 119 | #define CS35L45_DSP1_XMEM_UNPACK32_0 0x02400000 | ||
| 120 | #define CS35L45_DSP1_XMEM_UNPACK32_3071 0x02402FFC | ||
| 121 | #define CS35L45_DSP1_SYS_ID 0x025E0000 | ||
| 122 | #define CS35L45_DSP1_XMEM_UNPACK24_0 0x02800000 | ||
| 123 | #define CS35L45_DSP1_XMEM_UNPACK24_6143 0x02805FFC | ||
| 124 | #define CS35L45_DSP1_CLOCK_FREQ 0x02B80000 | ||
| 125 | #define CS35L45_DSP1_RX1_RATE 0x02B80080 | ||
| 126 | #define CS35L45_DSP1_RX2_RATE 0x02B80088 | ||
| 127 | #define CS35L45_DSP1_RX3_RATE 0x02B80090 | ||
| 128 | #define CS35L45_DSP1_RX4_RATE 0x02B80098 | ||
| 129 | #define CS35L45_DSP1_RX5_RATE 0x02B800A0 | ||
| 130 | #define CS35L45_DSP1_RX6_RATE 0x02B800A8 | ||
| 131 | #define CS35L45_DSP1_RX7_RATE 0x02B800B0 | ||
| 132 | #define CS35L45_DSP1_RX8_RATE 0x02B800B8 | ||
| 133 | #define CS35L45_DSP1_TX1_RATE 0x02B80280 | ||
| 134 | #define CS35L45_DSP1_TX2_RATE 0x02B80288 | ||
| 135 | #define CS35L45_DSP1_TX3_RATE 0x02B80290 | ||
| 136 | #define CS35L45_DSP1_TX4_RATE 0x02B80298 | ||
| 137 | #define CS35L45_DSP1_TX5_RATE 0x02B802A0 | ||
| 138 | #define CS35L45_DSP1_TX6_RATE 0x02B802A8 | ||
| 139 | #define CS35L45_DSP1_TX7_RATE 0x02B802B0 | ||
| 140 | #define CS35L45_DSP1_TX8_RATE 0x02B802B8 | ||
| 141 | #define CS35L45_DSP1_SCRATCH1 0x02B805C0 | ||
| 142 | #define CS35L45_DSP1_SCRATCH2 0x02B805C8 | ||
| 143 | #define CS35L45_DSP1_SCRATCH3 0x02B805D0 | ||
| 144 | #define CS35L45_DSP1_SCRATCH4 0x02B805D8 | ||
| 145 | #define CS35L45_DSP1_CCM_CORE_CONTROL 0x02BC1000 | ||
| 146 | #define CS35L45_DSP1_YMEM_PACK_0 0x02C00000 | ||
| 147 | #define CS35L45_DSP1_YMEM_PACK_1532 0x02C017F0 | ||
| 148 | #define CS35L45_DSP1_YMEM_UNPACK32_0 0x03000000 | ||
| 149 | #define CS35L45_DSP1_YMEM_UNPACK32_1022 0x03000FF8 | ||
| 150 | #define CS35L45_DSP1_YMEM_UNPACK24_0 0x03400000 | ||
| 151 | #define CS35L45_DSP1_YMEM_UNPACK24_2043 0x03401FEC | ||
| 152 | #define CS35L45_DSP1_PMEM_0 0x03800000 | ||
| 153 | #define CS35L45_DSP1_PMEM_3834 0x03803BE8 | ||
| 154 | #define CS35L45_LASTREG 0x03C6EFE8 | ||
| 52 | 155 | ||
| 53 | /* SFT_RESET */ | 156 | /* SFT_RESET */ |
| 54 | #define CS35L45_SOFT_RESET_TRIGGER 0x5A000000 | 157 | #define CS35L45_SOFT_RESET_TRIGGER 0x5A000000 |
| @@ -70,9 +173,20 @@ · 15 unmodified lines | |||
| 70 | /* BLOCK_ENABLES2 */ | 173 | /* BLOCK_ENABLES2 */ |
| 71 | #define CS35L45_ASP_EN_SHIFT 27 | 174 | #define CS35L45_ASP_EN_SHIFT 27 |
| 72 | 175 | ||
| 176 | #define CS35L45_MEM_RDY_SHIFT 1 | ||
| 177 | #define CS35L45_MEM_RDY_MASK BIT(1) | ||
| 178 | |||
| 73 | /* ERROR_RELEASE */ | 179 | /* ERROR_RELEASE */ |
| 74 | #define CS35L45_GLOBAL_ERR_RLS_MASK BIT(11) | 180 | #define CS35L45_GLOBAL_ERR_RLS_MASK BIT(11) |
| 75 | 181 | ||
| 182 | /* CCM_CORE */ | ||
| 183 | #define CS35L45_CCM_CORE_RESET_SHIFT 9 | ||
| 184 | #define CS35L45_CCM_CORE_RESET_MASK BIT(9) | ||
| 185 | #define CS35L45_CCM_PM_REMAP_SHIFT 7 | ||
| 186 | #define CS35L45_CCM_PM_REMAP_MASK BIT(7) | ||
| 187 | #define CS35L45_CCM_CORE_EN_SHIFT 0 | ||
| 188 | #define CS35L45_CCM_CORE_EN_MASK BIT(0) | ||
| 189 | |||
| 76 | /* REFCLK_INPUT */ | 190 | /* REFCLK_INPUT */ |
| 77 | #define CS35L45_PLL_FORCE_EN_SHIFT 16 | 191 | #define CS35L45_PLL_FORCE_EN_SHIFT 16 |
| 78 | #define CS35L45_PLL_FORCE_EN_MASK BIT(16) | 192 | #define CS35L45_PLL_FORCE_EN_MASK BIT(16) |
| @@ -165,6 +279,56 @@ · 86 unmodified lines | |||
| 165 | #define CS35L45_OTP_BOOT_DONE_STS_MASK BIT(1) | 279 | #define CS35L45_OTP_BOOT_DONE_STS_MASK BIT(1) |
| 166 | #define CS35L45_OTP_BUSY_MASK BIT(0) | 280 | #define CS35L45_OTP_BUSY_MASK BIT(0) |
| 167 | 281 | ||
| 282 | /* GPIOX_CTRL1 */ | ||
| 283 | #define CS35L45_GPIO_DIR_SHIFT 31 | ||
| 284 | #define CS35L45_GPIO_DIR_MASK BIT(31) | ||
| 285 | #define CS35L45_GPIO_LVL_SHIFT 15 | ||
| 286 | #define CS35L45_GPIO_LVL_MASK BIT(15) | ||
| 287 | #define CS35L45_GPIO_OP_CFG_SHIFT 14 | ||
| 288 | #define CS35L45_GPIO_OP_CFG_MASK BIT(14) | ||
| 289 | #define CS35L45_GPIO_POL_SHIFT 12 | ||
| 290 | #define CS35L45_GPIO_POL_MASK BIT(12) | ||
| 291 | |||
| 292 | /* SYNC_GPIO1, INTB_GPIO2_MCLK_REF, GPIO3 */ | ||
| 293 | #define CS35L45_GPIO_CTRL_SHIFT 20 | ||
| 294 | #define CS35L45_GPIO_CTRL_MASK GENMASK(22, 20) | ||
| 295 | #define CS35L45_GPIO_INVERT_SHIFT 19 | ||
| 296 | #define CS35L45_GPIO_INVERT_MASK BIT(19) | ||
| 297 | |||
| 298 | /* CS35L45_IRQ1_EINT_1 */ | ||
| 299 | #define CS35L45_BST_UVP_ERR_SHIFT 7 | ||
| 300 | #define CS35L45_BST_UVP_ERR_MASK BIT(7) | ||
| 301 | #define CS35L45_BST_SHORT_ERR_SHIFT 8 | ||
| 302 | #define CS35L45_BST_SHORT_ERR_MASK BIT(8) | ||
| 303 | #define CS35L45_TEMP_ERR_SHIFT 17 | ||
| 304 | #define CS35L45_TEMP_ERR_MASK BIT(17) | ||
| 305 | #define CS35L45_MSM_GLOBAL_EN_ASSERT_SHIFT 22 | ||
| 306 | #define CS35L45_MSM_GLOBAL_EN_ASSERT_MASK BIT(22) | ||
| 307 | #define CS35L45_UVLO_VDDBATT_ERR_SHIFT 29 | ||
| 308 | #define CS35L45_UVLO_VDDBATT_ERR_MASK BIT(29) | ||
| 309 | #define CS35L45_AMP_SHORT_ERR_SHIFT 31 | ||
| 310 | #define CS35L45_AMP_SHORT_ERR_MASK BIT(31) | ||
| 311 | |||
| 312 | /* CS35L45_IRQ1_EINT_2 */ | ||
| 313 | #define CS35L45_DSP_WDT_EXPIRE_SHIFT 4 | ||
| 314 | #define CS35L45_DSP_WDT_EXPIRE_MASK BIT(4) | ||
| 315 | #define CS35L45_DSP_VIRT2_MBOX_SHIFT 21 | ||
| 316 | #define CS35L45_DSP_VIRT2_MBOX_MASK BIT(21) | ||
| 317 | |||
| 318 | /* CS35L45_IRQ1_EINT_3 */ | ||
| 319 | #define CS35L45_PLL_LOCK_FLAG_SHIFT 1 | ||
| 320 | #define CS35L45_PLL_LOCK_FLAG_MASK BIT(1) | ||
| 321 | #define CS35L45_PLL_UNLOCK_FLAG_RISE_SHIFT 4 | ||
| 322 | #define CS35L45_PLL_UNLOCK_FLAG_RISE_MASK BIT(4) | ||
| 323 | #define CS35L45_AMP_CAL_ERR_SHIFT 25 | ||
| 324 | #define CS35L45_AMP_CAL_ERR_MASK BIT(25) | ||
| 325 | |||
| 326 | /* CS35L45_IRQ1_EINT_18 */ | ||
| 327 | #define CS35L45_GLOBAL_ERROR_SHIFT 15 | ||
| 328 | #define CS35L45_GLOBAL_ERROR_MASK BIT(15) | ||
| 329 | #define CS35L45_UVLO_VDDLV_ERR_SHIFT 16 | ||
| 330 | #define CS35L45_UVLO_VDDLV_ERR_MASK BIT(16) | ||
| 331 | |||
| 168 | /* Mixer sources */ | 332 | /* Mixer sources */ |
| 169 | #define CS35L45_PCM_SRC_MASK 0x7F | 333 | #define CS35L45_PCM_SRC_MASK 0x7F |
| 170 | #define CS35L45_PCM_SRC_ZERO 0x00 | 334 | #define CS35L45_PCM_SRC_ZERO 0x00 |
| @@ -176,6 +340,8 @@ · 5 unmodified lines | |||
| 176 | #define CS35L45_PCM_SRC_CLASSH_TGT 0x21 | 340 | #define CS35L45_PCM_SRC_CLASSH_TGT 0x21 |
| 177 | #define CS35L45_PCM_SRC_VDD_BATTMON 0x28 | 341 | #define CS35L45_PCM_SRC_VDD_BATTMON 0x28 |
| 178 | #define CS35L45_PCM_SRC_VDD_BSTMON 0x29 | 342 | #define CS35L45_PCM_SRC_VDD_BSTMON 0x29 |
| 343 | #define CS35L45_PCM_SRC_DSP_TX1 0x32 | ||
| 344 | #define CS35L45_PCM_SRC_DSP_TX2 0x33 | ||
| 179 | #define CS35L45_PCM_SRC_TEMPMON 0x3A | 345 | #define CS35L45_PCM_SRC_TEMPMON 0x3A |
| 180 | #define CS35L45_PCM_SRC_INTERPOLATOR 0x40 | 346 | #define CS35L45_PCM_SRC_INTERPOLATOR 0x40 |
| 181 | #define CS35L45_PCM_SRC_IL_TARGET 0x48 | 347 | #define CS35L45_PCM_SRC_IL_TARGET 0x48 |
| @@ -185,6 +351,51 @@ · 3 unmodified lines | |||
| 185 | #define CS35L45_POST_GLOBAL_EN_US 5000 | 351 | #define CS35L45_POST_GLOBAL_EN_US 5000 |
| 186 | #define CS35L45_PRE_GLOBAL_DIS_US 3000 | 352 | #define CS35L45_PRE_GLOBAL_DIS_US 3000 |
| 187 | 353 | ||
| 354 | /* WAKESRC_CTL */ | ||
| 355 | #define CS35L45_WKSRC_SYNC_GPIO1 BIT(0) | ||
| 356 | #define CS35L45_WKSRC_INT_GPIO2 BIT(1) | ||
| 357 | #define CS35L45_WKSRC_GPIO3 BIT(2) | ||
| 358 | #define CS35L45_WKSRC_SPI BIT(3) | ||
| 359 | #define CS35L45_WKSRC_I2C BIT(4) | ||
| 360 | #define CS35L45_UPDT_WKCTL_SHIFT 15 | ||
| 361 | #define CS35L45_UPDT_WKCTL_MASK BIT(15) | ||
| 362 | #define CS35L45_WKSRC_EN_SHIFT 8 | ||
| 363 | #define CS35L45_WKSRC_EN_MASK GENMASK(12, 8) | ||
| 364 | #define CS35L45_WKSRC_POL_SHIFT 0 | ||
| 365 | #define CS35L45_WKSRC_POL_MASK GENMASK(3, 0) | ||
| 366 | |||
| 367 | /* WAKEI2C_CTL */ | ||
| 368 | #define CS35L45_UPDT_WKI2C_SHIFT 15 | ||
| 369 | #define CS35L45_UPDT_WKI2C_MASK BIT(15) | ||
| 370 | #define CS35L45_WKI2C_ADDR_SHIFT 0 | ||
| 371 | #define CS35L45_WKI2C_ADDR_MASK GENMASK(6, 0) | ||
| 372 | |||
| 373 | #define CS35L45_SPI_MAX_FREQ 4000000 | ||
| 374 | |||
| 375 | enum cs35l45_cspl_mboxstate { | ||
| 376 | CSPL_MBOX_STS_RUNNING = 0, | ||
| 377 | CSPL_MBOX_STS_PAUSED = 1, | ||
| 378 | CSPL_MBOX_STS_RDY_FOR_REINIT = 2, | ||
| 379 | CSPL_MBOX_STS_HIBERNATE = 3, | ||
| 380 | }; | ||
| 381 | |||
| 382 | enum cs35l45_cspl_mboxcmd { | ||
| 383 | CSPL_MBOX_CMD_NONE = 0, | ||
| 384 | CSPL_MBOX_CMD_PAUSE = 1, | ||
| 385 | CSPL_MBOX_CMD_RESUME = 2, | ||
| 386 | CSPL_MBOX_CMD_REINIT = 3, | ||
| 387 | CSPL_MBOX_CMD_STOP_PRE_REINIT = 4, | ||
| 388 | CSPL_MBOX_CMD_HIBERNATE = 5, | ||
| 389 | CSPL_MBOX_CMD_OUT_OF_HIBERNATE = 6, | ||
| 390 | CSPL_MBOX_CMD_UNKNOWN_CMD = -1, | ||
| 391 | CSPL_MBOX_CMD_INVALID_SEQUENCE = -2, | ||
| 392 | }; | ||
| 393 | |||
| 394 | enum control_bus_type { | ||
| 395 | CONTROL_BUS_I2C = 0, | ||
| 396 | CONTROL_BUS_SPI = 1, | ||
| 397 | }; | ||
| 398 | |||
| 188 | #define CS35L45_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | \ | 399 | #define CS35L45_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | \ |
| 189 | SNDRV_PCM_FMTBIT_S24_3LE| \ | 400 | SNDRV_PCM_FMTBIT_S24_3LE| \ |
| 190 | SNDRV_PCM_FMTBIT_S24_LE) | 401 | SNDRV_PCM_FMTBIT_S24_LE) |
| @@ -194,7 +405,56 @@ · 3 unmodified lines | |||
| 194 | SNDRV_PCM_RATE_88200 | \ | 405 | SNDRV_PCM_RATE_88200 | \ |
| 195 | SNDRV_PCM_RATE_96000) | 406 | SNDRV_PCM_RATE_96000) |
| 196 | 407 | ||
| 408 | /* | ||
| 409 | * IRQs | ||
| 410 | */ | ||
| 411 | #define CS35L45_IRQ(_irq, _name, _hand) \ | ||
| 412 | { \ | ||
| 413 | .irq = CS35L45_ ## _irq ## _IRQ,\ | ||
| 414 | .name = _name, \ | ||
| 415 | .handler = _hand, \ | ||
| 416 | } | ||
| 417 | |||
| 418 | struct cs35l45_irq { | ||
| 419 | int irq; | ||
| 420 | const char *name; | ||
| 421 | irqreturn_t (*handler)(int irq, void *data); | ||
| 422 | }; | ||
| 423 | |||
| 424 | #define CS35L45_REG_IRQ(_reg, _irq) \ | ||
| 425 | [CS35L45_ ## _irq ## _IRQ] = { \ | ||
| 426 | .reg_offset = (CS35L45_ ## _reg) - CS35L45_IRQ1_EINT_1, \ | ||
| 427 | .mask = CS35L45_ ## _irq ## _MASK \ | ||
| 428 | } | ||
| 429 | |||
| 430 | enum cs35l45_irq_list { | ||
| 431 | CS35L45_AMP_SHORT_ERR_IRQ, | ||
| 432 | CS35L45_UVLO_VDDBATT_ERR_IRQ, | ||
| 433 | CS35L45_BST_SHORT_ERR_IRQ, | ||
| 434 | CS35L45_BST_UVP_ERR_IRQ, | ||
| 435 | CS35L45_TEMP_ERR_IRQ, | ||
| 436 | CS35L45_AMP_CAL_ERR_IRQ, | ||
| 437 | CS35L45_UVLO_VDDLV_ERR_IRQ, | ||
| 438 | CS35L45_GLOBAL_ERROR_IRQ, | ||
| 439 | CS35L45_DSP_WDT_EXPIRE_IRQ, | ||
| 440 | CS35L45_PLL_UNLOCK_FLAG_RISE_IRQ, | ||
| 441 | CS35L45_PLL_LOCK_FLAG_IRQ, | ||
| 442 | CS35L45_DSP_VIRT2_MBOX_IRQ, | ||
| 443 | CS35L45_NUM_IRQ | ||
| 444 | }; | ||
| 445 | |||
| 446 | #define CS35L45_MBOX3_CMD_MASK 0xFF | ||
| 447 | #define CS35L45_MBOX3_CMD_SHIFT 0 | ||
| 448 | #define CS35L45_MBOX3_DATA_MASK 0xFFFFFF00 | ||
| 449 | #define CS35L45_MBOX3_DATA_SHIFT 8 | ||
| 450 | |||
| 451 | enum mbox3_events { | ||
| 452 | EVENT_SPEAKER_STATUS = 0x66, | ||
| 453 | EVENT_BOOT_DONE = 0x67, | ||
| 454 | }; | ||
| 455 | |||
| 197 | struct cs35l45_private { | 456 | struct cs35l45_private { |
| 457 | struct wm_adsp dsp; /* needs to be first member */ | ||
| 198 | struct device *dev; | 458 | struct device *dev; |
| 199 | struct regmap *regmap; | 459 | struct regmap *regmap; |
| 200 | struct gpio_desc *reset_gpio; | 460 | struct gpio_desc *reset_gpio; |
| @@ -204,6 +464,11 @@ struct cs35l45_private { · 3 unmodified lines | |||
| 204 | bool sysclk_set; | 464 | bool sysclk_set; |
| 205 | u8 slot_width; | 465 | u8 slot_width; |
| 206 | u8 slot_count; | 466 | u8 slot_count; |
| 467 | int irq_invert; | ||
| 468 | int irq; | ||
| 469 | unsigned int i2c_addr; | ||
| 470 | enum control_bus_type bus_type; | ||
| 471 | struct regmap_irq_chip_data *irq_data; | ||
| 207 | }; | 472 | }; |
| 208 | 473 | ||
| 209 | extern const struct dev_pm_ops cs35l45_pm_ops; | 474 | extern const struct dev_pm_ops cs35l45_pm_ops; |
| @@ -0,0 +1,82 @@ | |||
| 1 | // SPDX-License-Identifier: GPL-2.0-only | ||
| 2 | // | ||
| 3 | // CS35L56 ALSA SoC audio driver I2C binding | ||
| 4 | // | ||
| 5 | // Copyright (C) 2023 Cirrus Logic, Inc. and | ||
| 6 | // Cirrus Logic International Semiconductor Ltd. | ||
| 7 | |||
| 8 | #include <linux/acpi.h> | ||
| 9 | #include <linux/i2c.h> | ||
| 10 | #include <linux/module.h> | ||
| 11 | #include <linux/moduleparam.h> | ||
| 12 | #include <linux/regmap.h> | ||
| 13 | #include <linux/slab.h> | ||
| 14 | #include <linux/types.h> | ||
| 15 | |||
| 16 | #include "cs35l56.h" | ||
| 17 | |||
| 18 | static int cs35l56_i2c_probe(struct i2c_client *client) | ||
| 19 | { | ||
| 20 | struct cs35l56_private *cs35l56; | ||
| 21 | struct device *dev = &client->dev; | ||
| 22 | const struct regmap_config *regmap_config = &cs35l56_regmap_i2c; | ||
| 23 | int ret; | ||
| 24 | |||
| 25 | cs35l56 = devm_kzalloc(dev, sizeof(struct cs35l56_private), GFP_KERNEL); | ||
| 26 | if (!cs35l56) | ||
| 27 | return -ENOMEM; | ||
| 28 | |||
| 29 | cs35l56->dev = dev; | ||
| 30 | cs35l56->can_hibernate = true; | ||
| 31 | |||
| 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"); | ||
| 37 | } | ||
| 38 | |||
| 39 | ret = cs35l56_common_probe(cs35l56); | ||
| 40 | if (ret != 0) | ||
| 41 | return ret; | ||
| 42 | |||
| 43 | ret = cs35l56_init(cs35l56); | ||
| 44 | if (ret == 0) | ||
| 45 | ret = cs35l56_irq_request(cs35l56, client->irq); | ||
| 46 | if (ret < 0) | ||
| 47 | cs35l56_remove(cs35l56); | ||
| 48 | |||
| 49 | return ret; | ||
| 50 | } | ||
| 51 | |||
| 52 | static void cs35l56_i2c_remove(struct i2c_client *client) | ||
| 53 | { | ||
| 54 | struct cs35l56_private *cs35l56 = i2c_get_clientdata(client); | ||
| 55 | |||
| 56 | cs35l56_remove(cs35l56); | ||
| 57 | } | ||
| 58 | |||
| 59 | static const struct i2c_device_id cs35l56_id_i2c[] = { | ||
| 60 | { "cs35l56", 0 }, | ||
| 61 | {} | ||
| 62 | }; | ||
| 63 | MODULE_DEVICE_TABLE(i2c, cs35l56_id_i2c); | ||
| 64 | |||
| 65 | static struct i2c_driver cs35l56_i2c_driver = { | ||
| 66 | .driver = { | ||
| 67 | .name = "cs35l56", | ||
| 68 | .pm = &cs35l56_pm_ops_i2c_spi, | ||
| 69 | }, | ||
| 70 | .id_table = cs35l56_id_i2c, | ||
| 71 | .probe_new = cs35l56_i2c_probe, | ||
| 72 | .remove = cs35l56_i2c_remove, | ||
| 73 | }; | ||
| 74 | |||
| 75 | module_i2c_driver(cs35l56_i2c_driver); | ||
| 76 | |||
| 77 | MODULE_DESCRIPTION("ASoC CS35L56 I2C driver"); | ||
| 78 | MODULE_IMPORT_NS(SND_SOC_CS35L56_CORE); | ||
| 79 | MODULE_IMPORT_NS(SND_SOC_CS35L56_SHARED); | ||
| 80 | MODULE_AUTHOR("Richard Fitzgerald <rf@opensource.cirrus.com>"); | ||
| 81 | MODULE_AUTHOR("Simon Trimmer <simont@opensource.cirrus.com>"); | ||
| 82 | MODULE_LICENSE("GPL"); | ||
| @@ -0,0 +1,566 @@ | |||
| 1 | // SPDX-License-Identifier: GPL-2.0-only | ||
| 2 | // | ||
| 3 | // CS35L56 ALSA SoC audio driver SoundWire binding | ||
| 4 | // | ||
| 5 | // Copyright (C) 2023 Cirrus Logic, Inc. and | ||
| 6 | // Cirrus Logic International Semiconductor Ltd. | ||
| 7 | |||
| 8 | #include <linux/delay.h> | ||
| 9 | #include <linux/device.h> | ||
| 10 | #include <linux/err.h> | ||
| 11 | #include <linux/module.h> | ||
| 12 | #include <linux/pm_runtime.h> | ||
| 13 | #include <linux/regmap.h> | ||
| 14 | #include <linux/soundwire/sdw.h> | ||
| 15 | #include <linux/soundwire/sdw_registers.h> | ||
| 16 | #include <linux/soundwire/sdw_type.h> | ||
| 17 | #include <linux/swab.h> | ||
| 18 | #include <linux/types.h> | ||
| 19 | #include <linux/workqueue.h> | ||
| 20 | |||
| 21 | #include "cs35l56.h" | ||
| 22 | |||
| 23 | /* Register addresses are offset when sent over SoundWire */ | ||
| 24 | #define CS35L56_SDW_ADDR_OFFSET 0x8000 | ||
| 25 | |||
| 26 | static int cs35l56_sdw_read_one(struct sdw_slave *peripheral, unsigned int reg, void *buf) | ||
| 27 | { | ||
| 28 | int ret; | ||
| 29 | |||
| 30 | ret = sdw_nread_no_pm(peripheral, reg, 4, (u8 *)buf); | ||
| 31 | if (ret != 0) { | ||
| 32 | dev_err(&peripheral->dev, "Read failed @%#x:%d\n", reg, ret); | ||
| 33 | return ret; | ||
| 34 | } | ||
| 35 | |||
| 36 | swab32s((u32 *)buf); | ||
| 37 | |||
| 38 | return 0; | ||
| 39 | } | ||
| 40 | |||
| 41 | static int cs35l56_sdw_read(void *context, const void *reg_buf, | ||
| 42 | const size_t reg_size, void *val_buf, | ||
| 43 | size_t val_size) | ||
| 44 | { | ||
| 45 | struct sdw_slave *peripheral = context; | ||
| 46 | u8 *buf8 = val_buf; | ||
| 47 | unsigned int reg, bytes; | ||
| 48 | int ret; | ||
| 49 | |||
| 50 | reg = le32_to_cpu(*(const __le32 *)reg_buf); | ||
| 51 | reg += CS35L56_SDW_ADDR_OFFSET; | ||
| 52 | |||
| 53 | if (val_size == 4) | ||
| 54 | return cs35l56_sdw_read_one(peripheral, reg, val_buf); | ||
| 55 | |||
| 56 | while (val_size) { | ||
| 57 | bytes = SDW_REG_NO_PAGE - (reg & SDW_REGADDR); /* to end of page */ | ||
| 58 | if (bytes > val_size) | ||
| 59 | bytes = val_size; | ||
| 60 | |||
| 61 | ret = sdw_nread_no_pm(peripheral, reg, bytes, buf8); | ||
| 62 | if (ret != 0) { | ||
| 63 | dev_err(&peripheral->dev, "Read failed @%#x..%#x:%d\n", | ||
| 64 | reg, reg + bytes - 1, ret); | ||
| 65 | return ret; | ||
| 66 | } | ||
| 67 | |||
| 68 | swab32_array((u32 *)buf8, bytes / 4); | ||
| 69 | val_size -= bytes; | ||
| 70 | reg += bytes; | ||
| 71 | buf8 += bytes; | ||
| 72 | } | ||
| 73 | |||
| 74 | return 0; | ||
| 75 | } | ||
| 76 | |||
| 77 | static inline void cs35l56_swab_copy(void *dest, const void *src, size_t nbytes) | ||
| 78 | { | ||
| 79 | u32 *dest32 = dest; | ||
| 80 | const u32 *src32 = src; | ||
| 81 | |||
| 82 | for (; nbytes > 0; nbytes -= 4) | ||
| 83 | *dest32++ = swab32(*src32++); | ||
| 84 | } | ||
| 85 | |||
| 86 | static int cs35l56_sdw_write_one(struct sdw_slave *peripheral, unsigned int reg, const void *buf) | ||
| 87 | { | ||
| 88 | u32 val_le = swab32(*(u32 *)buf); | ||
| 89 | int ret; | ||
| 90 | |||
| 91 | ret = sdw_nwrite_no_pm(peripheral, reg, 4, (u8 *)&val_le); | ||
| 92 | if (ret != 0) { | ||
| 93 | dev_err(&peripheral->dev, "Write failed @%#x:%d\n", reg, ret); | ||
| 94 | return ret; | ||
| 95 | } | ||
| 96 | |||
| 97 | return 0; | ||
| 98 | } | ||
| 99 | |||
| 100 | static int cs35l56_sdw_gather_write(void *context, | ||
| 101 | const void *reg_buf, size_t reg_size, | ||
| 102 | const void *val_buf, size_t val_size) | ||
| 103 | { | ||
| 104 | struct sdw_slave *peripheral = context; | ||
| 105 | const u8 *src_be = val_buf; | ||
| 106 | u32 val_le_buf[64]; /* Define u32 so it is 32-bit aligned */ | ||
| 107 | unsigned int reg, bytes; | ||
| 108 | int ret; | ||
| 109 | |||
| 110 | reg = le32_to_cpu(*(const __le32 *)reg_buf); | ||
| 111 | reg += CS35L56_SDW_ADDR_OFFSET; | ||
| 112 | |||
| 113 | if (val_size == 4) | ||
| 114 | return cs35l56_sdw_write_one(peripheral, reg, src_be); | ||
| 115 | |||
| 116 | while (val_size) { | ||
| 117 | bytes = SDW_REG_NO_PAGE - (reg & SDW_REGADDR); /* to end of page */ | ||
| 118 | if (bytes > val_size) | ||
| 119 | bytes = val_size; | ||
| 120 | if (bytes > sizeof(val_le_buf)) | ||
| 121 | bytes = sizeof(val_le_buf); | ||
| 122 | |||
| 123 | cs35l56_swab_copy(val_le_buf, src_be, bytes); | ||
| 124 | |||
| 125 | ret = sdw_nwrite_no_pm(peripheral, reg, bytes, (u8 *)val_le_buf); | ||
| 126 | if (ret != 0) { | ||
| 127 | dev_err(&peripheral->dev, "Write failed @%#x..%#x:%d\n", | ||
| 128 | reg, reg + bytes - 1, ret); | ||
| 129 | return ret; | ||
| 130 | } | ||
| 131 | |||
| 132 | val_size -= bytes; | ||
| 133 | reg += bytes; | ||
| 134 | src_be += bytes; | ||
| 135 | } | ||
| 136 | |||
| 137 | return 0; | ||
| 138 | } | ||
| 139 | |||
| 140 | static int cs35l56_sdw_write(void *context, const void *val_buf, size_t val_size) | ||
| 141 | { | ||
| 142 | const u8 *src_buf = val_buf; | ||
| 143 | |||
| 144 | /* First word of val_buf contains the destination address */ | ||
| 145 | return cs35l56_sdw_gather_write(context, &src_buf[0], 4, &src_buf[4], val_size - 4); | ||
| 146 | } | ||
| 147 | |||
| 148 | /* | ||
| 149 | * Registers are big-endian on I2C and SPI but little-endian on SoundWire. | ||
| 150 | * Exported firmware controls are big-endian on I2C/SPI but little-endian on | ||
| 151 | * SoundWire. Firmware files are always big-endian and are opaque blobs. | ||
| 152 | * Present a big-endian regmap and hide the endianness swap, so that the ALSA | ||
| 153 | * byte controls always have the same byte order, and firmware file blobs | ||
| 154 | * can be written verbatim. | ||
| 155 | */ | ||
| 156 | static const struct regmap_bus cs35l56_regmap_bus_sdw = { | ||
| 157 | .read = cs35l56_sdw_read, | ||
| 158 | .write = cs35l56_sdw_write, | ||
| 159 | .gather_write = cs35l56_sdw_gather_write, | ||
| 160 | .reg_format_endian_default = REGMAP_ENDIAN_LITTLE, | ||
| 161 | .val_format_endian_default = REGMAP_ENDIAN_BIG, | ||
| 162 | }; | ||
| 163 | |||
| 164 | static void cs35l56_sdw_init(struct sdw_slave *peripheral) | ||
| 165 | { | ||
| 166 | struct cs35l56_private *cs35l56 = dev_get_drvdata(&peripheral->dev); | ||
| 167 | int ret; | ||
| 168 | |||
| 169 | pm_runtime_get_noresume(cs35l56->dev); | ||
| 170 | |||
| 171 | regcache_cache_only(cs35l56->regmap, false); | ||
| 172 | |||
| 173 | ret = cs35l56_init(cs35l56); | ||
| 174 | if (ret < 0) { | ||
| 175 | regcache_cache_only(cs35l56->regmap, true); | ||
| 176 | goto out; | ||
| 177 | } | ||
| 178 | |||
| 179 | /* | ||
| 180 | * cs35l56_init can return with !init_done if it triggered | ||
| 181 | * a soft reset. | ||
| 182 | */ | ||
| 183 | if (cs35l56->init_done) { | ||
| 184 | /* Enable SoundWire interrupts */ | ||
| 185 | sdw_write_no_pm(peripheral, CS35L56_SDW_GEN_INT_MASK_1, | ||
| 186 | CS35L56_SDW_INT_MASK_CODEC_IRQ); | ||
| 187 | } | ||
| 188 | |||
| 189 | out: | ||
| 190 | pm_runtime_mark_last_busy(cs35l56->dev); | ||
| 191 | pm_runtime_put_autosuspend(cs35l56->dev); | ||
| 192 | } | ||
| 193 | |||
| 194 | static int cs35l56_sdw_interrupt(struct sdw_slave *peripheral, | ||
| 195 | struct sdw_slave_intr_status *status) | ||
| 196 | { | ||
| 197 | struct cs35l56_private *cs35l56 = dev_get_drvdata(&peripheral->dev); | ||
| 198 | |||
| 199 | /* SoundWire core holds our pm_runtime when calling this function. */ | ||
| 200 | |||
| 201 | dev_dbg(cs35l56->dev, "int control_port=%#x\n", status->control_port); | ||
| 202 | |||
| 203 | if ((status->control_port & SDW_SCP_INT1_IMPL_DEF) == 0) | ||
| 204 | return 0; | ||
| 205 | |||
| 206 | /* | ||
| 207 | * Prevent bus manager suspending and possibly issuing a | ||
| 208 | * bus-reset before the queued work has run. | ||
| 209 | */ | ||
| 210 | pm_runtime_get_noresume(cs35l56->dev); | ||
| 211 | |||
| 212 | /* | ||
| 213 | * Mask and clear until it has been handled. The read of GEN_INT_STAT_1 | ||
| 214 | * is required as per the SoundWire spec for interrupt status bits | ||
| 215 | * to clear. GEN_INT_MASK_1 masks the _inputs_ to GEN_INT_STAT1. | ||
| 216 | * None of the interrupts are time-critical so use the | ||
| 217 | * power-efficient queue. | ||
| 218 | */ | ||
| 219 | sdw_write_no_pm(peripheral, CS35L56_SDW_GEN_INT_MASK_1, 0); | ||
| 220 | sdw_read_no_pm(peripheral, CS35L56_SDW_GEN_INT_STAT_1); | ||
| 221 | sdw_write_no_pm(peripheral, CS35L56_SDW_GEN_INT_STAT_1, 0xFF); | ||
| 222 | queue_work(system_power_efficient_wq, &cs35l56->sdw_irq_work); | ||
| 223 | |||
| 224 | return 0; | ||
| 225 | } | ||
| 226 | |||
| 227 | static void cs35l56_sdw_irq_work(struct work_struct *work) | ||
| 228 | { | ||
| 229 | struct cs35l56_private *cs35l56 = container_of(work, | ||
| 230 | struct cs35l56_private, | ||
| 231 | sdw_irq_work); | ||
| 232 | |||
| 233 | cs35l56_irq(-1, cs35l56); | ||
| 234 | |||
| 235 | /* unmask interrupts */ | ||
| 236 | if (!cs35l56->sdw_irq_no_unmask) | ||
| 237 | sdw_write_no_pm(cs35l56->sdw_peripheral, CS35L56_SDW_GEN_INT_MASK_1, | ||
| 238 | CS35L56_SDW_INT_MASK_CODEC_IRQ); | ||
| 239 | |||
| 240 | pm_runtime_put_autosuspend(cs35l56->dev); | ||
| 241 | } | ||
| 242 | |||
| 243 | static int cs35l56_sdw_read_prop(struct sdw_slave *peripheral) | ||
| 244 | { | ||
| 245 | struct cs35l56_private *cs35l56 = dev_get_drvdata(&peripheral->dev); | ||
| 246 | struct sdw_slave_prop *prop = &peripheral->prop; | ||
| 247 | struct sdw_dpn_prop *ports; | ||
| 248 | |||
| 249 | ports = devm_kcalloc(cs35l56->dev, 2, sizeof(*ports), GFP_KERNEL); | ||
| 250 | if (!ports) | ||
| 251 | return -ENOMEM; | ||
| 252 | |||
| 253 | prop->source_ports = BIT(CS35L56_SDW1_CAPTURE_PORT); | ||
| 254 | prop->sink_ports = BIT(CS35L56_SDW1_PLAYBACK_PORT); | ||
| 255 | prop->paging_support = true; | ||
| 256 | prop->clk_stop_mode1 = false; | ||
| 257 | prop->quirks = SDW_SLAVE_QUIRKS_INVALID_INITIAL_PARITY; | ||
| 258 | prop->scp_int1_mask = SDW_SCP_INT1_BUS_CLASH | SDW_SCP_INT1_PARITY | SDW_SCP_INT1_IMPL_DEF; | ||
| 259 | |||
| 260 | /* DP1 - playback */ | ||
| 261 | ports[0].num = CS35L56_SDW1_PLAYBACK_PORT; | ||
| 262 | ports[0].type = SDW_DPN_FULL; | ||
| 263 | ports[0].ch_prep_timeout = 10; | ||
| 264 | prop->sink_dpn_prop = &ports[0]; | ||
| 265 | |||
| 266 | /* DP3 - capture */ | ||
| 267 | ports[1].num = CS35L56_SDW1_CAPTURE_PORT; | ||
| 268 | ports[1].type = SDW_DPN_FULL; | ||
| 269 | ports[1].ch_prep_timeout = 10; | ||
| 270 | prop->src_dpn_prop = &ports[1]; | ||
| 271 | |||
| 272 | return 0; | ||
| 273 | } | ||
| 274 | |||
| 275 | static int cs35l56_sdw_update_status(struct sdw_slave *peripheral, | ||
| 276 | enum sdw_slave_status status) | ||
| 277 | { | ||
| 278 | struct cs35l56_private *cs35l56 = dev_get_drvdata(&peripheral->dev); | ||
| 279 | |||
| 280 | switch (status) { | ||
| 281 | case SDW_SLAVE_ATTACHED: | ||
| 282 | dev_dbg(cs35l56->dev, "%s: ATTACHED\n", __func__); | ||
| 283 | if (cs35l56->sdw_attached) | ||
| 284 | break; | ||
| 285 | |||
| 286 | if (!cs35l56->init_done || cs35l56->soft_resetting) | ||
| 287 | cs35l56_sdw_init(peripheral); | ||
| 288 | |||
| 289 | cs35l56->sdw_attached = true; | ||
| 290 | break; | ||
| 291 | case SDW_SLAVE_UNATTACHED: | ||
| 292 | dev_dbg(cs35l56->dev, "%s: UNATTACHED\n", __func__); | ||
| 293 | cs35l56->sdw_attached = false; | ||
| 294 | break; | ||
| 295 | default: | ||
| 296 | break; | ||
| 297 | } | ||
| 298 | |||
| 299 | return 0; | ||
| 300 | } | ||
| 301 | |||
| 302 | static int cs35l56_a1_kick_divider(struct cs35l56_private *cs35l56, | ||
| 303 | struct sdw_slave *peripheral) | ||
| 304 | { | ||
| 305 | unsigned int curr_scale_reg, next_scale_reg; | ||
| 306 | int curr_scale, next_scale, ret; | ||
| 307 | |||
| 308 | if (!cs35l56->init_done) | ||
| 309 | return 0; | ||
| 310 | |||
| 311 | if (peripheral->bus->params.curr_bank) { | ||
| 312 | curr_scale_reg = SDW_SCP_BUSCLOCK_SCALE_B1; | ||
| 313 | next_scale_reg = SDW_SCP_BUSCLOCK_SCALE_B0; | ||
| 314 | } else { | ||
| 315 | curr_scale_reg = SDW_SCP_BUSCLOCK_SCALE_B0; | ||
| 316 | next_scale_reg = SDW_SCP_BUSCLOCK_SCALE_B1; | ||
| 317 | } | ||
| 318 | |||
| 319 | /* | ||
| 320 | * Current clock scale value must be different to new value. | ||
| 321 | * Modify current to guarantee this. If next still has the dummy | ||
| 322 | * value we wrote when it was current, the core code has not set | ||
| 323 | * a new scale so restore its original good value | ||
| 324 | */ | ||
| 325 | curr_scale = sdw_read_no_pm(peripheral, curr_scale_reg); | ||
| 326 | if (curr_scale < 0) { | ||
| 327 | dev_err(cs35l56->dev, "Failed to read current clock scale: %d\n", curr_scale); | ||
| 328 | return curr_scale; | ||
| 329 | } | ||
| 330 | |||
| 331 | next_scale = sdw_read_no_pm(peripheral, next_scale_reg); | ||
| 332 | if (next_scale < 0) { | ||
| 333 | dev_err(cs35l56->dev, "Failed to read next clock scale: %d\n", next_scale); | ||
| 334 | return next_scale; | ||
| 335 | } | ||
| 336 | |||
| 337 | if (next_scale == CS35L56_SDW_INVALID_BUS_SCALE) { | ||
| 338 | next_scale = cs35l56->old_sdw_clock_scale; | ||
| 339 | ret = sdw_write_no_pm(peripheral, next_scale_reg, next_scale); | ||
| 340 | if (ret < 0) { | ||
| 341 | dev_err(cs35l56->dev, "Failed to modify current clock scale: %d\n", ret); | ||
| 342 | return ret; | ||
| 343 | } | ||
| 344 | } | ||
| 345 | |||
| 346 | cs35l56->old_sdw_clock_scale = curr_scale; | ||
| 347 | ret = sdw_write_no_pm(peripheral, curr_scale_reg, CS35L56_SDW_INVALID_BUS_SCALE); | ||
| 348 | if (ret < 0) { | ||
| 349 | dev_err(cs35l56->dev, "Failed to modify current clock scale: %d\n", ret); | ||
| 350 | return ret; | ||
| 351 | } | ||
| 352 | |||
| 353 | dev_dbg(cs35l56->dev, "Next bus scale: %#x\n", next_scale); | ||
| 354 | |||
| 355 | return 0; | ||
| 356 | } | ||
| 357 | |||
| 358 | static int cs35l56_sdw_bus_config(struct sdw_slave *peripheral, | ||
| 359 | struct sdw_bus_params *params) | ||
| 360 | { | ||
| 361 | struct cs35l56_private *cs35l56 = dev_get_drvdata(&peripheral->dev); | ||
| 362 | int sclk; | ||
| 363 | |||
| 364 | 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 | |||
| 367 | if (cs35l56->rev < 0xb0) | ||
| 368 | return cs35l56_a1_kick_divider(cs35l56, peripheral); | ||
| 369 | |||
| 370 | return 0; | ||
| 371 | } | ||
| 372 | |||
| 373 | static int __maybe_unused cs35l56_sdw_clk_stop(struct sdw_slave *peripheral, | ||
| 374 | enum sdw_clk_stop_mode mode, | ||
| 375 | enum sdw_clk_stop_type type) | ||
| 376 | { | ||
| 377 | struct cs35l56_private *cs35l56 = dev_get_drvdata(&peripheral->dev); | ||
| 378 | |||
| 379 | dev_dbg(cs35l56->dev, "%s: mode:%d type:%d\n", __func__, mode, type); | ||
| 380 | |||
| 381 | return 0; | ||
| 382 | } | ||
| 383 | |||
| 384 | static const struct sdw_slave_ops cs35l56_sdw_ops = { | ||
| 385 | .read_prop = cs35l56_sdw_read_prop, | ||
| 386 | .interrupt_callback = cs35l56_sdw_interrupt, | ||
| 387 | .update_status = cs35l56_sdw_update_status, | ||
| 388 | .bus_config = cs35l56_sdw_bus_config, | ||
| 389 | #ifdef DEBUG | ||
| 390 | .clk_stop = cs35l56_sdw_clk_stop, | ||
| 391 | #endif | ||
| 392 | }; | ||
| 393 | |||
| 394 | static int __maybe_unused cs35l56_sdw_handle_unattach(struct cs35l56_private *cs35l56) | ||
| 395 | { | ||
| 396 | struct sdw_slave *peripheral = cs35l56->sdw_peripheral; | ||
| 397 | |||
| 398 | if (peripheral->unattach_request) { | ||
| 399 | /* Cannot access registers until bus is re-initialized. */ | ||
| 400 | dev_dbg(cs35l56->dev, "Wait for initialization_complete\n"); | ||
| 401 | if (!wait_for_completion_timeout(&peripheral->initialization_complete, | ||
| 402 | msecs_to_jiffies(5000))) { | ||
| 403 | dev_err(cs35l56->dev, "initialization_complete timed out\n"); | ||
| 404 | return -ETIMEDOUT; | ||
| 405 | } | ||
| 406 | |||
| 407 | peripheral->unattach_request = 0; | ||
| 408 | |||
| 409 | /* | ||
| 410 | * Don't call regcache_mark_dirty(), we can't be sure that the | ||
| 411 | * Manager really did issue a Bus Reset. | ||
| 412 | */ | ||
| 413 | } | ||
| 414 | |||
| 415 | return 0; | ||
| 416 | } | ||
| 417 | |||
| 418 | static int __maybe_unused cs35l56_sdw_runtime_suspend(struct device *dev) | ||
| 419 | { | ||
| 420 | struct cs35l56_private *cs35l56 = dev_get_drvdata(dev); | ||
| 421 | |||
| 422 | if (!cs35l56->init_done) | ||
| 423 | return 0; | ||
| 424 | |||
| 425 | return cs35l56_runtime_suspend(dev); | ||
| 426 | } | ||
| 427 | |||
| 428 | static int __maybe_unused cs35l56_sdw_runtime_resume(struct device *dev) | ||
| 429 | { | ||
| 430 | struct cs35l56_private *cs35l56 = dev_get_drvdata(dev); | ||
| 431 | int ret; | ||
| 432 | |||
| 433 | dev_dbg(dev, "Runtime resume\n"); | ||
| 434 | |||
| 435 | if (!cs35l56->init_done) | ||
| 436 | return 0; | ||
| 437 | |||
| 438 | ret = cs35l56_sdw_handle_unattach(cs35l56); | ||
| 439 | if (ret < 0) | ||
| 440 | return ret; | ||
| 441 | |||
| 442 | ret = cs35l56_runtime_resume_common(cs35l56); | ||
| 443 | if (ret) | ||
| 444 | return ret; | ||
| 445 | |||
| 446 | /* Re-enable SoundWire interrupts */ | ||
| 447 | sdw_write_no_pm(cs35l56->sdw_peripheral, CS35L56_SDW_GEN_INT_MASK_1, | ||
| 448 | CS35L56_SDW_INT_MASK_CODEC_IRQ); | ||
| 449 | |||
| 450 | return 0; | ||
| 451 | } | ||
| 452 | |||
| 453 | static int __maybe_unused cs35l56_sdw_system_suspend(struct device *dev) | ||
| 454 | { | ||
| 455 | struct cs35l56_private *cs35l56 = dev_get_drvdata(dev); | ||
| 456 | |||
| 457 | if (!cs35l56->init_done) | ||
| 458 | return 0; | ||
| 459 | |||
| 460 | /* | ||
| 461 | * Disable SoundWire interrupts. | ||
| 462 | * Flush - don't cancel because that could leave an unbalanced pm_runtime_get. | ||
| 463 | */ | ||
| 464 | cs35l56->sdw_irq_no_unmask = true; | ||
| 465 | flush_work(&cs35l56->sdw_irq_work); | ||
| 466 | |||
| 467 | /* Mask interrupts and flush in case sdw_irq_work was queued again */ | ||
| 468 | sdw_write_no_pm(cs35l56->sdw_peripheral, CS35L56_SDW_GEN_INT_MASK_1, 0); | ||
| 469 | sdw_read_no_pm(cs35l56->sdw_peripheral, CS35L56_SDW_GEN_INT_STAT_1); | ||
| 470 | sdw_write_no_pm(cs35l56->sdw_peripheral, CS35L56_SDW_GEN_INT_STAT_1, 0xFF); | ||
| 471 | flush_work(&cs35l56->sdw_irq_work); | ||
| 472 | |||
| 473 | return cs35l56_system_suspend(dev); | ||
| 474 | } | ||
| 475 | |||
| 476 | static int __maybe_unused cs35l56_sdw_system_resume(struct device *dev) | ||
| 477 | { | ||
| 478 | struct cs35l56_private *cs35l56 = dev_get_drvdata(dev); | ||
| 479 | |||
| 480 | cs35l56->sdw_irq_no_unmask = false; | ||
| 481 | /* runtime_resume re-enables the interrupt */ | ||
| 482 | |||
| 483 | return cs35l56_system_resume(dev); | ||
| 484 | } | ||
| 485 | |||
| 486 | static int cs35l56_sdw_probe(struct sdw_slave *peripheral, const struct sdw_device_id *id) | ||
| 487 | { | ||
| 488 | struct device *dev = &peripheral->dev; | ||
| 489 | struct cs35l56_private *cs35l56; | ||
| 490 | int ret; | ||
| 491 | |||
| 492 | cs35l56 = devm_kzalloc(dev, sizeof(*cs35l56), GFP_KERNEL); | ||
| 493 | if (!cs35l56) | ||
| 494 | return -ENOMEM; | ||
| 495 | |||
| 496 | cs35l56->dev = dev; | ||
| 497 | cs35l56->sdw_peripheral = peripheral; | ||
| 498 | INIT_WORK(&cs35l56->sdw_irq_work, cs35l56_sdw_irq_work); | ||
| 499 | |||
| 500 | dev_set_drvdata(dev, cs35l56); | ||
| 501 | |||
| 502 | cs35l56->regmap = devm_regmap_init(dev, &cs35l56_regmap_bus_sdw, | ||
| 503 | peripheral, &cs35l56_regmap_sdw); | ||
| 504 | if (IS_ERR(cs35l56->regmap)) { | ||
| 505 | ret = PTR_ERR(cs35l56->regmap); | ||
| 506 | return dev_err_probe(dev, ret, "Failed to allocate register map\n"); | ||
| 507 | } | ||
| 508 | |||
| 509 | /* Start in cache-only until device is enumerated */ | ||
| 510 | regcache_cache_only(cs35l56->regmap, true); | ||
| 511 | |||
| 512 | ret = cs35l56_common_probe(cs35l56); | ||
| 513 | if (ret != 0) | ||
| 514 | return ret; | ||
| 515 | |||
| 516 | return 0; | ||
| 517 | } | ||
| 518 | |||
| 519 | static int cs35l56_sdw_remove(struct sdw_slave *peripheral) | ||
| 520 | { | ||
| 521 | struct cs35l56_private *cs35l56 = dev_get_drvdata(&peripheral->dev); | ||
| 522 | |||
| 523 | /* Disable SoundWire interrupts */ | ||
| 524 | cs35l56->sdw_irq_no_unmask = true; | ||
| 525 | cancel_work_sync(&cs35l56->sdw_irq_work); | ||
| 526 | sdw_write_no_pm(peripheral, CS35L56_SDW_GEN_INT_MASK_1, 0); | ||
| 527 | sdw_read_no_pm(peripheral, CS35L56_SDW_GEN_INT_STAT_1); | ||
| 528 | sdw_write_no_pm(peripheral, CS35L56_SDW_GEN_INT_STAT_1, 0xFF); | ||
| 529 | |||
| 530 | cs35l56_remove(cs35l56); | ||
| 531 | |||
| 532 | return 0; | ||
| 533 | } | ||
| 534 | |||
| 535 | static const struct dev_pm_ops cs35l56_sdw_pm = { | ||
| 536 | SET_RUNTIME_PM_OPS(cs35l56_sdw_runtime_suspend, cs35l56_sdw_runtime_resume, NULL) | ||
| 537 | SYSTEM_SLEEP_PM_OPS(cs35l56_sdw_system_suspend, cs35l56_sdw_system_resume) | ||
| 538 | LATE_SYSTEM_SLEEP_PM_OPS(cs35l56_system_suspend_late, cs35l56_system_resume_early) | ||
| 539 | /* NOIRQ stage not needed, SoundWire doesn't use a hard IRQ */ | ||
| 540 | }; | ||
| 541 | |||
| 542 | static const struct sdw_device_id cs35l56_sdw_id[] = { | ||
| 543 | SDW_SLAVE_ENTRY(0x01FA, 0x3556, 0), | ||
| 544 | {}, | ||
| 545 | }; | ||
| 546 | MODULE_DEVICE_TABLE(sdw, cs35l56_sdw_id); | ||
| 547 | |||
| 548 | static struct sdw_driver cs35l56_sdw_driver = { | ||
| 549 | .driver = { | ||
| 550 | .name = "cs35l56", | ||
| 551 | .pm = &cs35l56_sdw_pm, | ||
| 552 | }, | ||
| 553 | .probe = cs35l56_sdw_probe, | ||
| 554 | .remove = cs35l56_sdw_remove, | ||
| 555 | .ops = &cs35l56_sdw_ops, | ||
| 556 | .id_table = cs35l56_sdw_id, | ||
| 557 | }; | ||
| 558 | |||
| 559 | module_sdw_driver(cs35l56_sdw_driver); | ||
| 560 | |||
| 561 | MODULE_DESCRIPTION("ASoC CS35L56 SoundWire driver"); | ||
| 562 | MODULE_IMPORT_NS(SND_SOC_CS35L56_CORE); | ||
| 563 | MODULE_IMPORT_NS(SND_SOC_CS35L56_SHARED); | ||
| 564 | MODULE_AUTHOR("Richard Fitzgerald <rf@opensource.cirrus.com>"); | ||
| 565 | MODULE_AUTHOR("Simon Trimmer <simont@opensource.cirrus.com>"); | ||
| 566 | MODULE_LICENSE("GPL"); | ||
| @@ -0,0 +1,362 @@ | |||
| 1 | // SPDX-License-Identifier: GPL-2.0-only | ||
| 2 | // | ||
| 3 | // Components shared between ASoC and HDA CS35L56 drivers | ||
| 4 | // | ||
| 5 | // Copyright (C) 2023 Cirrus Logic, Inc. and | ||
| 6 | // Cirrus Logic International Semiconductor Ltd. | ||
| 7 | |||
| 8 | #include <linux/regmap.h> | ||
| 9 | #include <linux/regulator/consumer.h> | ||
| 10 | #include <linux/types.h> | ||
| 11 | |||
| 12 | #include "cs35l56.h" | ||
| 13 | |||
| 14 | static const struct reg_default cs35l56_reg_defaults[] = { | ||
| 15 | { CS35L56_ASP1_ENABLES1, 0x00000000 }, | ||
| 16 | { CS35L56_ASP1_CONTROL1, 0x00000028 }, | ||
| 17 | { CS35L56_ASP1_CONTROL2, 0x18180200 }, | ||
| 18 | { CS35L56_ASP1_CONTROL3, 0x00000002 }, | ||
| 19 | { CS35L56_ASP1_FRAME_CONTROL1, 0x03020100 }, | ||
| 20 | { CS35L56_ASP1_FRAME_CONTROL5, 0x00020100 }, | ||
| 21 | { CS35L56_ASP1_DATA_CONTROL1, 0x00000018 }, | ||
| 22 | { CS35L56_ASP1_DATA_CONTROL5, 0x00000018 }, | ||
| 23 | { CS35L56_ASP1TX1_INPUT, 0x00000018 }, | ||
| 24 | { CS35L56_ASP1TX2_INPUT, 0x00000019 }, | ||
| 25 | { CS35L56_ASP1TX3_INPUT, 0x00000020 }, | ||
| 26 | { CS35L56_ASP1TX4_INPUT, 0x00000028 }, | ||
| 27 | { CS35L56_SWIRE_DP3_CH1_INPUT, 0x00000018 }, | ||
| 28 | { CS35L56_SWIRE_DP3_CH2_INPUT, 0x00000019 }, | ||
| 29 | { CS35L56_SWIRE_DP3_CH3_INPUT, 0x00000029 }, | ||
| 30 | { CS35L56_SWIRE_DP3_CH4_INPUT, 0x00000028 }, | ||
| 31 | { CS35L56_IRQ1_CFG, 0x00000000 }, | ||
| 32 | { CS35L56_IRQ1_MASK_1, 0x83ffffff }, | ||
| 33 | { CS35L56_IRQ1_MASK_2, 0xffff7fff }, | ||
| 34 | { CS35L56_IRQ1_MASK_4, 0xe0ffffff }, | ||
| 35 | { CS35L56_IRQ1_MASK_8, 0xfc000fff }, | ||
| 36 | { CS35L56_IRQ1_MASK_18, 0x1f7df0ff }, | ||
| 37 | { CS35L56_IRQ1_MASK_20, 0x15c00000 }, | ||
| 38 | /* CS35L56_MAIN_RENDER_USER_MUTE - soft register, no default */ | ||
| 39 | /* CS35L56_MAIN_RENDER_USER_VOLUME - soft register, no default */ | ||
| 40 | /* CS35L56_MAIN_POSTURE_NUMBER - soft register, no default */ | ||
| 41 | }; | ||
| 42 | |||
| 43 | static bool cs35l56_is_dsp_memory(unsigned int reg) | ||
| 44 | { | ||
| 45 | switch (reg) { | ||
| 46 | case CS35L56_DSP1_XMEM_PACKED_0 ... CS35L56_DSP1_XMEM_PACKED_6143: | ||
| 47 | case CS35L56_DSP1_XMEM_UNPACKED32_0 ... CS35L56_DSP1_XMEM_UNPACKED32_4095: | ||
| 48 | case CS35L56_DSP1_XMEM_UNPACKED24_0 ... CS35L56_DSP1_XMEM_UNPACKED24_8191: | ||
| 49 | case CS35L56_DSP1_YMEM_PACKED_0 ... CS35L56_DSP1_YMEM_PACKED_4604: | ||
| 50 | case CS35L56_DSP1_YMEM_UNPACKED32_0 ... CS35L56_DSP1_YMEM_UNPACKED32_3070: | ||
| 51 | case CS35L56_DSP1_YMEM_UNPACKED24_0 ... CS35L56_DSP1_YMEM_UNPACKED24_6141: | ||
| 52 | case CS35L56_DSP1_PMEM_0 ... CS35L56_DSP1_PMEM_5114: | ||
| 53 | return true; | ||
| 54 | default: | ||
| 55 | return false; | ||
| 56 | } | ||
| 57 | } | ||
| 58 | |||
| 59 | static bool cs35l56_readable_reg(struct device *dev, unsigned int reg) | ||
| 60 | { | ||
| 61 | switch (reg) { | ||
| 62 | case CS35L56_DEVID: | ||
| 63 | case CS35L56_REVID: | ||
| 64 | case CS35L56_RELID: | ||
| 65 | case CS35L56_OTPID: | ||
| 66 | case CS35L56_SFT_RESET: | ||
| 67 | case CS35L56_GLOBAL_ENABLES: | ||
| 68 | case CS35L56_BLOCK_ENABLES: | ||
| 69 | case CS35L56_BLOCK_ENABLES2: | ||
| 70 | case CS35L56_REFCLK_INPUT: | ||
| 71 | case CS35L56_GLOBAL_SAMPLE_RATE: | ||
| 72 | case CS35L56_ASP1_ENABLES1: | ||
| 73 | case CS35L56_ASP1_CONTROL1: | ||
| 74 | case CS35L56_ASP1_CONTROL2: | ||
| 75 | case CS35L56_ASP1_CONTROL3: | ||
| 76 | case CS35L56_ASP1_FRAME_CONTROL1: | ||
| 77 | case CS35L56_ASP1_FRAME_CONTROL5: | ||
| 78 | case CS35L56_ASP1_DATA_CONTROL1: | ||
| 79 | case CS35L56_ASP1_DATA_CONTROL5: | ||
| 80 | case CS35L56_DACPCM1_INPUT: | ||
| 81 | case CS35L56_DACPCM2_INPUT: | ||
| 82 | case CS35L56_ASP1TX1_INPUT: | ||
| 83 | case CS35L56_ASP1TX2_INPUT: | ||
| 84 | case CS35L56_ASP1TX3_INPUT: | ||
| 85 | case CS35L56_ASP1TX4_INPUT: | ||
| 86 | case CS35L56_DSP1RX1_INPUT: | ||
| 87 | case CS35L56_DSP1RX2_INPUT: | ||
| 88 | case CS35L56_SWIRE_DP3_CH1_INPUT: | ||
| 89 | case CS35L56_SWIRE_DP3_CH2_INPUT: | ||
| 90 | case CS35L56_SWIRE_DP3_CH3_INPUT: | ||
| 91 | case CS35L56_SWIRE_DP3_CH4_INPUT: | ||
| 92 | case CS35L56_IRQ1_CFG: | ||
| 93 | case CS35L56_IRQ1_STATUS: | ||
| 94 | case CS35L56_IRQ1_EINT_1 ... CS35L56_IRQ1_EINT_8: | ||
| 95 | case CS35L56_IRQ1_EINT_18: | ||
| 96 | case CS35L56_IRQ1_EINT_20: | ||
| 97 | case CS35L56_IRQ1_MASK_1: | ||
| 98 | case CS35L56_IRQ1_MASK_2: | ||
| 99 | case CS35L56_IRQ1_MASK_4: | ||
| 100 | case CS35L56_IRQ1_MASK_8: | ||
| 101 | case CS35L56_IRQ1_MASK_18: | ||
| 102 | case CS35L56_IRQ1_MASK_20: | ||
| 103 | case CS35L56_DSP_VIRTUAL1_MBOX_1: | ||
| 104 | case CS35L56_DSP_VIRTUAL1_MBOX_2: | ||
| 105 | case CS35L56_DSP_VIRTUAL1_MBOX_3: | ||
| 106 | case CS35L56_DSP_VIRTUAL1_MBOX_4: | ||
| 107 | case CS35L56_DSP_VIRTUAL1_MBOX_5: | ||
| 108 | case CS35L56_DSP_VIRTUAL1_MBOX_6: | ||
| 109 | case CS35L56_DSP_VIRTUAL1_MBOX_7: | ||
| 110 | case CS35L56_DSP_VIRTUAL1_MBOX_8: | ||
| 111 | case CS35L56_DSP_RESTRICT_STS1: | ||
| 112 | case CS35L56_DSP1_SYS_INFO_ID ... CS35L56_DSP1_SYS_INFO_END: | ||
| 113 | case CS35L56_DSP1_AHBM_WINDOW_DEBUG_0: | ||
| 114 | case CS35L56_DSP1_AHBM_WINDOW_DEBUG_1: | ||
| 115 | case CS35L56_DSP1_SCRATCH1: | ||
| 116 | case CS35L56_DSP1_SCRATCH2: | ||
| 117 | case CS35L56_DSP1_SCRATCH3: | ||
| 118 | case CS35L56_DSP1_SCRATCH4: | ||
| 119 | return true; | ||
| 120 | default: | ||
| 121 | return cs35l56_is_dsp_memory(reg); | ||
| 122 | } | ||
| 123 | } | ||
| 124 | |||
| 125 | static bool cs35l56_precious_reg(struct device *dev, unsigned int reg) | ||
| 126 | { | ||
| 127 | switch (reg) { | ||
| 128 | case CS35L56_DSP1_XMEM_PACKED_0 ... CS35L56_DSP1_XMEM_PACKED_6143: | ||
| 129 | case CS35L56_DSP1_YMEM_PACKED_0 ... CS35L56_DSP1_YMEM_PACKED_4604: | ||
| 130 | case CS35L56_DSP1_PMEM_0 ... CS35L56_DSP1_PMEM_5114: | ||
| 131 | return true; | ||
| 132 | default: | ||
| 133 | return false; | ||
| 134 | } | ||
| 135 | } | ||
| 136 | |||
| 137 | static bool cs35l56_volatile_reg(struct device *dev, unsigned int reg) | ||
| 138 | { | ||
| 139 | switch (reg) { | ||
| 140 | case CS35L56_DEVID: | ||
| 141 | case CS35L56_REVID: | ||
| 142 | case CS35L56_RELID: | ||
| 143 | case CS35L56_OTPID: | ||
| 144 | case CS35L56_SFT_RESET: | ||
| 145 | case CS35L56_GLOBAL_ENABLES: /* owned by firmware */ | ||
| 146 | case CS35L56_BLOCK_ENABLES: /* owned by firmware */ | ||
| 147 | case CS35L56_BLOCK_ENABLES2: /* owned by firmware */ | ||
| 148 | case CS35L56_REFCLK_INPUT: /* owned by firmware */ | ||
| 149 | case CS35L56_GLOBAL_SAMPLE_RATE: /* owned by firmware */ | ||
| 150 | case CS35L56_DACPCM1_INPUT: /* owned by firmware */ | ||
| 151 | case CS35L56_DACPCM2_INPUT: /* owned by firmware */ | ||
| 152 | case CS35L56_DSP1RX1_INPUT: /* owned by firmware */ | ||
| 153 | case CS35L56_DSP1RX2_INPUT: /* owned by firmware */ | ||
| 154 | case CS35L56_IRQ1_STATUS: | ||
| 155 | case CS35L56_IRQ1_EINT_1 ... CS35L56_IRQ1_EINT_8: | ||
| 156 | case CS35L56_IRQ1_EINT_18: | ||
| 157 | case CS35L56_IRQ1_EINT_20: | ||
| 158 | case CS35L56_DSP_VIRTUAL1_MBOX_1: | ||
| 159 | case CS35L56_DSP_VIRTUAL1_MBOX_2: | ||
| 160 | case CS35L56_DSP_VIRTUAL1_MBOX_3: | ||
| 161 | case CS35L56_DSP_VIRTUAL1_MBOX_4: | ||
| 162 | case CS35L56_DSP_VIRTUAL1_MBOX_5: | ||
| 163 | case CS35L56_DSP_VIRTUAL1_MBOX_6: | ||
| 164 | case CS35L56_DSP_VIRTUAL1_MBOX_7: | ||
| 165 | case CS35L56_DSP_VIRTUAL1_MBOX_8: | ||
| 166 | case CS35L56_DSP_RESTRICT_STS1: | ||
| 167 | case CS35L56_DSP1_SYS_INFO_ID ... CS35L56_DSP1_SYS_INFO_END: | ||
| 168 | case CS35L56_DSP1_AHBM_WINDOW_DEBUG_0: | ||
| 169 | case CS35L56_DSP1_AHBM_WINDOW_DEBUG_1: | ||
| 170 | case CS35L56_DSP1_SCRATCH1: | ||
| 171 | case CS35L56_DSP1_SCRATCH2: | ||
| 172 | case CS35L56_DSP1_SCRATCH3: | ||
| 173 | case CS35L56_DSP1_SCRATCH4: | ||
| 174 | return true; | ||
| 175 | case CS35L56_MAIN_RENDER_USER_MUTE: | ||
| 176 | case CS35L56_MAIN_RENDER_USER_VOLUME: | ||
| 177 | case CS35L56_MAIN_POSTURE_NUMBER: | ||
| 178 | return false; | ||
| 179 | default: | ||
| 180 | return cs35l56_is_dsp_memory(reg); | ||
| 181 | } | ||
| 182 | } | ||
| 183 | |||
| 184 | static const u32 cs35l56_firmware_registers[] = { | ||
| 185 | CS35L56_MAIN_RENDER_USER_MUTE, | ||
| 186 | CS35L56_MAIN_RENDER_USER_VOLUME, | ||
| 187 | CS35L56_MAIN_POSTURE_NUMBER, | ||
| 188 | }; | ||
| 189 | |||
| 190 | void cs35l56_reread_firmware_registers(struct device *dev, struct regmap *regmap) | ||
| 191 | { | ||
| 192 | int i; | ||
| 193 | unsigned int val; | ||
| 194 | |||
| 195 | for (i = 0; i < ARRAY_SIZE(cs35l56_firmware_registers); i++) { | ||
| 196 | regmap_read(regmap, cs35l56_firmware_registers[i], &val); | ||
| 197 | dev_dbg(dev, "%s: %d: %#x: %#x\n", __func__, | ||
| 198 | i, cs35l56_firmware_registers[i], val); | ||
| 199 | } | ||
| 200 | } | ||
| 201 | EXPORT_SYMBOL_NS_GPL(cs35l56_reread_firmware_registers, SND_SOC_CS35L56_SHARED); | ||
| 202 | |||
| 203 | const struct cs_dsp_region cs35l56_dsp1_regions[] = { | ||
| 204 | { .type = WMFW_HALO_PM_PACKED, .base = CS35L56_DSP1_PMEM_0 }, | ||
| 205 | { .type = WMFW_HALO_XM_PACKED, .base = CS35L56_DSP1_XMEM_PACKED_0 }, | ||
| 206 | { .type = WMFW_HALO_YM_PACKED, .base = CS35L56_DSP1_YMEM_PACKED_0 }, | ||
| 207 | { .type = WMFW_ADSP2_XM, .base = CS35L56_DSP1_XMEM_UNPACKED24_0 }, | ||
| 208 | { .type = WMFW_ADSP2_YM, .base = CS35L56_DSP1_YMEM_UNPACKED24_0 }, | ||
| 209 | }; | ||
| 210 | EXPORT_SYMBOL_NS_GPL(cs35l56_dsp1_regions, SND_SOC_CS35L56_SHARED); | ||
| 211 | |||
| 212 | static const u32 cs35l56_bclk_valid_for_pll_freq_table[] = { | ||
| 213 | [0x0C] = 128000, | ||
| 214 | [0x0F] = 256000, | ||
| 215 | [0x11] = 384000, | ||
| 216 | [0x12] = 512000, | ||
| 217 | [0x15] = 768000, | ||
| 218 | [0x17] = 1024000, | ||
| 219 | [0x1A] = 1500000, | ||
| 220 | [0x1B] = 1536000, | ||
| 221 | [0x1C] = 2000000, | ||
| 222 | [0x1D] = 2048000, | ||
| 223 | [0x1E] = 2400000, | ||
| 224 | [0x20] = 3000000, | ||
| 225 | [0x21] = 3072000, | ||
| 226 | [0x23] = 4000000, | ||
| 227 | [0x24] = 4096000, | ||
| 228 | [0x25] = 4800000, | ||
| 229 | [0x27] = 6000000, | ||
| 230 | [0x28] = 6144000, | ||
| 231 | [0x29] = 6250000, | ||
| 232 | [0x2A] = 6400000, | ||
| 233 | [0x2E] = 8000000, | ||
| 234 | [0x2F] = 8192000, | ||
| 235 | [0x30] = 9600000, | ||
| 236 | [0x32] = 12000000, | ||
| 237 | [0x33] = 12288000, | ||
| 238 | [0x37] = 13500000, | ||
| 239 | [0x38] = 19200000, | ||
| 240 | [0x39] = 22579200, | ||
| 241 | [0x3B] = 24576000, | ||
| 242 | }; | ||
| 243 | |||
| 244 | int cs35l56_get_bclk_freq_id(unsigned int freq) | ||
| 245 | { | ||
| 246 | int i; | ||
| 247 | |||
| 248 | if (freq == 0) | ||
| 249 | return -EINVAL; | ||
| 250 | |||
| 251 | /* The BCLK frequency must be a valid PLL REFCLK */ | ||
| 252 | for (i = 0; i < ARRAY_SIZE(cs35l56_bclk_valid_for_pll_freq_table); ++i) { | ||
| 253 | if (cs35l56_bclk_valid_for_pll_freq_table[i] == freq) | ||
| 254 | return i; | ||
| 255 | } | ||
| 256 | |||
| 257 | return -EINVAL; | ||
| 258 | } | ||
| 259 | EXPORT_SYMBOL_NS_GPL(cs35l56_get_bclk_freq_id, SND_SOC_CS35L56_SHARED); | ||
| 260 | |||
| 261 | static const char * const cs35l56_supplies[/* auto-sized */] = { | ||
| 262 | "VDD_P", | ||
| 263 | "VDD_IO", | ||
| 264 | "VDD_A", | ||
| 265 | }; | ||
| 266 | |||
| 267 | void cs35l56_fill_supply_names(struct regulator_bulk_data *data) | ||
| 268 | { | ||
| 269 | int i; | ||
| 270 | |||
| 271 | BUILD_BUG_ON(ARRAY_SIZE(cs35l56_supplies) != CS35L56_NUM_BULK_SUPPLIES); | ||
| 272 | for (i = 0; i < ARRAY_SIZE(cs35l56_supplies); i++) | ||
| 273 | data[i].supply = cs35l56_supplies[i]; | ||
| 274 | } | ||
| 275 | EXPORT_SYMBOL_NS_GPL(cs35l56_fill_supply_names, SND_SOC_CS35L56_SHARED); | ||
| 276 | |||
| 277 | const char * const cs35l56_tx_input_texts[] = { | ||
| 278 | "None", "ASP1RX1", "ASP1RX2", "VMON", "IMON", "ERRVOL", "CLASSH", | ||
| 279 | "VDDBMON", "VBSTMON", "DSP1TX1", "DSP1TX2", "DSP1TX3", "DSP1TX4", | ||
| 280 | "DSP1TX5", "DSP1TX6", "DSP1TX7", "DSP1TX8", "TEMPMON", | ||
| 281 | "INTERPOLATOR", "SDW1RX1", "SDW1RX2", | ||
| 282 | }; | ||
| 283 | EXPORT_SYMBOL_NS_GPL(cs35l56_tx_input_texts, SND_SOC_CS35L56_SHARED); | ||
| 284 | |||
| 285 | const unsigned int cs35l56_tx_input_values[] = { | ||
| 286 | CS35L56_INPUT_SRC_NONE, | ||
| 287 | CS35L56_INPUT_SRC_ASP1RX1, | ||
| 288 | CS35L56_INPUT_SRC_ASP1RX2, | ||
| 289 | CS35L56_INPUT_SRC_VMON, | ||
| 290 | CS35L56_INPUT_SRC_IMON, | ||
| 291 | CS35L56_INPUT_SRC_ERR_VOL, | ||
| 292 | CS35L56_INPUT_SRC_CLASSH, | ||
| 293 | CS35L56_INPUT_SRC_VDDBMON, | ||
| 294 | CS35L56_INPUT_SRC_VBSTMON, | ||
| 295 | CS35L56_INPUT_SRC_DSP1TX1, | ||
| 296 | CS35L56_INPUT_SRC_DSP1TX2, | ||
| 297 | CS35L56_INPUT_SRC_DSP1TX3, | ||
| 298 | CS35L56_INPUT_SRC_DSP1TX4, | ||
| 299 | CS35L56_INPUT_SRC_DSP1TX5, | ||
| 300 | CS35L56_INPUT_SRC_DSP1TX6, | ||
| 301 | CS35L56_INPUT_SRC_DSP1TX7, | ||
| 302 | CS35L56_INPUT_SRC_DSP1TX8, | ||
| 303 | CS35L56_INPUT_SRC_TEMPMON, | ||
| 304 | CS35L56_INPUT_SRC_INTERPOLATOR, | ||
| 305 | CS35L56_INPUT_SRC_SWIRE_DP1_CHANNEL1, | ||
| 306 | CS35L56_INPUT_SRC_SWIRE_DP1_CHANNEL2, | ||
| 307 | }; | ||
| 308 | EXPORT_SYMBOL_NS_GPL(cs35l56_tx_input_values, SND_SOC_CS35L56_SHARED); | ||
| 309 | |||
| 310 | struct regmap_config cs35l56_regmap_i2c = { | ||
| 311 | .reg_bits = 32, | ||
| 312 | .val_bits = 32, | ||
| 313 | .reg_stride = 4, | ||
| 314 | .reg_format_endian = REGMAP_ENDIAN_BIG, | ||
| 315 | .val_format_endian = REGMAP_ENDIAN_BIG, | ||
| 316 | .max_register = CS35L56_DSP1_PMEM_5114, | ||
| 317 | .reg_defaults = cs35l56_reg_defaults, | ||
| 318 | .num_reg_defaults = ARRAY_SIZE(cs35l56_reg_defaults), | ||
| 319 | .volatile_reg = cs35l56_volatile_reg, | ||
| 320 | .readable_reg = cs35l56_readable_reg, | ||
| 321 | .precious_reg = cs35l56_precious_reg, | ||
| 322 | .cache_type = REGCACHE_RBTREE, | ||
| 323 | }; | ||
| 324 | EXPORT_SYMBOL_NS_GPL(cs35l56_regmap_i2c, SND_SOC_CS35L56_SHARED); | ||
| 325 | |||
| 326 | struct regmap_config cs35l56_regmap_spi = { | ||
| 327 | .reg_bits = 32, | ||
| 328 | .val_bits = 32, | ||
| 329 | .pad_bits = 16, | ||
| 330 | .reg_stride = 4, | ||
| 331 | .reg_format_endian = REGMAP_ENDIAN_BIG, | ||
| 332 | .val_format_endian = REGMAP_ENDIAN_BIG, | ||
| 333 | .max_register = CS35L56_DSP1_PMEM_5114, | ||
| 334 | .reg_defaults = cs35l56_reg_defaults, | ||
| 335 | .num_reg_defaults = ARRAY_SIZE(cs35l56_reg_defaults), | ||
| 336 | .volatile_reg = cs35l56_volatile_reg, | ||
| 337 | .readable_reg = cs35l56_readable_reg, | ||
| 338 | .precious_reg = cs35l56_precious_reg, | ||
| 339 | .cache_type = REGCACHE_RBTREE, | ||
| 340 | }; | ||
| 341 | EXPORT_SYMBOL_NS_GPL(cs35l56_regmap_spi, SND_SOC_CS35L56_SHARED); | ||
| 342 | |||
| 343 | struct regmap_config cs35l56_regmap_sdw = { | ||
| 344 | .reg_bits = 32, | ||
| 345 | .val_bits = 32, | ||
| 346 | .reg_stride = 4, | ||
| 347 | .reg_format_endian = REGMAP_ENDIAN_LITTLE, | ||
| 348 | .val_format_endian = REGMAP_ENDIAN_BIG, | ||
| 349 | .max_register = CS35L56_DSP1_PMEM_5114, | ||
| 350 | .reg_defaults = cs35l56_reg_defaults, | ||
| 351 | .num_reg_defaults = ARRAY_SIZE(cs35l56_reg_defaults), | ||
| 352 | .volatile_reg = cs35l56_volatile_reg, | ||
| 353 | .readable_reg = cs35l56_readable_reg, | ||
| 354 | .precious_reg = cs35l56_precious_reg, | ||
| 355 | .cache_type = REGCACHE_RBTREE, | ||
| 356 | }; | ||
| 357 | EXPORT_SYMBOL_NS_GPL(cs35l56_regmap_sdw, SND_SOC_CS35L56_SHARED); | ||
| 358 | |||
| 359 | MODULE_DESCRIPTION("ASoC CS35L56 Shared"); | ||
| 360 | MODULE_AUTHOR("Richard Fitzgerald <rf@opensource.cirrus.com>"); | ||
| 361 | MODULE_AUTHOR("Simon Trimmer <simont@opensource.cirrus.com>"); | ||
| 362 | MODULE_LICENSE("GPL"); | ||
| @@ -0,0 +1,79 @@ | |||
| 1 | // SPDX-License-Identifier: GPL-2.0-only | ||
| 2 | // | ||
| 3 | // CS35L56 ALSA SoC audio driver SPI binding | ||
| 4 | // | ||
| 5 | // Copyright (C) 2023 Cirrus Logic, Inc. and | ||
| 6 | // Cirrus Logic International Semiconductor Ltd. | ||
| 7 | |||
| 8 | #include <linux/acpi.h> | ||
| 9 | #include <linux/module.h> | ||
| 10 | #include <linux/moduleparam.h> | ||
| 11 | #include <linux/regmap.h> | ||
| 12 | #include <linux/spi/spi.h> | ||
| 13 | #include <linux/types.h> | ||
| 14 | |||
| 15 | #include "cs35l56.h" | ||
| 16 | |||
| 17 | static int cs35l56_spi_probe(struct spi_device *spi) | ||
| 18 | { | ||
| 19 | const struct regmap_config *regmap_config = &cs35l56_regmap_spi; | ||
| 20 | struct cs35l56_private *cs35l56; | ||
| 21 | int ret; | ||
| 22 | |||
| 23 | cs35l56 = devm_kzalloc(&spi->dev, sizeof(struct cs35l56_private), GFP_KERNEL); | ||
| 24 | if (!cs35l56) | ||
| 25 | return -ENOMEM; | ||
| 26 | |||
| 27 | spi_set_drvdata(spi, cs35l56); | ||
| 28 | cs35l56->regmap = devm_regmap_init_spi(spi, regmap_config); | ||
| 29 | if (IS_ERR(cs35l56->regmap)) { | ||
| 30 | ret = PTR_ERR(cs35l56->regmap); | ||
| 31 | return dev_err_probe(&spi->dev, ret, "Failed to allocate register map\n"); | ||
| 32 | } | ||
| 33 | |||
| 34 | cs35l56->dev = &spi->dev; | ||
| 35 | |||
| 36 | ret = cs35l56_common_probe(cs35l56); | ||
| 37 | if (ret != 0) | ||
| 38 | return ret; | ||
| 39 | |||
| 40 | ret = cs35l56_init(cs35l56); | ||
| 41 | if (ret == 0) | ||
| 42 | ret = cs35l56_irq_request(cs35l56, spi->irq); | ||
| 43 | if (ret < 0) | ||
| 44 | cs35l56_remove(cs35l56); | ||
| 45 | |||
| 46 | return ret; | ||
| 47 | } | ||
| 48 | |||
| 49 | static void cs35l56_spi_remove(struct spi_device *spi) | ||
| 50 | { | ||
| 51 | struct cs35l56_private *cs35l56 = spi_get_drvdata(spi); | ||
| 52 | |||
| 53 | cs35l56_remove(cs35l56); | ||
| 54 | } | ||
| 55 | |||
| 56 | static const struct spi_device_id cs35l56_id_spi[] = { | ||
| 57 | { "cs35l56", 0 }, | ||
| 58 | {} | ||
| 59 | }; | ||
| 60 | MODULE_DEVICE_TABLE(spi, cs35l56_id_spi); | ||
| 61 | |||
| 62 | static struct spi_driver cs35l56_spi_driver = { | ||
| 63 | .driver = { | ||
| 64 | .name = "cs35l56", | ||
| 65 | .pm = &cs35l56_pm_ops_i2c_spi, | ||
| 66 | }, | ||
| 67 | .id_table = cs35l56_id_spi, | ||
| 68 | .probe = cs35l56_spi_probe, | ||
| 69 | .remove = cs35l56_spi_remove, | ||
| 70 | }; | ||
| 71 | |||
| 72 | module_spi_driver(cs35l56_spi_driver); | ||
| 73 | |||
| 74 | MODULE_DESCRIPTION("ASoC CS35L56 SPI driver"); | ||
| 75 | MODULE_IMPORT_NS(SND_SOC_CS35L56_CORE); | ||
| 76 | MODULE_IMPORT_NS(SND_SOC_CS35L56_SHARED); | ||
| 77 | MODULE_AUTHOR("Richard Fitzgerald <rf@opensource.cirrus.com>"); | ||
| 78 | MODULE_AUTHOR("Simon Trimmer <simont@opensource.cirrus.com>"); | ||
| 79 | MODULE_LICENSE("GPL"); | ||
| @@ -0,0 +1,1601 @@ | |||
| 1 | // SPDX-License-Identifier: GPL-2.0-only | ||
| 2 | // | ||
| 3 | // Driver for Cirrus Logic CS35L56 smart amp | ||
| 4 | // | ||
| 5 | // Copyright (C) 2023 Cirrus Logic, Inc. and | ||
| 6 | // Cirrus Logic International Semiconductor Ltd. | ||
| 7 | |||
| 8 | #include <linux/acpi.h> | ||
| 9 | #include <linux/completion.h> | ||
| 10 | #include <linux/debugfs.h> | ||
| 11 | #include <linux/delay.h> | ||
| 12 | #include <linux/err.h> | ||
| 13 | #include <linux/gpio/consumer.h> | ||
| 14 | #include <linux/interrupt.h> | ||
| 15 | #include <linux/math.h> | ||
| 16 | #include <linux/module.h> | ||
| 17 | #include <linux/pm.h> | ||
| 18 | #include <linux/pm_runtime.h> | ||
| 19 | #include <linux/regmap.h> | ||
| 20 | #include <linux/regulator/consumer.h> | ||
| 21 | #include <linux/slab.h> | ||
| 22 | #include <linux/soundwire/sdw.h> | ||
| 23 | #include <linux/types.h> | ||
| 24 | #include <linux/workqueue.h> | ||
| 25 | #include <sound/pcm.h> | ||
| 26 | #include <sound/pcm_params.h> | ||
| 27 | #include <sound/soc.h> | ||
| 28 | #include <sound/soc-dapm.h> | ||
| 29 | #include <sound/tlv.h> | ||
| 30 | |||
| 31 | #include "wm_adsp.h" | ||
| 32 | #include "cs35l56.h" | ||
| 33 | |||
| 34 | static int cs35l56_dsp_event(struct snd_soc_dapm_widget *w, | ||
| 35 | struct snd_kcontrol *kcontrol, int event); | ||
| 36 | |||
| 37 | static int cs35l56_mbox_send(struct cs35l56_private *cs35l56, unsigned int command) | ||
| 38 | { | ||
| 39 | unsigned int val; | ||
| 40 | int ret; | ||
| 41 | |||
| 42 | regmap_write(cs35l56->regmap, CS35L56_DSP_VIRTUAL1_MBOX_1, command); | ||
| 43 | ret = regmap_read_poll_timeout(cs35l56->regmap, CS35L56_DSP_VIRTUAL1_MBOX_1, | ||
| 44 | val, (val == 0), | ||
| 45 | CS35L56_MBOX_POLL_US, CS35L56_MBOX_TIMEOUT_US); | ||
| 46 | if (ret) { | ||
| 47 | dev_warn(cs35l56->dev, "MBOX command %#x failed: %d\n", command, ret); | ||
| 48 | return ret; | ||
| 49 | } | ||
| 50 | |||
| 51 | return 0; | ||
| 52 | } | ||
| 53 | |||
| 54 | static void cs35l56_wait_dsp_ready(struct cs35l56_private *cs35l56) | ||
| 55 | { | ||
| 56 | /* Wait for patching to complete */ | ||
| 57 | flush_work(&cs35l56->dsp_work); | ||
| 58 | } | ||
| 59 | |||
| 60 | static int cs35l56_dspwait_get_volsw(struct snd_kcontrol *kcontrol, | ||
| 61 | struct snd_ctl_elem_value *ucontrol) | ||
| 62 | { | ||
| 63 | struct snd_soc_component *component = snd_kcontrol_chip(kcontrol); | ||
| 64 | struct cs35l56_private *cs35l56 = snd_soc_component_get_drvdata(component); | ||
| 65 | |||
| 66 | cs35l56_wait_dsp_ready(cs35l56); | ||
| 67 | return snd_soc_get_volsw(kcontrol, ucontrol); | ||
| 68 | } | ||
| 69 | |||
| 70 | static int cs35l56_dspwait_put_volsw(struct snd_kcontrol *kcontrol, | ||
| 71 | struct snd_ctl_elem_value *ucontrol) | ||
| 72 | { | ||
| 73 | struct snd_soc_component *component = snd_kcontrol_chip(kcontrol); | ||
| 74 | struct cs35l56_private *cs35l56 = snd_soc_component_get_drvdata(component); | ||
| 75 | |||
| 76 | cs35l56_wait_dsp_ready(cs35l56); | ||
| 77 | return snd_soc_put_volsw(kcontrol, ucontrol); | ||
| 78 | } | ||
| 79 | |||
| 80 | static DECLARE_TLV_DB_SCALE(vol_tlv, -10000, 25, 0); | ||
| 81 | |||
| 82 | static const struct snd_kcontrol_new cs35l56_controls[] = { | ||
| 83 | SOC_SINGLE_EXT("Speaker Switch", | ||
| 84 | CS35L56_MAIN_RENDER_USER_MUTE, 0, 1, 1, | ||
| 85 | cs35l56_dspwait_get_volsw, cs35l56_dspwait_put_volsw), | ||
| 86 | SOC_SINGLE_S_EXT_TLV("Speaker Volume", | ||
| 87 | CS35L56_MAIN_RENDER_USER_VOLUME, | ||
| 88 | 6, -400, 400, 9, 0, | ||
| 89 | cs35l56_dspwait_get_volsw, | ||
| 90 | cs35l56_dspwait_put_volsw, | ||
| 91 | vol_tlv), | ||
| 92 | SOC_SINGLE_EXT("Posture Number", CS35L56_MAIN_POSTURE_NUMBER, | ||
| 93 | 0, 255, 0, | ||
| 94 | cs35l56_dspwait_get_volsw, cs35l56_dspwait_put_volsw), | ||
| 95 | }; | ||
| 96 | |||
| 97 | static SOC_VALUE_ENUM_SINGLE_DECL(cs35l56_asp1tx1_enum, | ||
| 98 | CS35L56_ASP1TX1_INPUT, | ||
| 99 | 0, CS35L56_ASP_TXn_SRC_MASK, | ||
| 100 | cs35l56_tx_input_texts, | ||
| 101 | cs35l56_tx_input_values); | ||
| 102 | |||
| 103 | static const struct snd_kcontrol_new asp1_tx1_mux = | ||
| 104 | SOC_DAPM_ENUM("ASP1TX1 SRC", cs35l56_asp1tx1_enum); | ||
| 105 | |||
| 106 | static SOC_VALUE_ENUM_SINGLE_DECL(cs35l56_asp1tx2_enum, | ||
| 107 | CS35L56_ASP1TX2_INPUT, | ||
| 108 | 0, CS35L56_ASP_TXn_SRC_MASK, | ||
| 109 | cs35l56_tx_input_texts, | ||
| 110 | cs35l56_tx_input_values); | ||
| 111 | |||
| 112 | static const struct snd_kcontrol_new asp1_tx2_mux = | ||
| 113 | SOC_DAPM_ENUM("ASP1TX2 SRC", cs35l56_asp1tx2_enum); | ||
| 114 | |||
| 115 | static SOC_VALUE_ENUM_SINGLE_DECL(cs35l56_asp1tx3_enum, | ||
| 116 | CS35L56_ASP1TX3_INPUT, | ||
| 117 | 0, CS35L56_ASP_TXn_SRC_MASK, | ||
| 118 | cs35l56_tx_input_texts, | ||
| 119 | cs35l56_tx_input_values); | ||
| 120 | |||
| 121 | static const struct snd_kcontrol_new asp1_tx3_mux = | ||
| 122 | SOC_DAPM_ENUM("ASP1TX3 SRC", cs35l56_asp1tx3_enum); | ||
| 123 | |||
| 124 | static SOC_VALUE_ENUM_SINGLE_DECL(cs35l56_asp1tx4_enum, | ||
| 125 | CS35L56_ASP1TX4_INPUT, | ||
| 126 | 0, CS35L56_ASP_TXn_SRC_MASK, | ||
| 127 | cs35l56_tx_input_texts, | ||
| 128 | cs35l56_tx_input_values); | ||
| 129 | |||
| 130 | static const struct snd_kcontrol_new asp1_tx4_mux = | ||
| 131 | SOC_DAPM_ENUM("ASP1TX4 SRC", cs35l56_asp1tx4_enum); | ||
| 132 | |||
| 133 | static SOC_VALUE_ENUM_SINGLE_DECL(cs35l56_sdw1tx1_enum, | ||
| 134 | CS35L56_SWIRE_DP3_CH1_INPUT, | ||
| 135 | 0, CS35L56_SWIRETXn_SRC_MASK, | ||
| 136 | cs35l56_tx_input_texts, | ||
| 137 | cs35l56_tx_input_values); | ||
| 138 | |||
| 139 | static const struct snd_kcontrol_new sdw1_tx1_mux = | ||
| 140 | SOC_DAPM_ENUM("SDW1TX1 SRC", cs35l56_sdw1tx1_enum); | ||
| 141 | |||
| 142 | static SOC_VALUE_ENUM_SINGLE_DECL(cs35l56_sdw1tx2_enum, | ||
| 143 | CS35L56_SWIRE_DP3_CH2_INPUT, | ||
| 144 | 0, CS35L56_SWIRETXn_SRC_MASK, | ||
| 145 | cs35l56_tx_input_texts, | ||
| 146 | cs35l56_tx_input_values); | ||
| 147 | |||
| 148 | static const struct snd_kcontrol_new sdw1_tx2_mux = | ||
| 149 | SOC_DAPM_ENUM("SDW1TX2 SRC", cs35l56_sdw1tx2_enum); | ||
| 150 | |||
| 151 | static SOC_VALUE_ENUM_SINGLE_DECL(cs35l56_sdw1tx3_enum, | ||
| 152 | CS35L56_SWIRE_DP3_CH3_INPUT, | ||
| 153 | 0, CS35L56_SWIRETXn_SRC_MASK, | ||
| 154 | cs35l56_tx_input_texts, | ||
| 155 | cs35l56_tx_input_values); | ||
| 156 | |||
| 157 | static const struct snd_kcontrol_new sdw1_tx3_mux = | ||
| 158 | SOC_DAPM_ENUM("SDW1TX3 SRC", cs35l56_sdw1tx3_enum); | ||
| 159 | |||
| 160 | static SOC_VALUE_ENUM_SINGLE_DECL(cs35l56_sdw1tx4_enum, | ||
| 161 | CS35L56_SWIRE_DP3_CH4_INPUT, | ||
| 162 | 0, CS35L56_SWIRETXn_SRC_MASK, | ||
| 163 | cs35l56_tx_input_texts, | ||
| 164 | cs35l56_tx_input_values); | ||
| 165 | |||
| 166 | static const struct snd_kcontrol_new sdw1_tx4_mux = | ||
| 167 | SOC_DAPM_ENUM("SDW1TX4 SRC", cs35l56_sdw1tx4_enum); | ||
| 168 | |||
| 169 | static int cs35l56_play_event(struct snd_soc_dapm_widget *w, | ||
| 170 | struct snd_kcontrol *kcontrol, int event) | ||
| 171 | { | ||
| 172 | struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm); | ||
| 173 | struct cs35l56_private *cs35l56 = snd_soc_component_get_drvdata(component); | ||
| 174 | unsigned int val; | ||
| 175 | int ret; | ||
| 176 | |||
| 177 | dev_dbg(cs35l56->dev, "play: %d\n", event); | ||
| 178 | |||
| 179 | switch (event) { | ||
| 180 | case SND_SOC_DAPM_PRE_PMU: | ||
| 181 | /* Don't wait for ACK, we check in POST_PMU that it completed */ | ||
| 182 | return regmap_write(cs35l56->regmap, CS35L56_DSP_VIRTUAL1_MBOX_1, | ||
| 183 | CS35L56_MBOX_CMD_AUDIO_PLAY); | ||
| 184 | case SND_SOC_DAPM_POST_PMU: | ||
| 185 | /* Wait for firmware to enter PS0 power state */ | ||
| 186 | ret = regmap_read_poll_timeout(cs35l56->regmap, | ||
| 187 | CS35L56_TRANSDUCER_ACTUAL_PS, | ||
| 188 | val, (val == CS35L56_PS0), | ||
| 189 | CS35L56_PS0_POLL_US, | ||
| 190 | CS35L56_PS0_TIMEOUT_US); | ||
| 191 | if (ret) | ||
| 192 | dev_err(cs35l56->dev, "PS0 wait failed: %d\n", ret); | ||
| 193 | return ret; | ||
| 194 | case SND_SOC_DAPM_POST_PMD: | ||
| 195 | return cs35l56_mbox_send(cs35l56, CS35L56_MBOX_CMD_AUDIO_PAUSE); | ||
| 196 | default: | ||
| 197 | return 0; | ||
| 198 | } | ||
| 199 | } | ||
| 200 | |||
| 201 | static const struct snd_soc_dapm_widget cs35l56_dapm_widgets[] = { | ||
| 202 | SND_SOC_DAPM_REGULATOR_SUPPLY("VDD_B", 0, 0), | ||
| 203 | SND_SOC_DAPM_REGULATOR_SUPPLY("VDD_AMP", 0, 0), | ||
| 204 | |||
| 205 | SND_SOC_DAPM_SUPPLY("PLAY", SND_SOC_NOPM, 0, 0, cs35l56_play_event, | ||
| 206 | SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD), | ||
| 207 | |||
| 208 | SND_SOC_DAPM_OUT_DRV("AMP", SND_SOC_NOPM, 0, 0, NULL, 0), | ||
| 209 | SND_SOC_DAPM_OUTPUT("SPK"), | ||
| 210 | |||
| 211 | SND_SOC_DAPM_PGA_E("DSP1", SND_SOC_NOPM, 0, 0, NULL, 0, cs35l56_dsp_event, | ||
| 212 | SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD), | ||
| 213 | |||
| 214 | SND_SOC_DAPM_AIF_IN("ASP1RX1", NULL, 0, CS35L56_ASP1_ENABLES1, | ||
| 215 | CS35L56_ASP_RX1_EN_SHIFT, 0), | ||
| 216 | SND_SOC_DAPM_AIF_IN("ASP1RX2", NULL, 1, CS35L56_ASP1_ENABLES1, | ||
| 217 | CS35L56_ASP_RX2_EN_SHIFT, 0), | ||
| 218 | SND_SOC_DAPM_AIF_OUT("ASP1TX1", NULL, 0, CS35L56_ASP1_ENABLES1, | ||
| 219 | CS35L56_ASP_TX1_EN_SHIFT, 0), | ||
| 220 | SND_SOC_DAPM_AIF_OUT("ASP1TX2", NULL, 1, CS35L56_ASP1_ENABLES1, | ||
| 221 | CS35L56_ASP_TX2_EN_SHIFT, 0), | ||
| 222 | SND_SOC_DAPM_AIF_OUT("ASP1TX3", NULL, 2, CS35L56_ASP1_ENABLES1, | ||
| 223 | CS35L56_ASP_TX3_EN_SHIFT, 0), | ||
| 224 | SND_SOC_DAPM_AIF_OUT("ASP1TX4", NULL, 3, CS35L56_ASP1_ENABLES1, | ||
| 225 | CS35L56_ASP_TX4_EN_SHIFT, 0), | ||
| 226 | |||
| 227 | SND_SOC_DAPM_MUX("ASP1 TX1 Source", SND_SOC_NOPM, 0, 0, &asp1_tx1_mux), | ||
| 228 | SND_SOC_DAPM_MUX("ASP1 TX2 Source", SND_SOC_NOPM, 0, 0, &asp1_tx2_mux), | ||
| 229 | SND_SOC_DAPM_MUX("ASP1 TX3 Source", SND_SOC_NOPM, 0, 0, &asp1_tx3_mux), | ||
| 230 | SND_SOC_DAPM_MUX("ASP1 TX4 Source", SND_SOC_NOPM, 0, 0, &asp1_tx4_mux), | ||
| 231 | |||
| 232 | SND_SOC_DAPM_MUX("SDW1 TX1 Source", SND_SOC_NOPM, 0, 0, &sdw1_tx1_mux), | ||
| 233 | SND_SOC_DAPM_MUX("SDW1 TX2 Source", SND_SOC_NOPM, 0, 0, &sdw1_tx2_mux), | ||
| 234 | SND_SOC_DAPM_MUX("SDW1 TX3 Source", SND_SOC_NOPM, 0, 0, &sdw1_tx3_mux), | ||
| 235 | SND_SOC_DAPM_MUX("SDW1 TX4 Source", SND_SOC_NOPM, 0, 0, &sdw1_tx4_mux), | ||
| 236 | |||
| 237 | SND_SOC_DAPM_SIGGEN("VMON ADC"), | ||
| 238 | SND_SOC_DAPM_SIGGEN("IMON ADC"), | ||
| 239 | SND_SOC_DAPM_SIGGEN("ERRVOL ADC"), | ||
| 240 | SND_SOC_DAPM_SIGGEN("CLASSH ADC"), | ||
| 241 | SND_SOC_DAPM_SIGGEN("VDDBMON ADC"), | ||
| 242 | SND_SOC_DAPM_SIGGEN("VBSTMON ADC"), | ||
| 243 | SND_SOC_DAPM_SIGGEN("TEMPMON ADC"), | ||
| 244 | }; | ||
| 245 | |||
| 246 | #define CS35L56_SRC_ROUTE(name) \ | ||
| 247 | { name" Source", "ASP1RX1", "ASP1RX1" }, \ | ||
| 248 | { name" Source", "ASP1RX2", "ASP1RX2" }, \ | ||
| 249 | { name" Source", "VMON", "VMON ADC" }, \ | ||
| 250 | { name" Source", "IMON", "IMON ADC" }, \ | ||
| 251 | { name" Source", "ERRVOL", "ERRVOL ADC" }, \ | ||
| 252 | { name" Source", "CLASSH", "CLASSH ADC" }, \ | ||
| 253 | { name" Source", "VDDBMON", "VDDBMON ADC" }, \ | ||
| 254 | { name" Source", "VBSTMON", "VBSTMON ADC" }, \ | ||
| 255 | { name" Source", "DSP1TX1", "DSP1" }, \ | ||
| 256 | { name" Source", "DSP1TX2", "DSP1" }, \ | ||
| 257 | { name" Source", "DSP1TX3", "DSP1" }, \ | ||
| 258 | { name" Source", "DSP1TX4", "DSP1" }, \ | ||
| 259 | { name" Source", "DSP1TX5", "DSP1" }, \ | ||
| 260 | { name" Source", "DSP1TX6", "DSP1" }, \ | ||
| 261 | { name" Source", "DSP1TX7", "DSP1" }, \ | ||
| 262 | { name" Source", "DSP1TX8", "DSP1" }, \ | ||
| 263 | { name" Source", "TEMPMON", "TEMPMON ADC" }, \ | ||
| 264 | { name" Source", "INTERPOLATOR", "AMP" }, \ | ||
| 265 | { name" Source", "SDW1RX1", "SDW1 Playback" }, \ | ||
| 266 | { name" Source", "SDW1RX2", "SDW1 Playback" }, | ||
| 267 | |||
| 268 | static const struct snd_soc_dapm_route cs35l56_audio_map[] = { | ||
| 269 | { "AMP", NULL, "VDD_B" }, | ||
| 270 | { "AMP", NULL, "VDD_AMP" }, | ||
| 271 | |||
| 272 | { "ASP1 Playback", NULL, "PLAY" }, | ||
| 273 | { "SDW1 Playback", NULL, "PLAY" }, | ||
| 274 | |||
| 275 | { "ASP1RX1", NULL, "ASP1 Playback" }, | ||
| 276 | { "ASP1RX2", NULL, "ASP1 Playback" }, | ||
| 277 | { "DSP1", NULL, "ASP1RX1" }, | ||
| 278 | { "DSP1", NULL, "ASP1RX2" }, | ||
| 279 | { "DSP1", NULL, "SDW1 Playback" }, | ||
| 280 | { "AMP", NULL, "DSP1" }, | ||
| 281 | { "SPK", NULL, "AMP" }, | ||
| 282 | |||
| 283 | CS35L56_SRC_ROUTE("ASP1 TX1") | ||
| 284 | CS35L56_SRC_ROUTE("ASP1 TX2") | ||
| 285 | CS35L56_SRC_ROUTE("ASP1 TX3") | ||
| 286 | CS35L56_SRC_ROUTE("ASP1 TX4") | ||
| 287 | |||
| 288 | { "ASP1TX1", NULL, "ASP1 TX1 Source" }, | ||
| 289 | { "ASP1TX2", NULL, "ASP1 TX2 Source" }, | ||
| 290 | { "ASP1TX3", NULL, "ASP1 TX3 Source" }, | ||
| 291 | { "ASP1TX4", NULL, "ASP1 TX4 Source" }, | ||
| 292 | { "ASP1 Capture", NULL, "ASP1TX1" }, | ||
| 293 | { "ASP1 Capture", NULL, "ASP1TX2" }, | ||
| 294 | { "ASP1 Capture", NULL, "ASP1TX3" }, | ||
| 295 | { "ASP1 Capture", NULL, "ASP1TX4" }, | ||
| 296 | |||
| 297 | CS35L56_SRC_ROUTE("SDW1 TX1") | ||
| 298 | CS35L56_SRC_ROUTE("SDW1 TX2") | ||
| 299 | CS35L56_SRC_ROUTE("SDW1 TX3") | ||
| 300 | CS35L56_SRC_ROUTE("SDW1 TX4") | ||
| 301 | { "SDW1 Capture", NULL, "SDW1 TX1 Source" }, | ||
| 302 | { "SDW1 Capture", NULL, "SDW1 TX2 Source" }, | ||
| 303 | { "SDW1 Capture", NULL, "SDW1 TX3 Source" }, | ||
| 304 | { "SDW1 Capture", NULL, "SDW1 TX4 Source" }, | ||
| 305 | }; | ||
| 306 | |||
| 307 | static int cs35l56_dsp_event(struct snd_soc_dapm_widget *w, | ||
| 308 | struct snd_kcontrol *kcontrol, int event) | ||
| 309 | { | ||
| 310 | struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm); | ||
| 311 | struct cs35l56_private *cs35l56 = snd_soc_component_get_drvdata(component); | ||
| 312 | |||
| 313 | dev_dbg(cs35l56->dev, "%s: %d\n", __func__, event); | ||
| 314 | |||
| 315 | return wm_adsp_event(w, kcontrol, event); | ||
| 316 | } | ||
| 317 | |||
| 318 | irqreturn_t cs35l56_irq(int irq, void *data) | ||
| 319 | { | ||
| 320 | struct cs35l56_private *cs35l56 = data; | ||
| 321 | unsigned int status1 = 0, status8 = 0, status20 = 0; | ||
| 322 | unsigned int mask1, mask8, mask20; | ||
| 323 | unsigned int val; | ||
| 324 | int rv; | ||
| 325 | |||
| 326 | irqreturn_t ret = IRQ_NONE; | ||
| 327 | |||
| 328 | if (!cs35l56->init_done) | ||
| 329 | return IRQ_NONE; | ||
| 330 | |||
| 331 | mutex_lock(&cs35l56->irq_lock); | ||
| 332 | |||
| 333 | rv = pm_runtime_resume_and_get(cs35l56->dev); | ||
| 334 | if (rv < 0) { | ||
| 335 | dev_err(cs35l56->dev, "irq: failed to get pm_runtime: %d\n", rv); | ||
| 336 | goto err_unlock; | ||
| 337 | } | ||
| 338 | |||
| 339 | regmap_read(cs35l56->regmap, CS35L56_IRQ1_STATUS, &val); | ||
| 340 | if ((val & CS35L56_IRQ1_STS_MASK) == 0) { | ||
| 341 | dev_dbg(cs35l56->dev, "Spurious IRQ: no pending interrupt\n"); | ||
| 342 | goto err; | ||
| 343 | } | ||
| 344 | |||
| 345 | /* Ack interrupts */ | ||
| 346 | regmap_read(cs35l56->regmap, CS35L56_IRQ1_EINT_1, &status1); | ||
| 347 | regmap_read(cs35l56->regmap, CS35L56_IRQ1_MASK_1, &mask1); | ||
| 348 | status1 &= ~mask1; | ||
| 349 | regmap_write(cs35l56->regmap, CS35L56_IRQ1_EINT_1, status1); | ||
| 350 | |||
| 351 | regmap_read(cs35l56->regmap, CS35L56_IRQ1_EINT_8, &status8); | ||
| 352 | regmap_read(cs35l56->regmap, CS35L56_IRQ1_MASK_8, &mask8); | ||
| 353 | status8 &= ~mask8; | ||
| 354 | regmap_write(cs35l56->regmap, CS35L56_IRQ1_EINT_8, status8); | ||
| 355 | |||
| 356 | regmap_read(cs35l56->regmap, CS35L56_IRQ1_EINT_20, &status20); | ||
| 357 | regmap_read(cs35l56->regmap, CS35L56_IRQ1_MASK_20, &mask20); | ||
| 358 | status20 &= ~mask20; | ||
| 359 | /* We don't want EINT20 but they default to unmasked: force mask */ | ||
| 360 | regmap_write(cs35l56->regmap, CS35L56_IRQ1_MASK_20, 0xffffffff); | ||
| 361 | |||
| 362 | dev_dbg(cs35l56->dev, "%s: %#x %#x\n", __func__, status1, status8); | ||
| 363 | |||
| 364 | /* Check to see if unmasked bits are active */ | ||
| 365 | if (!status1 && !status8 && !status20) | ||
| 366 | goto err; | ||
| 367 | |||
| 368 | if (status1 & CS35L56_AMP_SHORT_ERR_EINT1_MASK) | ||
| 369 | dev_crit(cs35l56->dev, "Amp short error\n"); | ||
| 370 | |||
| 371 | if (status8 & CS35L56_TEMP_ERR_EINT1_MASK) | ||
| 372 | dev_crit(cs35l56->dev, "Overtemp error\n"); | ||
| 373 | |||
| 374 | ret = IRQ_HANDLED; | ||
| 375 | |||
| 376 | err: | ||
| 377 | pm_runtime_put(cs35l56->dev); | ||
| 378 | err_unlock: | ||
| 379 | mutex_unlock(&cs35l56->irq_lock); | ||
| 380 | |||
| 381 | return ret; | ||
| 382 | } | ||
| 383 | EXPORT_SYMBOL_NS_GPL(cs35l56_irq, SND_SOC_CS35L56_CORE); | ||
| 384 | |||
| 385 | int cs35l56_irq_request(struct cs35l56_private *cs35l56, int irq) | ||
| 386 | { | ||
| 387 | int ret; | ||
| 388 | |||
| 389 | if (!irq) | ||
| 390 | return 0; | ||
| 391 | |||
| 392 | ret = devm_request_threaded_irq(cs35l56->dev, irq, NULL, cs35l56_irq, | ||
| 393 | IRQF_ONESHOT | IRQF_SHARED | IRQF_TRIGGER_LOW, | ||
| 394 | "cs35l56", cs35l56); | ||
| 395 | if (!ret) | ||
| 396 | cs35l56->irq = irq; | ||
| 397 | else | ||
| 398 | dev_err(cs35l56->dev, "Failed to get IRQ: %d\n", ret); | ||
| 399 | |||
| 400 | return ret; | ||
| 401 | } | ||
| 402 | EXPORT_SYMBOL_NS_GPL(cs35l56_irq_request, SND_SOC_CS35L56_CORE); | ||
| 403 | |||
| 404 | static int cs35l56_asp_dai_set_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt) | ||
| 405 | { | ||
| 406 | struct cs35l56_private *cs35l56 = snd_soc_component_get_drvdata(codec_dai->component); | ||
| 407 | unsigned int val; | ||
| 408 | |||
| 409 | dev_dbg(cs35l56->dev, "%s: %#x\n", __func__, fmt); | ||
| 410 | |||
| 411 | switch (fmt & SND_SOC_DAIFMT_CLOCK_PROVIDER_MASK) { | ||
| 412 | case SND_SOC_DAIFMT_CBC_CFC: | ||
| 413 | break; | ||
| 414 | default: | ||
| 415 | dev_err(cs35l56->dev, "Unsupported clock source mode\n"); | ||
| 416 | return -EINVAL; | ||
| 417 | } | ||
| 418 | |||
| 419 | switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { | ||
| 420 | case SND_SOC_DAIFMT_DSP_A: | ||
| 421 | val = CS35L56_ASP_FMT_DSP_A << CS35L56_ASP_FMT_SHIFT; | ||
| 422 | cs35l56->tdm_mode = true; | ||
| 423 | break; | ||
| 424 | case SND_SOC_DAIFMT_I2S: | ||
| 425 | val = CS35L56_ASP_FMT_I2S << CS35L56_ASP_FMT_SHIFT; | ||
| 426 | cs35l56->tdm_mode = false; | ||
| 427 | break; | ||
| 428 | default: | ||
| 429 | dev_err(cs35l56->dev, "Unsupported DAI format\n"); | ||
| 430 | return -EINVAL; | ||
| 431 | } | ||
| 432 | |||
| 433 | switch (fmt & SND_SOC_DAIFMT_INV_MASK) { | ||
| 434 | case SND_SOC_DAIFMT_NB_IF: | ||
| 435 | val |= CS35L56_ASP_FSYNC_INV_MASK; | ||
| 436 | break; | ||
| 437 | case SND_SOC_DAIFMT_IB_NF: | ||
| 438 | val |= CS35L56_ASP_BCLK_INV_MASK; | ||
| 439 | break; | ||
| 440 | case SND_SOC_DAIFMT_IB_IF: | ||
| 441 | val |= CS35L56_ASP_BCLK_INV_MASK | CS35L56_ASP_FSYNC_INV_MASK; | ||
| 442 | break; | ||
| 443 | case SND_SOC_DAIFMT_NB_NF: | ||
| 444 | break; | ||
| 445 | default: | ||
| 446 | dev_err(cs35l56->dev, "Invalid clock invert\n"); | ||
| 447 | return -EINVAL; | ||
| 448 | } | ||
| 449 | |||
| 450 | regmap_update_bits(cs35l56->regmap, | ||
| 451 | CS35L56_ASP1_CONTROL2, | ||
| 452 | CS35L56_ASP_FMT_MASK | | ||
| 453 | CS35L56_ASP_BCLK_INV_MASK | CS35L56_ASP_FSYNC_INV_MASK, | ||
| 454 | val); | ||
| 455 | |||
| 456 | /* Hi-Z DOUT in unused slots and when all TX are disabled */ | ||
| 457 | regmap_update_bits(cs35l56->regmap, CS35L56_ASP1_CONTROL3, | ||
| 458 | CS35L56_ASP1_DOUT_HIZ_CTRL_MASK, | ||
| 459 | CS35L56_ASP_UNUSED_HIZ_OFF_HIZ); | ||
| 460 | |||
| 461 | return 0; | ||
| 462 | } | ||
| 463 | |||
| 464 | static void cs35l56_set_asp_slot_positions(struct cs35l56_private *cs35l56, | ||
| 465 | unsigned int reg, unsigned long mask) | ||
| 466 | { | ||
| 467 | unsigned int reg_val, channel_shift; | ||
| 468 | int bit_num; | ||
| 469 | |||
| 470 | /* Init all slots to 63 */ | ||
| 471 | switch (reg) { | ||
| 472 | case CS35L56_ASP1_FRAME_CONTROL1: | ||
| 473 | reg_val = 0x3f3f3f3f; | ||
| 474 | break; | ||
| 475 | case CS35L56_ASP1_FRAME_CONTROL5: | ||
| 476 | reg_val = 0x3f3f3f; | ||
| 477 | break; | ||
| 478 | } | ||
| 479 | |||
| 480 | /* Enable consecutive TX1..TXn for each of the slots set in mask */ | ||
| 481 | channel_shift = 0; | ||
| 482 | for_each_set_bit(bit_num, &mask, 32) { | ||
| 483 | reg_val &= ~(0x3f << channel_shift); | ||
| 484 | reg_val |= bit_num << channel_shift; | ||
| 485 | channel_shift += 8; | ||
| 486 | } | ||
| 487 | |||
| 488 | regmap_write(cs35l56->regmap, reg, reg_val); | ||
| 489 | } | ||
| 490 | |||
| 491 | static int cs35l56_asp_dai_set_tdm_slot(struct snd_soc_dai *dai, unsigned int tx_mask, | ||
| 492 | unsigned int rx_mask, int slots, int slot_width) | ||
| 493 | { | ||
| 494 | struct cs35l56_private *cs35l56 = snd_soc_component_get_drvdata(dai->component); | ||
| 495 | |||
| 496 | if ((slots == 0) || (slot_width == 0)) { | ||
| 497 | dev_dbg(cs35l56->dev, "tdm config cleared\n"); | ||
| 498 | cs35l56->asp_slot_width = 0; | ||
| 499 | cs35l56->asp_slot_count = 0; | ||
| 500 | return 0; | ||
| 501 | } | ||
| 502 | |||
| 503 | if (slot_width > (CS35L56_ASP_RX_WIDTH_MASK >> CS35L56_ASP_RX_WIDTH_SHIFT)) { | ||
| 504 | dev_err(cs35l56->dev, "tdm invalid slot width %d\n", slot_width); | ||
| 505 | return -EINVAL; | ||
| 506 | } | ||
| 507 | |||
| 508 | /* More than 32 slots would give an unsupportable BCLK frequency */ | ||
| 509 | if (slots > 32) { | ||
| 510 | dev_err(cs35l56->dev, "tdm invalid slot count %d\n", slots); | ||
| 511 | return -EINVAL; | ||
| 512 | } | ||
| 513 | |||
| 514 | cs35l56->asp_slot_width = (u8)slot_width; | ||
| 515 | cs35l56->asp_slot_count = (u8)slots; | ||
| 516 | |||
| 517 | // Note: rx/tx is from point of view of the CPU end | ||
| 518 | if (tx_mask == 0) | ||
| 519 | tx_mask = 0x3; // ASPRX1/RX2 in slots 0 and 1 | ||
| 520 | |||
| 521 | if (rx_mask == 0) | ||
| 522 | rx_mask = 0xf; // ASPTX1..TX4 in slots 0..3 | ||
| 523 | |||
| 524 | cs35l56_set_asp_slot_positions(cs35l56, CS35L56_ASP1_FRAME_CONTROL1, rx_mask); | ||
| 525 | cs35l56_set_asp_slot_positions(cs35l56, CS35L56_ASP1_FRAME_CONTROL5, tx_mask); | ||
| 526 | |||
| 527 | dev_dbg(cs35l56->dev, "tdm slot width: %u count: %u tx_mask: %#x rx_mask: %#x\n", | ||
| 528 | cs35l56->asp_slot_width, cs35l56->asp_slot_count, tx_mask, rx_mask); | ||
| 529 | |||
| 530 | return 0; | ||
| 531 | } | ||
| 532 | |||
| 533 | static int cs35l56_asp_dai_hw_params(struct snd_pcm_substream *substream, | ||
| 534 | struct snd_pcm_hw_params *params, | ||
| 535 | struct snd_soc_dai *dai) | ||
| 536 | { | ||
| 537 | struct cs35l56_private *cs35l56 = snd_soc_component_get_drvdata(dai->component); | ||
| 538 | unsigned int rate = params_rate(params); | ||
| 539 | u8 asp_width, asp_wl; | ||
| 540 | |||
| 541 | asp_wl = params_width(params); | ||
| 542 | if (cs35l56->asp_slot_width) | ||
| 543 | asp_width = cs35l56->asp_slot_width; | ||
| 544 | else | ||
| 545 | asp_width = asp_wl; | ||
| 546 | |||
| 547 | dev_dbg(cs35l56->dev, "%s: wl=%d, width=%d, rate=%d", __func__, asp_wl, asp_width, rate); | ||
| 548 | |||
| 549 | if (!cs35l56->sysclk_set) { | ||
| 550 | unsigned int slots = cs35l56->asp_slot_count; | ||
| 551 | unsigned int bclk_freq; | ||
| 552 | int freq_id; | ||
| 553 | |||
| 554 | if (slots == 0) { | ||
| 555 | slots = params_channels(params); | ||
| 556 | |||
| 557 | /* I2S always has an even number of slots */ | ||
| 558 | if (!cs35l56->tdm_mode) | ||
| 559 | slots = round_up(slots, 2); | ||
| 560 | } | ||
| 561 | |||
| 562 | bclk_freq = asp_width * slots * rate; | ||
| 563 | freq_id = cs35l56_get_bclk_freq_id(bclk_freq); | ||
| 564 | if (freq_id < 0) { | ||
| 565 | dev_err(cs35l56->dev, "%s: Invalid BCLK %u\n", __func__, bclk_freq); | ||
| 566 | return -EINVAL; | ||
| 567 | } | ||
| 568 | |||
| 569 | regmap_update_bits(cs35l56->regmap, CS35L56_ASP1_CONTROL1, | ||
| 570 | CS35L56_ASP_BCLK_FREQ_MASK, | ||
| 571 | freq_id << CS35L56_ASP_BCLK_FREQ_SHIFT); | ||
| 572 | } | ||
| 573 | |||
| 574 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { | ||
| 575 | regmap_update_bits(cs35l56->regmap, CS35L56_ASP1_CONTROL2, | ||
| 576 | CS35L56_ASP_RX_WIDTH_MASK, asp_width << | ||
| 577 | CS35L56_ASP_RX_WIDTH_SHIFT); | ||
| 578 | regmap_update_bits(cs35l56->regmap, CS35L56_ASP1_DATA_CONTROL5, | ||
| 579 | CS35L56_ASP_RX_WL_MASK, asp_wl); | ||
| 580 | } else { | ||
| 581 | regmap_update_bits(cs35l56->regmap, CS35L56_ASP1_CONTROL2, | ||
| 582 | CS35L56_ASP_TX_WIDTH_MASK, asp_width << | ||
| 583 | CS35L56_ASP_TX_WIDTH_SHIFT); | ||
| 584 | regmap_update_bits(cs35l56->regmap, CS35L56_ASP1_DATA_CONTROL1, | ||
| 585 | CS35L56_ASP_TX_WL_MASK, asp_wl); | ||
| 586 | } | ||
| 587 | |||
| 588 | return 0; | ||
| 589 | } | ||
| 590 | |||
| 591 | static int cs35l56_asp_dai_set_sysclk(struct snd_soc_dai *dai, | ||
| 592 | int clk_id, unsigned int freq, int dir) | ||
| 593 | { | ||
| 594 | struct cs35l56_private *cs35l56 = snd_soc_component_get_drvdata(dai->component); | ||
| 595 | int freq_id; | ||
| 596 | |||
| 597 | if (freq == 0) { | ||
| 598 | cs35l56->sysclk_set = false; | ||
| 599 | return 0; | ||
| 600 | } | ||
| 601 | |||
| 602 | freq_id = cs35l56_get_bclk_freq_id(freq); | ||
| 603 | if (freq_id < 0) | ||
| 604 | return freq_id; | ||
| 605 | |||
| 606 | regmap_update_bits(cs35l56->regmap, CS35L56_ASP1_CONTROL1, | ||
| 607 | CS35L56_ASP_BCLK_FREQ_MASK, | ||
| 608 | freq_id << CS35L56_ASP_BCLK_FREQ_SHIFT); | ||
| 609 | cs35l56->sysclk_set = true; | ||
| 610 | |||
| 611 | return 0; | ||
| 612 | } | ||
| 613 | |||
| 614 | static const struct snd_soc_dai_ops cs35l56_ops = { | ||
| 615 | .set_fmt = cs35l56_asp_dai_set_fmt, | ||
| 616 | .set_tdm_slot = cs35l56_asp_dai_set_tdm_slot, | ||
| 617 | .hw_params = cs35l56_asp_dai_hw_params, | ||
| 618 | .set_sysclk = cs35l56_asp_dai_set_sysclk, | ||
| 619 | }; | ||
| 620 | |||
| 621 | static void cs35l56_sdw_dai_shutdown(struct snd_pcm_substream *substream, | ||
| 622 | struct snd_soc_dai *dai) | ||
| 623 | { | ||
| 624 | snd_soc_dai_set_dma_data(dai, substream, NULL); | ||
| 625 | } | ||
| 626 | |||
| 627 | static int cs35l56_sdw_dai_set_tdm_slot(struct snd_soc_dai *dai, unsigned int tx_mask, | ||
| 628 | unsigned int rx_mask, int slots, int slot_width) | ||
| 629 | { | ||
| 630 | struct cs35l56_private *cs35l56 = snd_soc_component_get_drvdata(dai->component); | ||
| 631 | |||
| 632 | /* rx/tx are from point of view of the CPU end so opposite to our rx/tx */ | ||
| 633 | cs35l56->rx_mask = tx_mask; | ||
| 634 | cs35l56->tx_mask = rx_mask; | ||
| 635 | |||
| 636 | return 0; | ||
| 637 | } | ||
| 638 | |||
| 639 | static int cs35l56_sdw_dai_hw_params(struct snd_pcm_substream *substream, | ||
| 640 | struct snd_pcm_hw_params *params, | ||
| 641 | struct snd_soc_dai *dai) | ||
| 642 | { | ||
| 643 | struct cs35l56_private *cs35l56 = snd_soc_component_get_drvdata(dai->component); | ||
| 644 | struct sdw_stream_runtime *sdw_stream = snd_soc_dai_get_dma_data(dai, substream); | ||
| 645 | struct sdw_stream_config sconfig; | ||
| 646 | struct sdw_port_config pconfig; | ||
| 647 | int ret; | ||
| 648 | |||
| 649 | dev_dbg(cs35l56->dev, "%s: rate %d\n", __func__, params_rate(params)); | ||
| 650 | |||
| 651 | if (!cs35l56->init_done) | ||
| 652 | return -ENODEV; | ||
| 653 | |||
| 654 | if (!sdw_stream) | ||
| 655 | return -EINVAL; | ||
| 656 | |||
| 657 | memset(&sconfig, 0, sizeof(sconfig)); | ||
| 658 | memset(&pconfig, 0, sizeof(pconfig)); | ||
| 659 | |||
| 660 | sconfig.frame_rate = params_rate(params); | ||
| 661 | sconfig.bps = snd_pcm_format_width(params_format(params)); | ||
| 662 | |||
| 663 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { | ||
| 664 | sconfig.direction = SDW_DATA_DIR_RX; | ||
| 665 | pconfig.num = CS35L56_SDW1_PLAYBACK_PORT; | ||
| 666 | pconfig.ch_mask = cs35l56->rx_mask; | ||
| 667 | } else { | ||
| 668 | sconfig.direction = SDW_DATA_DIR_TX; | ||
| 669 | pconfig.num = CS35L56_SDW1_CAPTURE_PORT; | ||
| 670 | pconfig.ch_mask = cs35l56->tx_mask; | ||
931 more lines aren’t shown here.
This diff is large: its 82 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 11 lines aren’t shown here.
This diff is large: its 10 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 27 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 27 lines aren’t shown here.
This diff is large: its 18 lines aren’t shown here.
This diff is large: its 137 lines aren’t shown here.
This diff is large: its 12 lines aren’t shown here.
This diff is large: its 54 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 10 lines aren’t shown here.
This diff is large: its 91 lines aren’t shown here.
This diff is large: its 94 lines aren’t shown here.
This diff is large: its 27 lines aren’t shown here.
This diff is large: its 102 lines aren’t shown here.
This diff is large: its 465 lines aren’t shown here.
This diff is large: its 37 lines aren’t shown here.
This diff is large: its 84 lines aren’t shown here.
This diff is large: its 55 lines aren’t shown here.
This diff is large: its 24 lines aren’t shown here.
This diff is large: its 25 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 116 lines aren’t shown here.
This diff is large: its 30 lines aren’t shown here.
This diff is large: its 29 lines aren’t shown here.
This diff is large: its 8 lines aren’t shown here.
This diff is large: its 9 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 75 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 75 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 76 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 83 lines aren’t shown here.
This diff is large: its 76 lines aren’t shown here.
This diff is large: its 11 lines aren’t shown here.
This diff is large: its 76 lines aren’t shown here.
This diff is large: its 11 lines aren’t shown here.
This diff is large: its 76 lines aren’t shown here.
This diff is large: its 11 lines aren’t shown here.
This diff is large: its 984 lines aren’t shown here.
This diff is large: its 109 lines aren’t shown here.
This diff is large: its 76 lines aren’t shown here.
This diff is large: its 11 lines aren’t shown here.
This diff is large: its 75 lines aren’t shown here.
This diff is large: its 11 lines aren’t shown here.
This diff is large: its 75 lines aren’t shown here.
This diff is large: its 11 lines aren’t shown here.
This diff is large: its 83 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 41 lines aren’t shown here.
This diff is large: its 54 lines aren’t shown here.
This diff is large: its 83 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 80 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 54 lines aren’t shown here.
This diff is large: its 68 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 8 lines aren’t shown here.
This diff is large: its 22 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 130 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 26 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 22 lines aren’t shown here.
This diff is large: its 42 lines aren’t shown here.
This diff is large: its 24 lines aren’t shown here.
This diff is large: its 22 lines aren’t shown here.
This diff is large: its 27 lines aren’t shown here.
This diff is large: its 26 lines aren’t shown here.
This diff is large: its 22 lines aren’t shown here.
This diff is large: its 27 lines aren’t shown here.
This diff is large: its 55 lines aren’t shown here.
This diff is large: its 736 lines aren’t shown here.
This diff is large: its 25 lines aren’t shown here.
This diff is large: its 65 lines aren’t shown here.
This diff is large: its 22 lines aren’t shown here.
This diff is large: its 36 lines aren’t shown here.
This diff is large: its 21 lines aren’t shown here.
This diff is large: its 59 lines aren’t shown here.
This diff is large: its 23 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 33 lines aren’t shown here.
This diff is large: its 25 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 23 lines aren’t shown here.
This diff is large: its 22 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 24 lines aren’t shown here.
This diff is large: its 25 lines aren’t shown here.
This diff is large: its 39 lines aren’t shown here.
This diff is large: its 10 lines aren’t shown here.
This diff is large: its 62 lines aren’t shown here.
This diff is large: its 63 lines aren’t shown here.
This diff is large: its 47 lines aren’t shown here.
This diff is large: its 22 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 27 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 26 lines aren’t shown here.
This diff is large: its 21 lines aren’t shown here.
This diff is large: its 25 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 26 lines aren’t shown here.
This diff is large: its 26 lines aren’t shown here.
This diff is large: its 25 lines aren’t shown here.
This diff is large: its 24 lines aren’t shown here.
This diff is large: its 26 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 24 lines aren’t shown here.
This diff is large: its 63 lines aren’t shown here.
This diff is large: its 363 lines aren’t shown here.
This diff is large: its 17 lines aren’t shown here.
This diff is large: its 38 lines aren’t shown here.
This diff is large: its 22 lines aren’t shown here.
This diff is large: its 27 lines aren’t shown here.
This diff is large: its 49 lines aren’t shown here.
This diff is large: its 26 lines aren’t shown here.
This diff is large: its 27 lines aren’t shown here.
This diff is large: its 24 lines aren’t shown here.
This diff is large: its 30 lines aren’t shown here.
This diff is large: its 25 lines aren’t shown here.
This diff is large: its 25 lines aren’t shown here.
This diff is large: its 25 lines aren’t shown here.
This diff is large: its 24 lines aren’t shown here.
This diff is large: its 112 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 27 lines aren’t shown here.
This diff is large: its 22 lines aren’t shown here.
This diff is large: its 18 lines aren’t shown here.
This diff is large: its 53 lines aren’t shown here.
This diff is large: its 71 lines aren’t shown here.
This diff is large: its 26 lines aren’t shown here.
This diff is large: its 26 lines aren’t shown here.
This diff is large: its 35 lines aren’t shown here.
This diff is large: its 397 lines aren’t shown here.
This diff is large: its 49 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 22 lines aren’t shown here.
This diff is large: its 10 lines aren’t shown here.
This diff is large: its 27 lines aren’t shown here.
This diff is large: its 10 lines aren’t shown here.
This diff is large: its 17 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 24 lines aren’t shown here.
This diff is large: its 36 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 23 lines aren’t shown here.
This diff is large: its 14 lines aren’t shown here.
This diff is large: its 35 lines aren’t shown here.
This diff is large: its 27 lines aren’t shown here.
This diff is large: its 25 lines aren’t shown here.
This diff is large: its 24 lines aren’t shown here.
This diff is large: its 19 lines aren’t shown here.
This diff is large: its 23 lines aren’t shown here.
This diff is large: its 70 lines aren’t shown here.
This diff is large: its 43 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 26 lines aren’t shown here.
This diff is large: its 23 lines aren’t shown here.
This diff is large: its 27 lines aren’t shown here.
This diff is large: its 24 lines aren’t shown here.
This diff is large: its 10 lines aren’t shown here.
This diff is large: its 36 lines aren’t shown here.
This diff is large: its 21 lines aren’t shown here.
This diff is large: its 27 lines aren’t shown here.
This diff is large: its 13 lines aren’t shown here.
This diff is large: its 112 lines aren’t shown here.
This diff is large: its 21 lines aren’t shown here.
This diff is large: its 54 lines aren’t shown here.
This diff is large: its 279 lines aren’t shown here.
This diff is large: its 143 lines aren’t shown here.
This diff is large: its 10 lines aren’t shown here.
This diff is large: its 820 lines aren’t shown here.
This diff is large: its 8 lines aren’t shown here.
This diff is large: its 132 lines aren’t shown here.
This diff is large: its 35 lines aren’t shown here.
This diff is large: its 31 lines aren’t shown here.
This diff is large: its 45 lines aren’t shown here.
This diff is large: its 94 lines aren’t shown here.
This diff is large: its 39 lines aren’t shown here.
This diff is large: its 121 lines aren’t shown here.
This diff is large: its 121 lines aren’t shown here.
This diff is large: its 32 lines aren’t shown here.
This diff is large: its 24 lines aren’t shown here.
This diff is large: its 36 lines aren’t shown here.
This diff is large: its 60 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 22 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 8 lines aren’t shown here.
This diff is large: its 30 lines aren’t shown here.
This diff is large: its 391 lines aren’t shown here.
This diff is large: its 892 lines aren’t shown here.
This diff is large: its 188 lines aren’t shown here.
This diff is large: its 10 lines aren’t shown here.
This diff is large: its 35 lines aren’t shown here.
This diff is large: its 875 lines aren’t shown here.
This diff is large: its 43 lines aren’t shown here.
This diff is large: its 206 lines aren’t shown here.
This diff is large: its 433 lines aren’t shown here.
This diff is large: its 102 lines aren’t shown here.
This diff is large: its 18 lines aren’t shown here.
This diff is large: its 82 lines aren’t shown here.
This diff is large: its 16 lines aren’t shown here.
This diff is large: its 24 lines aren’t shown here.
This diff is large: its 16 lines aren’t shown here.
This diff is large: its 8 lines aren’t shown here.
This diff is large: its 16 lines aren’t shown here.
This diff is large: its 64 lines aren’t shown here.
This diff is large: its 18 lines aren’t shown here.
This diff is large: its 159 lines aren’t shown here.
This diff is large: its 59 lines aren’t shown here.
This diff is large: its 40 lines aren’t shown here.
This diff is large: its 152 lines aren’t shown here.
This diff is large: its 48 lines aren’t shown here.
This diff is large: its 281 lines aren’t shown here.
This diff is large: its 42 lines aren’t shown here.
This diff is large: its 248 lines aren’t shown here.
This diff is large: its 1962 lines aren’t shown here.
This diff is large: its 142 lines aren’t shown here.
This diff is large: its 18 lines aren’t shown here.
This diff is large: its 122 lines aren’t shown here.
This diff is large: its 12 lines aren’t shown here.
This diff is large: its 117 lines aren’t shown here.
This diff is large: its 103 lines aren’t shown here.
This diff is large: its 17 lines aren’t shown here.
This diff is large: its 65 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 11 lines aren’t shown here.
This diff is large: its 46 lines aren’t shown here.
This diff is large: its 444 lines aren’t shown here.
This diff is large: its 27 lines aren’t shown here.
This diff is large: its 23 lines aren’t shown here.
This diff is large: its 33 lines aren’t shown here.
This diff is large: its 45 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 27 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 24 lines aren’t shown here.
This diff is large: its 32 lines aren’t shown here.
This diff is large: its 22 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 24 lines aren’t shown here.
This diff is large: its 22 lines aren’t shown here.
This diff is large: its 22 lines aren’t shown here.
This diff is large: its 22 lines aren’t shown here.
This diff is large: its 22 lines aren’t shown here.
This diff is large: its 22 lines aren’t shown here.
This diff is large: its 22 lines aren’t shown here.
This diff is large: its 22 lines aren’t shown here.
This diff is large: its 22 lines aren’t shown here.
This diff is large: its 22 lines aren’t shown here.
This diff is large: its 22 lines aren’t shown here.
This diff is large: its 24 lines aren’t shown here.
This diff is large: its 27 lines aren’t shown here.
This diff is large: its 207 lines aren’t shown here.
This diff is large: its 26 lines aren’t shown here.
This diff is large: its 27 lines aren’t shown here.
This diff is large: its 22 lines aren’t shown here.
This diff is large: its 45 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 27 lines aren’t shown here.
This diff is large: its 27 lines aren’t shown here.
This diff is large: its 26 lines aren’t shown here.
This diff is large: its 23 lines aren’t shown here.
This diff is large: its 26 lines aren’t shown here.
This diff is large: its 24 lines aren’t shown here.
This diff is large: its 25 lines aren’t shown here.
This diff is large: its 8 lines aren’t shown here.
This diff is large: its 36 lines aren’t shown here.
This diff is large: its 8 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 128 lines aren’t shown here.
This diff is large: its 49 lines aren’t shown here.