mirror of
https://github.com/FEX-Emu/linux.git
synced 2024-12-11 02:02:27 +00:00
sound updates for 3.18-rc1
This time it's a relatively calm update batch, but the amount isn't too small in the end. Here we go over some highlights: - ALSA core - One major change is the support of nonatomic PCM operations. This allows the trigger and other callbacks to call schedule(), which would be useful for mailbox type communications. Already some drivers (Digigram ones) have been converted to use together with threaded irqs as an example. - Improvement / fixes of DSD PCM format support - HD-audio - Large volume of rewrites are found in Realtek codec driver for converting Dell and HP quirks to generic forms. - Inverted dmic code cleanup from David. - Realtek COEF access has been optimized. - Now HD-audio jack infrastructure allows multiple callbacks, which fixes / simplifies the jack-dependent power controls on STAC/IDT and VIA codecs. - Many additional device-specific fixups as usual - A few deadcode cleanups, CA0132 code cleanup, etc. - ASoC - More componentization work from Lars-Peter, this time mainly cleaning up the suspend and bias level transition callbacks. - Real system support for the Intel drivers and a bunch of fixes and enhancements for the associated CODEC drivers, this is going to need a lot quirks over time due to the lack of any firmware description of the boards. - Jack detect support for simple card from Dylan Reid. - A bunch of small fixes and enhancements for the Freescale drivers. - New drivers for Analog Devices SSM4567, Cirrus Logic CS35L32, Everest Semiconductor ES8328 and Freescale cards using the ASRC in newer i.MX processors. - A few simple-card fixes, mostly cleanups but also a fix for - interaction between GPIO 0 and simple-card. - Misc - Virtuoso / Oxygen updates by Clemens - USB-audio: Yamaha MOTIF XF MIDI port name fixes - Conversion of kernel messages to standard dev_*() in ctxfi driver. -----BEGIN PGP SIGNATURE----- Version: GnuPG v2 iQIcBAABAgAGBQJUNrU8AAoJEGwxgFQ9KSmkxZYQAI7DgkrCx2S1dIHij99jtJGz FjhFSO/x8Jj0lgXkoCLRHXFgtq3iYjbyS9s0aokIpvAewD9SreVE977DsMqqZVJz 9FPOkv4keuxyJZ46mxJpYswDeazCjEYNFVbkYHhwsCiiyce8HyWMpe38tWrQfwSV loJYbnEfjpTxFc4JPaQK3pIICRofQCZJonWv20K25pm7L8yG29jtqFsMQWjDCONb ZVNwnvW61gl6ouuHincGGqVtj8pmkgKlU0l0bMgRNflRqRusrpQdobW56OEoM13H Tq7xMp5Yxzg7j9sM/QzL+VAksHc1u1aBzg8XZKXjk9PsmH26h1gq98W2BDKQkMzF U7MQaUks4x+apJcVVDoi5+15AOsyGoxNq9ahc0fe4ADTMSe94or78GaKptWMR+NK pA2pX2zwvool4TYj+AtcK8SNwfVeBjSua9eNnNpaNTKuwPIX6Vch0O6jaEbQZSaC 92JYhqiC6HsW5tbhN3afTmeHxelBCpQfWPLVtgEl/eIhY3B72/1ZXWCCqwY+Ur8E D3OCtuAjFnzvzr/gdHZWEnMu3HGt/xqOMVE0EHTQWokQpX2E3IF724YcttAzQakw wS1ppeWSO5l+TkplqcqurEA7Bq1mN6bO/q9UK+iduIiYmvtNI3fDPTlXXy2SxRUz QuIEpsIKuZFFumFksQd9 =S4IQ -----END PGP SIGNATURE----- Merge tag 'sound-3.18-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound Pull sound updates from Takashi Iwai: "This time it's a relatively calm update batch, but the amount isn't too small in the end. Here we go over some highlights: ALSA core: - One major change is the support of nonatomic PCM operations. This allows the trigger and other callbacks to call schedule(), which would be useful for mailbox type communications. Already some drivers (Digigram ones) have been converted to use together with threaded irqs as an example. - Improvement / fixes of DSD PCM format support HD-audio: - Large volume of rewrites are found in Realtek codec driver for converting Dell and HP quirks to generic forms. - Inverted dmic code cleanup from David. - Realtek COEF access has been optimized. - Now HD-audio jack infrastructure allows multiple callbacks, which fixes / simplifies the jack-dependent power controls on STAC/IDT and VIA codecs. - Many additional device-specific fixups as usual - A few deadcode cleanups, CA0132 code cleanup, etc. ASoC: - More componentization work from Lars-Peter, this time mainly cleaning up the suspend and bias level transition callbacks. - Real system support for the Intel drivers and a bunch of fixes and enhancements for the associated CODEC drivers, this is going to need a lot quirks over time due to the lack of any firmware description of the boards. - Jack detect support for simple card from Dylan Reid. - A bunch of small fixes and enhancements for the Freescale drivers. - New drivers for Analog Devices SSM4567, Cirrus Logic CS35L32, Everest Semiconductor ES8328 and Freescale cards using the ASRC in newer i.MX processors. - A few simple-card fixes, mostly cleanups but also a fix for interaction between GPIO 0 and simple-card. Misc: - Virtuoso / Oxygen updates by Clemens - USB-audio: Yamaha MOTIF XF MIDI port name fixes - Conversion of kernel messages to standard dev_*() in ctxfi driver" * tag 'sound-3.18-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound: (251 commits) ASoC: mc13783: Ensure we only try to dereference valid of_nodes ASoC: rockchip-i2s: fix infinite loop in rockchip_snd_txctrl ALSA: hda - Add dock port support to Thinkpad L440 (71aa:501e) ALSA: Allow pass NULL dev for snd_pci_quirk_lookup() ASoC: imx-es8328: Fix of_node_put() call with uninitialized object ASoC: soc-pcm: fix sig_bits determination in soc_pcm_apply_msb() ASoC: simple-card: Initialize headphone and mic GPIO numbers ASoC: imx-es8328: Fix missing return code in imx_es8328_probe() ALSA: hda - Add dock support for Thinkpad T440 (17aa:2212) ALSA: usb: caiaq: check for cdev->n_streams > 1 ASoC: 88pm860x-codec: Fix possibly missing string termination ASoC: core: fix use after free in snd_soc_remove_platform() ASoC: soc-dapm: fix use after free ALSA: hda - Make the inv dmic handling for Realtek use generic parser ALSA: hda - Add Inverted Internal mic for Samsung Ativ book 9 (NP900X3G) ALSA: hda - Add inverted internal mic for Asus Aspire 4830T ASoC: Intel: byt-rt5640: fix coccinelle warnings ASoC: fsl_esai doc: Add "fsl,vf610-esai" as compatible string ASoC: da732x: Remove unnecessary KERN_ERR in pr_err() ASoC: simple-card: Fix detect gpio documentation. ...
This commit is contained in:
commit
a2ce35273c
@ -2742,7 +2742,9 @@ struct _snd_pcm_runtime {
|
||||
|
||||
<para>
|
||||
Another note is that this callback is non-atomic
|
||||
(schedulable). This is important, because the
|
||||
(schedulable) as default, i.e. when no
|
||||
<structfield>nonatomic</structfield> flag set.
|
||||
This is important, because the
|
||||
<structfield>trigger</structfield> callback
|
||||
is atomic (non-schedulable). That is, mutexes or any
|
||||
schedule-related functions are not available in
|
||||
@ -2900,8 +2902,9 @@ struct _snd_pcm_runtime {
|
||||
</para>
|
||||
|
||||
<para>
|
||||
As mentioned, this callback is atomic. You cannot call
|
||||
functions which may sleep.
|
||||
As mentioned, this callback is atomic as default unless
|
||||
<structfield>nonatomic</structfield> flag set, and
|
||||
you cannot call functions which may sleep.
|
||||
The trigger callback should be as minimal as possible,
|
||||
just really triggering the DMA. The other stuff should be
|
||||
initialized hw_params and prepare callbacks properly
|
||||
@ -2936,7 +2939,7 @@ struct _snd_pcm_runtime {
|
||||
</para>
|
||||
|
||||
<para>
|
||||
This callback is also atomic.
|
||||
This callback is also atomic as default.
|
||||
</para>
|
||||
</section>
|
||||
|
||||
@ -2972,7 +2975,7 @@ struct _snd_pcm_runtime {
|
||||
is useful only for such a purpose.
|
||||
</para>
|
||||
<para>
|
||||
This callback is atomic.
|
||||
This callback is atomic as default.
|
||||
</para>
|
||||
</section>
|
||||
|
||||
@ -3175,6 +3178,21 @@ struct _snd_pcm_runtime {
|
||||
called with local interrupts disabled.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
The recent changes in PCM core code, however, allow all PCM
|
||||
operations to be non-atomic. This assumes that the all caller
|
||||
sides are in non-atomic contexts. For example, the function
|
||||
<function>snd_pcm_period_elapsed()</function> is called
|
||||
typically from the interrupt handler. But, if you set up the
|
||||
driver to use a threaded interrupt handler, this call can be in
|
||||
non-atomic context, too. In such a case, you can set
|
||||
<structfield>nonatomic</structfield> filed of
|
||||
<structname>snd_pcm</structname> object after creating it.
|
||||
When this flag is set, mutex and rwsem are used internally in
|
||||
the PCM core instead of spin and rwlocks, so that you can call
|
||||
all PCM functions safely in a non-atomic context.
|
||||
</para>
|
||||
|
||||
</section>
|
||||
<section id="pcm-interface-constraints">
|
||||
<title>Constraints</title>
|
||||
|
19
Documentation/devicetree/bindings/sound/adi,ssm2602.txt
Normal file
19
Documentation/devicetree/bindings/sound/adi,ssm2602.txt
Normal file
@ -0,0 +1,19 @@
|
||||
Analog Devices SSM2602, SSM2603 and SSM2604 I2S audio CODEC devices
|
||||
|
||||
SSM2602 support both I2C and SPI as the configuration interface,
|
||||
the selection is made by the MODE strap-in pin.
|
||||
SSM2603 and SSM2604 only support I2C as the configuration interface.
|
||||
|
||||
Required properties:
|
||||
|
||||
- compatible : One of "adi,ssm2602", "adi,ssm2603" or "adi,ssm2604"
|
||||
|
||||
- reg : the I2C address of the device for I2C, the chip select
|
||||
number for SPI.
|
||||
|
||||
Example:
|
||||
|
||||
ssm2602: ssm2602@1a {
|
||||
compatible = "adi,ssm2602";
|
||||
reg = <0x1a>;
|
||||
};
|
62
Documentation/devicetree/bindings/sound/cs35l32.txt
Normal file
62
Documentation/devicetree/bindings/sound/cs35l32.txt
Normal file
@ -0,0 +1,62 @@
|
||||
CS35L32 audio CODEC
|
||||
|
||||
Required properties:
|
||||
|
||||
- compatible : "cirrus,cs35l32"
|
||||
|
||||
- reg : the I2C address of the device for I2C. Address is determined by the level
|
||||
of the AD0 pin. Level 0 is 0x40 while Level 1 is 0x41.
|
||||
|
||||
- VA-supply, VP-supply : power supplies for the device,
|
||||
as covered in Documentation/devicetree/bindings/regulator/regulator.txt.
|
||||
|
||||
Optional properties:
|
||||
|
||||
- reset-gpios : a GPIO spec for the reset pin. If specified, it will be
|
||||
deasserted before communication to the codec starts.
|
||||
|
||||
- cirrus,boost-manager : Boost voltage control.
|
||||
0 = Automatically managed. Boost-converter output voltage is the higher
|
||||
of the two: Class G or adaptive LED voltage.
|
||||
1 = Automatically managed irrespective of audio, adapting for low-power
|
||||
dissipation when LEDs are ON, and operating in Fixed-Boost Bypass Mode
|
||||
if LEDs are OFF (VBST = VP).
|
||||
2 = (Default) Boost voltage fixed in Bypass Mode (VBST = VP).
|
||||
3 = Boost voltage fixed at 5 V.
|
||||
|
||||
- cirrus,sdout-datacfg : Data configuration for dual CS35L32 applications only.
|
||||
Determines the data packed in a two-CS35L32 configuration.
|
||||
0 = Left/right channels VMON[11:0], IMON[11:0], VPMON[7:0].
|
||||
1 = Left/right channels VMON[11:0], IMON[11:0], STATUS.
|
||||
2 = (Default) left/right channels VMON[15:0], IMON [15:0].
|
||||
3 = Left/right channels VPMON[7:0], STATUS.
|
||||
|
||||
- cirrus,sdout-share : SDOUT sharing. Determines whether one or two CS35L32
|
||||
devices are on board sharing SDOUT.
|
||||
0 = (Default) One IC.
|
||||
1 = Two IC's.
|
||||
|
||||
- cirrus,battery-recovery : Low battery nominal recovery threshold, rising VP.
|
||||
0 = 3.1V
|
||||
1 = 3.2V
|
||||
2 = 3.3V (Default)
|
||||
3 = 3.4V
|
||||
|
||||
- cirrus,battery-threshold : Low battery nominal threshold, falling VP.
|
||||
0 = 3.1V
|
||||
1 = 3.2V
|
||||
2 = 3.3V
|
||||
3 = 3.4V (Default)
|
||||
4 = 3.5V
|
||||
5 = 3.6V
|
||||
|
||||
Example:
|
||||
|
||||
codec: codec@40 {
|
||||
compatible = "cirrus,cs35l32";
|
||||
reg = <0x40>;
|
||||
reset-gpios = <&gpio 10 0>;
|
||||
cirrus,boost-manager = <0x03>;
|
||||
cirrus,sdout-datacfg = <0x02>;
|
||||
VA-supply = <®_audio>;
|
||||
};
|
38
Documentation/devicetree/bindings/sound/es8328.txt
Normal file
38
Documentation/devicetree/bindings/sound/es8328.txt
Normal file
@ -0,0 +1,38 @@
|
||||
Everest ES8328 audio CODEC
|
||||
|
||||
This device supports both I2C and SPI.
|
||||
|
||||
Required properties:
|
||||
|
||||
- compatible : "everest,es8328"
|
||||
- DVDD-supply : Regulator providing digital core supply voltage 1.8 - 3.6V
|
||||
- AVDD-supply : Regulator providing analog supply voltage 3.3V
|
||||
- PVDD-supply : Regulator providing digital IO supply voltage 1.8 - 3.6V
|
||||
- IPVDD-supply : Regulator providing analog output voltage 3.3V
|
||||
- clocks : A 22.5792 or 11.2896 MHz clock
|
||||
- reg : the I2C address of the device for I2C, the chip select number for SPI
|
||||
|
||||
Pins on the device (for linking into audio routes):
|
||||
|
||||
* LOUT1
|
||||
* LOUT2
|
||||
* ROUT1
|
||||
* ROUT2
|
||||
* LINPUT1
|
||||
* RINPUT1
|
||||
* LINPUT2
|
||||
* RINPUT2
|
||||
* Mic Bias
|
||||
|
||||
|
||||
Example:
|
||||
|
||||
codec: es8328@11 {
|
||||
compatible = "everest,es8328";
|
||||
DVDD-supply = <®_3p3v>;
|
||||
AVDD-supply = <®_3p3v>;
|
||||
PVDD-supply = <®_3p3v>;
|
||||
HPVDD-supply = <®_3p3v>;
|
||||
clocks = <&clks 169>;
|
||||
reg = <0x11>;
|
||||
};
|
@ -7,7 +7,8 @@ other DSPs. It has up to six transmitters and four receivers.
|
||||
|
||||
Required properties:
|
||||
|
||||
- compatible : Compatible list, must contain "fsl,imx35-esai".
|
||||
- compatible : Compatible list, must contain "fsl,imx35-esai" or
|
||||
"fsl,vf610-esai"
|
||||
|
||||
- reg : Offset and length of the register set for the device.
|
||||
|
||||
|
@ -58,13 +58,7 @@ Optional properties:
|
||||
Documentation/devicetree/bindings/dma/dma.txt.
|
||||
- dma-names: Two dmas have to be defined, "tx" and "rx", if fsl,imx-fiq
|
||||
is not defined.
|
||||
- fsl,mode: The operating mode for the SSI interface.
|
||||
"i2s-slave" - I2S mode, SSI is clock slave
|
||||
"i2s-master" - I2S mode, SSI is clock master
|
||||
"lj-slave" - left-justified mode, SSI is clock slave
|
||||
"lj-master" - l.j. mode, SSI is clock master
|
||||
"rj-slave" - right-justified mode, SSI is clock slave
|
||||
"rj-master" - r.j., SSI is clock master
|
||||
- fsl,mode: The operating mode for the AC97 interface only.
|
||||
"ac97-slave" - AC97 mode, SSI is clock slave
|
||||
"ac97-master" - AC97 mode, SSI is clock master
|
||||
|
||||
|
82
Documentation/devicetree/bindings/sound/fsl-asoc-card.txt
Normal file
82
Documentation/devicetree/bindings/sound/fsl-asoc-card.txt
Normal file
@ -0,0 +1,82 @@
|
||||
Freescale Generic ASoC Sound Card with ASRC support
|
||||
|
||||
The Freescale Generic ASoC Sound Card can be used, ideally, for all Freescale
|
||||
SoCs connecting with external CODECs.
|
||||
|
||||
The idea of this generic sound card is a bit like ASoC Simple Card. However,
|
||||
for Freescale SoCs (especially those released in recent years), most of them
|
||||
have ASRC (Documentation/devicetree/bindings/sound/fsl,asrc.txt) inside. And
|
||||
this is a specific feature that might be painstakingly controlled and merged
|
||||
into the Simple Card.
|
||||
|
||||
So having this generic sound card allows all Freescale SoC users to benefit
|
||||
from the simplification of a new card support and the capability of the wide
|
||||
sample rates support through ASRC.
|
||||
|
||||
Note: The card is initially designed for those sound cards who use I2S and
|
||||
PCM DAI formats. However, it'll be also possible to support those non
|
||||
I2S/PCM type sound cards, such as S/PDIF audio and HDMI audio, as long
|
||||
as the driver has been properly upgraded.
|
||||
|
||||
|
||||
The compatible list for this generic sound card currently:
|
||||
"fsl,imx-audio-cs42888"
|
||||
|
||||
"fsl,imx-audio-wm8962"
|
||||
(compatible with Documentation/devicetree/bindings/sound/imx-audio-wm8962.txt)
|
||||
|
||||
"fsl,imx-audio-sgtl5000"
|
||||
(compatible with Documentation/devicetree/bindings/sound/imx-audio-sgtl5000.txt)
|
||||
|
||||
Required properties:
|
||||
|
||||
- compatible : Contains one of entries in the compatible list.
|
||||
|
||||
- model : The user-visible name of this sound complex
|
||||
|
||||
- audio-cpu : The phandle of an CPU DAI controller
|
||||
|
||||
- audio-codec : The phandle of an audio codec
|
||||
|
||||
- audio-routing : A list of the connections between audio components.
|
||||
Each entry is a pair of strings, the first being the
|
||||
connection's sink, the second being the connection's
|
||||
source. There're a few pre-designed board connectors:
|
||||
* Line Out Jack
|
||||
* Line In Jack
|
||||
* Headphone Jack
|
||||
* Mic Jack
|
||||
* Ext Spk
|
||||
* AMIC (stands for Analog Microphone Jack)
|
||||
* DMIC (stands for Digital Microphone Jack)
|
||||
|
||||
Note: The "Mic Jack" and "AMIC" are redundant while
|
||||
coexsiting in order to support the old bindings
|
||||
of wm8962 and sgtl5000.
|
||||
|
||||
Optional properties:
|
||||
|
||||
- audio-asrc : The phandle of ASRC. It can be absent if there's no
|
||||
need to add ASRC support via DPCM.
|
||||
|
||||
Example:
|
||||
sound-cs42888 {
|
||||
compatible = "fsl,imx-audio-cs42888";
|
||||
model = "cs42888-audio";
|
||||
audio-cpu = <&esai>;
|
||||
audio-asrc = <&asrc>;
|
||||
audio-codec = <&cs42888>;
|
||||
audio-routing =
|
||||
"Line Out Jack", "AOUT1L",
|
||||
"Line Out Jack", "AOUT1R",
|
||||
"Line Out Jack", "AOUT2L",
|
||||
"Line Out Jack", "AOUT2R",
|
||||
"Line Out Jack", "AOUT3L",
|
||||
"Line Out Jack", "AOUT3R",
|
||||
"Line Out Jack", "AOUT4L",
|
||||
"Line Out Jack", "AOUT4R",
|
||||
"AIN1L", "Line In Jack",
|
||||
"AIN1R", "Line In Jack",
|
||||
"AIN2L", "Line In Jack",
|
||||
"AIN2R", "Line In Jack";
|
||||
};
|
@ -18,12 +18,26 @@ Required properties:
|
||||
- pinctrl-names: Must contain a "default" entry.
|
||||
- pinctrl-NNN: One property must exist for each entry in pinctrl-names.
|
||||
See ../pinctrl/pinctrl-bindings.txt for details of the property values.
|
||||
- big-endian-regs: If this property is absent, the little endian mode will
|
||||
be in use as default, or the big endian mode will be in use for all the
|
||||
device registers.
|
||||
- big-endian-data: If this property is absent, the little endian mode will
|
||||
be in use as default, or the big endian mode will be in use for all the
|
||||
fifo data.
|
||||
- big-endian: Boolean property, required if all the FTM_PWM registers
|
||||
are big-endian rather than little-endian.
|
||||
- lsb-first: Configures whether the LSB or the MSB is transmitted first for
|
||||
the fifo data. If this property is absent, the MSB is transmitted first as
|
||||
default, or the LSB is transmitted first.
|
||||
- fsl,sai-synchronous-rx: This is a boolean property. If present, indicating
|
||||
that SAI will work in the synchronous mode (sync Tx with Rx) which means
|
||||
both the transimitter and receiver will send and receive data by following
|
||||
receiver's bit clocks and frame sync clocks.
|
||||
- fsl,sai-asynchronous: This is a boolean property. If present, indicating
|
||||
that SAI will work in the asynchronous mode, which means both transimitter
|
||||
and receiver will send and receive data by following their own bit clocks
|
||||
and frame sync clocks separately.
|
||||
|
||||
Note:
|
||||
- If both fsl,sai-asynchronous and fsl,sai-synchronous-rx are absent, the
|
||||
default synchronous mode (sync Rx with Tx) will be used, which means both
|
||||
transimitter and receiver will send and receive data by following clocks
|
||||
of transimitter.
|
||||
- fsl,sai-asynchronous and fsl,sai-synchronous-rx are exclusive.
|
||||
|
||||
Example:
|
||||
sai2: sai@40031000 {
|
||||
@ -38,6 +52,6 @@ sai2: sai@40031000 {
|
||||
dma-names = "tx", "rx";
|
||||
dmas = <&edma0 0 VF610_EDMA_MUXID0_SAI2_TX>,
|
||||
<&edma0 0 VF610_EDMA_MUXID0_SAI2_RX>;
|
||||
big-endian-regs;
|
||||
big-endian-data;
|
||||
big-endian;
|
||||
lsb-first;
|
||||
};
|
||||
|
60
Documentation/devicetree/bindings/sound/imx-audio-es8328.txt
Normal file
60
Documentation/devicetree/bindings/sound/imx-audio-es8328.txt
Normal file
@ -0,0 +1,60 @@
|
||||
Freescale i.MX audio complex with ES8328 codec
|
||||
|
||||
Required properties:
|
||||
- compatible : "fsl,imx-audio-es8328"
|
||||
- model : The user-visible name of this sound complex
|
||||
- ssi-controller : The phandle of the i.MX SSI controller
|
||||
- jack-gpio : Optional GPIO for headphone jack
|
||||
- audio-amp-supply : Power regulator for speaker amps
|
||||
- audio-codec : The phandle of the ES8328 audio codec
|
||||
- audio-routing : A list of the connections between audio components.
|
||||
Each entry is a pair of strings, the first being the
|
||||
connection's sink, the second being the connection's
|
||||
source. Valid names could be power supplies, ES8328
|
||||
pins, and the jacks on the board:
|
||||
|
||||
Power supplies:
|
||||
* audio-amp
|
||||
|
||||
ES8328 pins:
|
||||
* LOUT1
|
||||
* LOUT2
|
||||
* ROUT1
|
||||
* ROUT2
|
||||
* LINPUT1
|
||||
* LINPUT2
|
||||
* RINPUT1
|
||||
* RINPUT2
|
||||
* Mic PGA
|
||||
|
||||
Board connectors:
|
||||
* Headphone
|
||||
* Speaker
|
||||
* Mic Jack
|
||||
- mux-int-port : The internal port of the i.MX audio muxer (AUDMUX)
|
||||
- mux-ext-port : The external port of the i.MX audio muxer (AUDMIX)
|
||||
|
||||
Note: The AUDMUX port numbering should start at 1, which is consistent with
|
||||
hardware manual.
|
||||
|
||||
Example:
|
||||
|
||||
sound {
|
||||
compatible = "fsl,imx-audio-es8328";
|
||||
model = "imx-audio-es8328";
|
||||
ssi-controller = <&ssi1>;
|
||||
audio-codec = <&codec>;
|
||||
jack-gpio = <&gpio5 15 0>;
|
||||
audio-amp-supply = <®_audio_amp>;
|
||||
audio-routing =
|
||||
"Speaker", "LOUT2",
|
||||
"Speaker", "ROUT2",
|
||||
"Speaker", "audio-amp",
|
||||
"Headphone", "ROUT1",
|
||||
"Headphone", "LOUT1",
|
||||
"LINPUT1", "Mic Jack",
|
||||
"RINPUT1", "Mic Jack",
|
||||
"Mic Jack", "Mic Bias";
|
||||
mux-int-port = <1>;
|
||||
mux-ext-port = <3>;
|
||||
};
|
@ -25,6 +25,7 @@ Required properties:
|
||||
|
||||
Optional properties:
|
||||
- nvidia,hp-det-gpios : The GPIO that detect headphones are plugged in
|
||||
- nvidia,mic-det-gpios : The GPIO that detect microphones are plugged in
|
||||
|
||||
Example:
|
||||
|
||||
|
59
Documentation/devicetree/bindings/sound/rt5677.txt
Normal file
59
Documentation/devicetree/bindings/sound/rt5677.txt
Normal file
@ -0,0 +1,59 @@
|
||||
RT5677 audio CODEC
|
||||
|
||||
This device supports I2C only.
|
||||
|
||||
Required properties:
|
||||
|
||||
- compatible : "realtek,rt5677".
|
||||
|
||||
- reg : The I2C address of the device.
|
||||
|
||||
- interrupts : The CODEC's interrupt output.
|
||||
|
||||
- gpio-controller : Indicates this device is a GPIO controller.
|
||||
|
||||
- #gpio-cells : Should be two. The first cell is the pin number and the
|
||||
second cell is used to specify optional parameters (currently unused).
|
||||
|
||||
Optional properties:
|
||||
|
||||
- realtek,pow-ldo2-gpio : The GPIO that controls the CODEC's POW_LDO2 pin.
|
||||
|
||||
- realtek,in1-differential
|
||||
- realtek,in2-differential
|
||||
- realtek,lout1-differential
|
||||
- realtek,lout2-differential
|
||||
- realtek,lout3-differential
|
||||
Boolean. Indicate MIC1/2 input and LOUT1/2/3 outputs are differential,
|
||||
rather than single-ended.
|
||||
|
||||
Pins on the device (for linking into audio routes):
|
||||
|
||||
* IN1P
|
||||
* IN1N
|
||||
* IN2P
|
||||
* IN2N
|
||||
* MICBIAS1
|
||||
* DMIC1
|
||||
* DMIC2
|
||||
* DMIC3
|
||||
* DMIC4
|
||||
* LOUT1
|
||||
* LOUT2
|
||||
* LOUT3
|
||||
|
||||
Example:
|
||||
|
||||
rt5677 {
|
||||
compatible = "realtek,rt5677";
|
||||
reg = <0x2c>;
|
||||
interrupt-parent = <&gpio>;
|
||||
interrupts = <TEGRA_GPIO(W, 3) GPIO_ACTIVE_HIGH>;
|
||||
|
||||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
|
||||
realtek,pow-ldo2-gpio =
|
||||
<&gpio TEGRA_GPIO(V, 3) GPIO_ACTIVE_HIGH>;
|
||||
realtek,in1-differential = "true";
|
||||
};
|
@ -17,6 +17,10 @@ Optional properties:
|
||||
source.
|
||||
- simple-audio-card,mclk-fs : Multiplication factor between stream rate and codec
|
||||
mclk.
|
||||
- simple-audio-card,hp-det-gpio : Reference to GPIO that signals when
|
||||
headphones are attached.
|
||||
- simple-audio-card,mic-det-gpio : Reference to GPIO that signals when
|
||||
a microphone is attached.
|
||||
|
||||
Optional subnodes:
|
||||
|
||||
|
15
Documentation/devicetree/bindings/sound/ssm4567.txt
Normal file
15
Documentation/devicetree/bindings/sound/ssm4567.txt
Normal file
@ -0,0 +1,15 @@
|
||||
Analog Devices SSM4567 audio amplifier
|
||||
|
||||
This device supports I2C only.
|
||||
|
||||
Required properties:
|
||||
- compatible : Must be "adi,ssm4567"
|
||||
- reg : the I2C address of the device. This will either be 0x34 (LR_SEL/ADDR connected to AGND),
|
||||
0x35 (LR_SEL/ADDR connected to IOVDD) or 0x36 (LR_SEL/ADDR open).
|
||||
|
||||
Example:
|
||||
|
||||
ssm4567: ssm4567@34 {
|
||||
compatible = "adi,ssm4567";
|
||||
reg = <0x34>;
|
||||
};
|
@ -51,6 +51,7 @@ epfl Ecole Polytechnique Fédérale de Lausanne
|
||||
epson Seiko Epson Corp.
|
||||
est ESTeem Wireless Modems
|
||||
eukrea Eukréa Electromatique
|
||||
everest Everest Semiconductor Co. Ltd.
|
||||
excito Excito
|
||||
fcs Fairchild Semiconductor
|
||||
fsl Freescale Semiconductor
|
||||
|
26
include/dt-bindings/sound/cs35l32.h
Normal file
26
include/dt-bindings/sound/cs35l32.h
Normal file
@ -0,0 +1,26 @@
|
||||
#ifndef __DT_CS35L32_H
|
||||
#define __DT_CS35L32_H
|
||||
|
||||
#define CS35L32_BOOST_MGR_AUTO 0
|
||||
#define CS35L32_BOOST_MGR_AUTO_AUDIO 1
|
||||
#define CS35L32_BOOST_MGR_BYPASS 2
|
||||
#define CS35L32_BOOST_MGR_FIXED 3
|
||||
|
||||
#define CS35L32_DATA_CFG_LR_VP 0
|
||||
#define CS35L32_DATA_CFG_LR_STAT 1
|
||||
#define CS35L32_DATA_CFG_LR 2
|
||||
#define CS35L32_DATA_CFG_LR_VPSTAT 3
|
||||
|
||||
#define CS35L32_BATT_THRESH_3_1V 0
|
||||
#define CS35L32_BATT_THRESH_3_2V 1
|
||||
#define CS35L32_BATT_THRESH_3_3V 2
|
||||
#define CS35L32_BATT_THRESH_3_4V 3
|
||||
|
||||
#define CS35L32_BATT_RECOV_3_1V 0
|
||||
#define CS35L32_BATT_RECOV_3_2V 1
|
||||
#define CS35L32_BATT_RECOV_3_3V 2
|
||||
#define CS35L32_BATT_RECOV_3_4V 3
|
||||
#define CS35L32_BATT_RECOV_3_5V 4
|
||||
#define CS35L32_BATT_RECOV_3_6V 5
|
||||
|
||||
#endif /* __DT_CS35L32_H */
|
@ -183,6 +183,7 @@ struct snd_pcm_ops {
|
||||
#define SNDRV_PCM_FMTBIT_G723_40_1B _SNDRV_PCM_FMTBIT(G723_40_1B)
|
||||
#define SNDRV_PCM_FMTBIT_DSD_U8 _SNDRV_PCM_FMTBIT(DSD_U8)
|
||||
#define SNDRV_PCM_FMTBIT_DSD_U16_LE _SNDRV_PCM_FMTBIT(DSD_U16_LE)
|
||||
#define SNDRV_PCM_FMTBIT_DSD_U32_LE _SNDRV_PCM_FMTBIT(DSD_U32_LE)
|
||||
|
||||
#ifdef SNDRV_LITTLE_ENDIAN
|
||||
#define SNDRV_PCM_FMTBIT_S16 SNDRV_PCM_FMTBIT_S16_LE
|
||||
@ -365,6 +366,7 @@ struct snd_pcm_runtime {
|
||||
|
||||
struct snd_pcm_group { /* keep linked substreams */
|
||||
spinlock_t lock;
|
||||
struct mutex mutex;
|
||||
struct list_head substreams;
|
||||
int count;
|
||||
};
|
||||
@ -460,6 +462,7 @@ struct snd_pcm {
|
||||
void (*private_free) (struct snd_pcm *pcm);
|
||||
struct device *dev; /* actual hw device this belongs to */
|
||||
bool internal; /* pcm is for internal use only */
|
||||
bool nonatomic; /* whole PCM operations are in non-atomic context */
|
||||
#if defined(CONFIG_SND_PCM_OSS) || defined(CONFIG_SND_PCM_OSS_MODULE)
|
||||
struct snd_pcm_oss oss;
|
||||
#endif
|
||||
@ -492,8 +495,6 @@ int snd_pcm_notify(struct snd_pcm_notify *notify, int nfree);
|
||||
* Native I/O
|
||||
*/
|
||||
|
||||
extern rwlock_t snd_pcm_link_rwlock;
|
||||
|
||||
int snd_pcm_info(struct snd_pcm_substream *substream, struct snd_pcm_info *info);
|
||||
int snd_pcm_info_user(struct snd_pcm_substream *substream,
|
||||
struct snd_pcm_info __user *info);
|
||||
@ -537,41 +538,18 @@ static inline int snd_pcm_stream_linked(struct snd_pcm_substream *substream)
|
||||
return substream->group != &substream->self_group;
|
||||
}
|
||||
|
||||
static inline void snd_pcm_stream_lock(struct snd_pcm_substream *substream)
|
||||
{
|
||||
read_lock(&snd_pcm_link_rwlock);
|
||||
spin_lock(&substream->self_group.lock);
|
||||
}
|
||||
|
||||
static inline void snd_pcm_stream_unlock(struct snd_pcm_substream *substream)
|
||||
{
|
||||
spin_unlock(&substream->self_group.lock);
|
||||
read_unlock(&snd_pcm_link_rwlock);
|
||||
}
|
||||
|
||||
static inline void snd_pcm_stream_lock_irq(struct snd_pcm_substream *substream)
|
||||
{
|
||||
read_lock_irq(&snd_pcm_link_rwlock);
|
||||
spin_lock(&substream->self_group.lock);
|
||||
}
|
||||
|
||||
static inline void snd_pcm_stream_unlock_irq(struct snd_pcm_substream *substream)
|
||||
{
|
||||
spin_unlock(&substream->self_group.lock);
|
||||
read_unlock_irq(&snd_pcm_link_rwlock);
|
||||
}
|
||||
|
||||
#define snd_pcm_stream_lock_irqsave(substream, flags) \
|
||||
do { \
|
||||
read_lock_irqsave(&snd_pcm_link_rwlock, (flags)); \
|
||||
spin_lock(&substream->self_group.lock); \
|
||||
} while (0)
|
||||
|
||||
#define snd_pcm_stream_unlock_irqrestore(substream, flags) \
|
||||
do { \
|
||||
spin_unlock(&substream->self_group.lock); \
|
||||
read_unlock_irqrestore(&snd_pcm_link_rwlock, (flags)); \
|
||||
} while (0)
|
||||
void snd_pcm_stream_lock(struct snd_pcm_substream *substream);
|
||||
void snd_pcm_stream_unlock(struct snd_pcm_substream *substream);
|
||||
void snd_pcm_stream_lock_irq(struct snd_pcm_substream *substream);
|
||||
void snd_pcm_stream_unlock_irq(struct snd_pcm_substream *substream);
|
||||
unsigned long _snd_pcm_stream_lock_irqsave(struct snd_pcm_substream *substream);
|
||||
#define snd_pcm_stream_lock_irqsave(substream, flags) \
|
||||
do { \
|
||||
typecheck(unsigned long, flags); \
|
||||
flags = _snd_pcm_stream_lock_irqsave(substream); \
|
||||
} while (0)
|
||||
void snd_pcm_stream_unlock_irqrestore(struct snd_pcm_substream *substream,
|
||||
unsigned long flags);
|
||||
|
||||
#define snd_pcm_group_for_each_entry(s, substream) \
|
||||
list_for_each_entry(s, &substream->group->substreams, link_list)
|
||||
|
@ -20,6 +20,9 @@ struct rt5645_platform_data {
|
||||
/* 0 = IN2N; 1 = GPIO5; 2 = GPIO11 */
|
||||
unsigned int dmic2_data_pin;
|
||||
/* 0 = IN2P; 1 = GPIO6; 2 = GPIO10; 3 = GPIO12 */
|
||||
|
||||
unsigned int hp_det_gpio;
|
||||
bool gpio_hp_det_active_high;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@ -12,10 +12,21 @@
|
||||
#ifndef __LINUX_SND_RT5677_H
|
||||
#define __LINUX_SND_RT5677_H
|
||||
|
||||
enum rt5677_dmic2_clk {
|
||||
RT5677_DMIC_CLK1 = 0,
|
||||
RT5677_DMIC_CLK2 = 1,
|
||||
};
|
||||
|
||||
|
||||
struct rt5677_platform_data {
|
||||
/* IN1 IN2 can optionally be differential */
|
||||
/* IN1/IN2/LOUT1/LOUT2/LOUT3 can optionally be differential */
|
||||
bool in1_diff;
|
||||
bool in2_diff;
|
||||
bool lout1_diff;
|
||||
bool lout2_diff;
|
||||
bool lout3_diff;
|
||||
/* DMIC2 clock source selection */
|
||||
enum rt5677_dmic2_clk dmic2_clk_pin;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@ -432,6 +432,7 @@ int snd_soc_dapm_force_enable_pin_unlocked(struct snd_soc_dapm_context *dapm,
|
||||
int snd_soc_dapm_ignore_suspend(struct snd_soc_dapm_context *dapm,
|
||||
const char *pin);
|
||||
void snd_soc_dapm_auto_nc_pins(struct snd_soc_card *card);
|
||||
unsigned int dapm_kcontrol_get_value(const struct snd_kcontrol *kcontrol);
|
||||
|
||||
/* Mostly internal - should not normally be used */
|
||||
void dapm_mark_io_dirty(struct snd_soc_dapm_context *dapm);
|
||||
@ -587,13 +588,13 @@ struct snd_soc_dapm_context {
|
||||
enum snd_soc_bias_level suspend_bias_level;
|
||||
struct delayed_work delayed_work;
|
||||
unsigned int idle_bias_off:1; /* Use BIAS_OFF instead of STANDBY */
|
||||
|
||||
/* Go to BIAS_OFF in suspend if the DAPM context is idle */
|
||||
unsigned int suspend_bias_off:1;
|
||||
void (*seq_notifier)(struct snd_soc_dapm_context *,
|
||||
enum snd_soc_dapm_type, int);
|
||||
|
||||
struct device *dev; /* from parent - for debug */
|
||||
struct snd_soc_component *component; /* parent component */
|
||||
struct snd_soc_codec *codec; /* parent codec */
|
||||
struct snd_soc_card *card; /* parent card */
|
||||
|
||||
/* used during DAPM updates */
|
||||
|
@ -690,6 +690,17 @@ struct snd_soc_compr_ops {
|
||||
struct snd_soc_component_driver {
|
||||
const char *name;
|
||||
|
||||
/* Default control and setup, added after probe() is run */
|
||||
const struct snd_kcontrol_new *controls;
|
||||
unsigned int num_controls;
|
||||
const struct snd_soc_dapm_widget *dapm_widgets;
|
||||
unsigned int num_dapm_widgets;
|
||||
const struct snd_soc_dapm_route *dapm_routes;
|
||||
unsigned int num_dapm_routes;
|
||||
|
||||
int (*probe)(struct snd_soc_component *);
|
||||
void (*remove)(struct snd_soc_component *);
|
||||
|
||||
/* DT */
|
||||
int (*of_xlate_dai_name)(struct snd_soc_component *component,
|
||||
struct of_phandle_args *args,
|
||||
@ -697,6 +708,10 @@ struct snd_soc_component_driver {
|
||||
void (*seq_notifier)(struct snd_soc_component *, enum snd_soc_dapm_type,
|
||||
int subseq);
|
||||
int (*stream_event)(struct snd_soc_component *, int event);
|
||||
|
||||
/* probe ordering - for components with runtime dependencies */
|
||||
int probe_order;
|
||||
int remove_order;
|
||||
};
|
||||
|
||||
struct snd_soc_component {
|
||||
@ -710,6 +725,7 @@ struct snd_soc_component {
|
||||
|
||||
unsigned int ignore_pmdown_time:1; /* pmdown_time is ignored at stop */
|
||||
unsigned int registered_as_component:1;
|
||||
unsigned int probed:1;
|
||||
|
||||
struct list_head list;
|
||||
|
||||
@ -728,9 +744,35 @@ struct snd_soc_component {
|
||||
|
||||
struct mutex io_mutex;
|
||||
|
||||
#ifdef CONFIG_DEBUG_FS
|
||||
struct dentry *debugfs_root;
|
||||
#endif
|
||||
|
||||
/*
|
||||
* DO NOT use any of the fields below in drivers, they are temporary and
|
||||
* are going to be removed again soon. If you use them in driver code the
|
||||
* driver will be marked as BROKEN when these fields are removed.
|
||||
*/
|
||||
|
||||
/* Don't use these, use snd_soc_component_get_dapm() */
|
||||
struct snd_soc_dapm_context dapm;
|
||||
struct snd_soc_dapm_context *dapm_ptr;
|
||||
|
||||
const struct snd_kcontrol_new *controls;
|
||||
unsigned int num_controls;
|
||||
const struct snd_soc_dapm_widget *dapm_widgets;
|
||||
unsigned int num_dapm_widgets;
|
||||
const struct snd_soc_dapm_route *dapm_routes;
|
||||
unsigned int num_dapm_routes;
|
||||
struct snd_soc_codec *codec;
|
||||
|
||||
int (*probe)(struct snd_soc_component *);
|
||||
void (*remove)(struct snd_soc_component *);
|
||||
|
||||
#ifdef CONFIG_DEBUG_FS
|
||||
void (*init_debugfs)(struct snd_soc_component *component);
|
||||
const char *debugfs_prefix;
|
||||
#endif
|
||||
};
|
||||
|
||||
/* SoC Audio Codec device */
|
||||
@ -746,11 +788,9 @@ struct snd_soc_codec {
|
||||
struct snd_ac97 *ac97; /* for ad-hoc ac97 devices */
|
||||
unsigned int cache_bypass:1; /* Suppress access to the cache */
|
||||
unsigned int suspended:1; /* Codec is in suspend PM state */
|
||||
unsigned int probed:1; /* Codec has been probed */
|
||||
unsigned int ac97_registered:1; /* Codec has been AC97 registered */
|
||||
unsigned int ac97_created:1; /* Codec has been created by SoC */
|
||||
unsigned int cache_init:1; /* codec cache has been initialized */
|
||||
u32 cache_only; /* Suppress writes to hardware */
|
||||
u32 cache_sync; /* Cache needs to be synced to hardware */
|
||||
|
||||
/* codec IO */
|
||||
@ -766,7 +806,6 @@ struct snd_soc_codec {
|
||||
struct snd_soc_dapm_context dapm;
|
||||
|
||||
#ifdef CONFIG_DEBUG_FS
|
||||
struct dentry *debugfs_codec_root;
|
||||
struct dentry *debugfs_reg;
|
||||
#endif
|
||||
};
|
||||
@ -808,15 +847,12 @@ struct snd_soc_codec_driver {
|
||||
int (*set_bias_level)(struct snd_soc_codec *,
|
||||
enum snd_soc_bias_level level);
|
||||
bool idle_bias_off;
|
||||
bool suspend_bias_off;
|
||||
|
||||
void (*seq_notifier)(struct snd_soc_dapm_context *,
|
||||
enum snd_soc_dapm_type, int);
|
||||
|
||||
bool ignore_pmdown_time; /* Doesn't benefit from pmdown delay */
|
||||
|
||||
/* probe ordering - for components with runtime dependencies */
|
||||
int probe_order;
|
||||
int remove_order;
|
||||
};
|
||||
|
||||
/* SoC platform interface */
|
||||
@ -832,14 +868,6 @@ struct snd_soc_platform_driver {
|
||||
int (*pcm_new)(struct snd_soc_pcm_runtime *);
|
||||
void (*pcm_free)(struct snd_pcm *);
|
||||
|
||||
/* Default control and setup, added after probe() is run */
|
||||
const struct snd_kcontrol_new *controls;
|
||||
int num_controls;
|
||||
const struct snd_soc_dapm_widget *dapm_widgets;
|
||||
int num_dapm_widgets;
|
||||
const struct snd_soc_dapm_route *dapm_routes;
|
||||
int num_dapm_routes;
|
||||
|
||||
/*
|
||||
* For platform caused delay reporting.
|
||||
* Optional.
|
||||
@ -853,13 +881,6 @@ struct snd_soc_platform_driver {
|
||||
/* platform stream compress ops */
|
||||
const struct snd_compr_ops *compr_ops;
|
||||
|
||||
/* probe ordering - for components with runtime dependencies */
|
||||
int probe_order;
|
||||
int remove_order;
|
||||
|
||||
/* platform IO - used for platform DAPM */
|
||||
unsigned int (*read)(struct snd_soc_platform *, unsigned int);
|
||||
int (*write)(struct snd_soc_platform *, unsigned int, unsigned int);
|
||||
int (*bespoke_trigger)(struct snd_pcm_substream *, int);
|
||||
};
|
||||
|
||||
@ -874,15 +895,10 @@ struct snd_soc_platform {
|
||||
const struct snd_soc_platform_driver *driver;
|
||||
|
||||
unsigned int suspended:1; /* platform is suspended */
|
||||
unsigned int probed:1;
|
||||
|
||||
struct list_head list;
|
||||
|
||||
struct snd_soc_component component;
|
||||
|
||||
#ifdef CONFIG_DEBUG_FS
|
||||
struct dentry *debugfs_platform_root;
|
||||
#endif
|
||||
};
|
||||
|
||||
struct snd_soc_dai_link {
|
||||
@ -897,7 +913,7 @@ struct snd_soc_dai_link {
|
||||
* only for codec to codec links, or systems using device tree.
|
||||
*/
|
||||
const char *cpu_name;
|
||||
const struct device_node *cpu_of_node;
|
||||
struct device_node *cpu_of_node;
|
||||
/*
|
||||
* You MAY specify the DAI name of the CPU DAI. If this information is
|
||||
* omitted, the CPU-side DAI is matched using .cpu_name/.cpu_of_node
|
||||
@ -909,7 +925,7 @@ struct snd_soc_dai_link {
|
||||
* DT/OF node, but not both.
|
||||
*/
|
||||
const char *codec_name;
|
||||
const struct device_node *codec_of_node;
|
||||
struct device_node *codec_of_node;
|
||||
/* You MUST specify the DAI name within the codec */
|
||||
const char *codec_dai_name;
|
||||
|
||||
@ -922,7 +938,7 @@ struct snd_soc_dai_link {
|
||||
* do not need a platform.
|
||||
*/
|
||||
const char *platform_name;
|
||||
const struct device_node *platform_of_node;
|
||||
struct device_node *platform_of_node;
|
||||
int be_id; /* optional ID for machine driver BE identification */
|
||||
|
||||
const struct snd_soc_pcm_stream *params;
|
||||
@ -994,7 +1010,7 @@ struct snd_soc_aux_dev {
|
||||
const struct device_node *codec_of_node;
|
||||
|
||||
/* codec/machine specific init - e.g. add machine controls */
|
||||
int (*init)(struct snd_soc_dapm_context *dapm);
|
||||
int (*init)(struct snd_soc_component *component);
|
||||
};
|
||||
|
||||
/* SoC card */
|
||||
@ -1112,6 +1128,7 @@ struct snd_soc_pcm_runtime {
|
||||
struct snd_soc_platform *platform;
|
||||
struct snd_soc_dai *codec_dai;
|
||||
struct snd_soc_dai *cpu_dai;
|
||||
struct snd_soc_component *component; /* Only valid for AUX dev rtds */
|
||||
|
||||
struct snd_soc_dai **codec_dais;
|
||||
unsigned int num_codecs;
|
||||
@ -1260,9 +1277,6 @@ void snd_soc_component_async_complete(struct snd_soc_component *component);
|
||||
int snd_soc_component_test_bits(struct snd_soc_component *component,
|
||||
unsigned int reg, unsigned int mask, unsigned int value);
|
||||
|
||||
int snd_soc_component_init_io(struct snd_soc_component *component,
|
||||
struct regmap *regmap);
|
||||
|
||||
/* device driver data */
|
||||
|
||||
static inline void snd_soc_card_set_drvdata(struct snd_soc_card *card,
|
||||
@ -1276,26 +1290,37 @@ static inline void *snd_soc_card_get_drvdata(struct snd_soc_card *card)
|
||||
return card->drvdata;
|
||||
}
|
||||
|
||||
static inline void snd_soc_component_set_drvdata(struct snd_soc_component *c,
|
||||
void *data)
|
||||
{
|
||||
dev_set_drvdata(c->dev, data);
|
||||
}
|
||||
|
||||
static inline void *snd_soc_component_get_drvdata(struct snd_soc_component *c)
|
||||
{
|
||||
return dev_get_drvdata(c->dev);
|
||||
}
|
||||
|
||||
static inline void snd_soc_codec_set_drvdata(struct snd_soc_codec *codec,
|
||||
void *data)
|
||||
{
|
||||
dev_set_drvdata(codec->dev, data);
|
||||
snd_soc_component_set_drvdata(&codec->component, data);
|
||||
}
|
||||
|
||||
static inline void *snd_soc_codec_get_drvdata(struct snd_soc_codec *codec)
|
||||
{
|
||||
return dev_get_drvdata(codec->dev);
|
||||
return snd_soc_component_get_drvdata(&codec->component);
|
||||
}
|
||||
|
||||
static inline void snd_soc_platform_set_drvdata(struct snd_soc_platform *platform,
|
||||
void *data)
|
||||
{
|
||||
dev_set_drvdata(platform->dev, data);
|
||||
snd_soc_component_set_drvdata(&platform->component, data);
|
||||
}
|
||||
|
||||
static inline void *snd_soc_platform_get_drvdata(struct snd_soc_platform *platform)
|
||||
{
|
||||
return dev_get_drvdata(platform->dev);
|
||||
return snd_soc_component_get_drvdata(&platform->component);
|
||||
}
|
||||
|
||||
static inline void snd_soc_pcm_set_drvdata(struct snd_soc_pcm_runtime *rtd,
|
||||
|
@ -80,8 +80,6 @@ struct vx_pipe {
|
||||
|
||||
unsigned int references; /* an output pipe may be used for monitoring and/or playback */
|
||||
struct vx_pipe *monitoring_pipe; /* pointer to the monitoring pipe (capture pipe only)*/
|
||||
|
||||
struct tasklet_struct start_tq;
|
||||
};
|
||||
|
||||
struct vx_core;
|
||||
@ -165,9 +163,7 @@ struct vx_core {
|
||||
struct snd_vx_hardware *hw;
|
||||
struct snd_vx_ops *ops;
|
||||
|
||||
spinlock_t lock;
|
||||
spinlock_t irq_lock;
|
||||
struct tasklet_struct tq;
|
||||
struct mutex lock;
|
||||
|
||||
unsigned int chip_status;
|
||||
unsigned int pcm_running;
|
||||
@ -223,6 +219,7 @@ void snd_vx_free_firmware(struct vx_core *chip);
|
||||
* interrupt handler; exported for pcmcia
|
||||
*/
|
||||
irqreturn_t snd_vx_irq_handler(int irq, void *dev);
|
||||
irqreturn_t snd_vx_threaded_irq_handler(int irq, void *dev);
|
||||
|
||||
/*
|
||||
* lowlevel functions
|
||||
|
@ -175,7 +175,7 @@ TRACE_EVENT(snd_soc_dapm_output_path,
|
||||
__entry->path_sink = (long)path->sink;
|
||||
),
|
||||
|
||||
TP_printk("%c%s -> %s -> %s\n",
|
||||
TP_printk("%c%s -> %s -> %s",
|
||||
(int) __entry->path_sink &&
|
||||
(int) __entry->path_connect ? '*' : ' ',
|
||||
__get_str(wname), __get_str(pname), __get_str(psname))
|
||||
@ -204,7 +204,7 @@ TRACE_EVENT(snd_soc_dapm_input_path,
|
||||
__entry->path_source = (long)path->source;
|
||||
),
|
||||
|
||||
TP_printk("%c%s <- %s <- %s\n",
|
||||
TP_printk("%c%s <- %s <- %s",
|
||||
(int) __entry->path_source &&
|
||||
(int) __entry->path_connect ? '*' : ' ',
|
||||
__get_str(wname), __get_str(pname), __get_str(psname))
|
||||
@ -226,7 +226,7 @@ TRACE_EVENT(snd_soc_dapm_connected,
|
||||
__entry->stream = stream;
|
||||
),
|
||||
|
||||
TP_printk("%s: found %d paths\n",
|
||||
TP_printk("%s: found %d paths",
|
||||
__entry->stream ? "capture" : "playback", __entry->paths)
|
||||
);
|
||||
|
||||
|
@ -219,7 +219,8 @@ typedef int __bitwise snd_pcm_format_t;
|
||||
#define SNDRV_PCM_FORMAT_G723_40_1B ((__force snd_pcm_format_t) 47) /* 1 sample in 1 byte */
|
||||
#define SNDRV_PCM_FORMAT_DSD_U8 ((__force snd_pcm_format_t) 48) /* DSD, 1-byte samples DSD (x8) */
|
||||
#define SNDRV_PCM_FORMAT_DSD_U16_LE ((__force snd_pcm_format_t) 49) /* DSD, 2-byte samples DSD (x16), little endian */
|
||||
#define SNDRV_PCM_FORMAT_LAST SNDRV_PCM_FORMAT_DSD_U16_LE
|
||||
#define SNDRV_PCM_FORMAT_DSD_U32_LE ((__force snd_pcm_format_t) 50) /* DSD, 4-byte samples DSD (x32), little endian */
|
||||
#define SNDRV_PCM_FORMAT_LAST SNDRV_PCM_FORMAT_DSD_U32_LE
|
||||
|
||||
#ifdef SNDRV_LITTLE_ENDIAN
|
||||
#define SNDRV_PCM_FORMAT_S16 SNDRV_PCM_FORMAT_S16_LE
|
||||
|
@ -145,6 +145,8 @@ EXPORT_SYMBOL(snd_pci_quirk_lookup_id);
|
||||
const struct snd_pci_quirk *
|
||||
snd_pci_quirk_lookup(struct pci_dev *pci, const struct snd_pci_quirk *list)
|
||||
{
|
||||
if (!pci)
|
||||
return NULL;
|
||||
return snd_pci_quirk_lookup_id(pci->subsystem_vendor,
|
||||
pci->subsystem_device,
|
||||
list);
|
||||
|
@ -215,6 +215,7 @@ static char *snd_pcm_format_names[] = {
|
||||
FORMAT(G723_40_1B),
|
||||
FORMAT(DSD_U8),
|
||||
FORMAT(DSD_U16_LE),
|
||||
FORMAT(DSD_U32_LE),
|
||||
};
|
||||
|
||||
const char *snd_pcm_format_name(snd_pcm_format_t format)
|
||||
@ -698,6 +699,7 @@ int snd_pcm_new_stream(struct snd_pcm *pcm, int stream, int substream_count)
|
||||
}
|
||||
substream->group = &substream->self_group;
|
||||
spin_lock_init(&substream->self_group.lock);
|
||||
mutex_init(&substream->self_group.mutex);
|
||||
INIT_LIST_HEAD(&substream->self_group.substreams);
|
||||
list_add_tail(&substream->link_list, &substream->self_group.substreams);
|
||||
atomic_set(&substream->mmap_count, 0);
|
||||
|
@ -1113,18 +1113,20 @@ int snd_interval_list(struct snd_interval *i, unsigned int count,
|
||||
|
||||
EXPORT_SYMBOL(snd_interval_list);
|
||||
|
||||
static int snd_interval_step(struct snd_interval *i, unsigned int min, unsigned int step)
|
||||
static int snd_interval_step(struct snd_interval *i, unsigned int step)
|
||||
{
|
||||
unsigned int n;
|
||||
int changed = 0;
|
||||
n = (i->min - min) % step;
|
||||
n = i->min % step;
|
||||
if (n != 0 || i->openmin) {
|
||||
i->min += step - n;
|
||||
i->openmin = 0;
|
||||
changed = 1;
|
||||
}
|
||||
n = (i->max - min) % step;
|
||||
n = i->max % step;
|
||||
if (n != 0 || i->openmax) {
|
||||
i->max -= n;
|
||||
i->openmax = 0;
|
||||
changed = 1;
|
||||
}
|
||||
if (snd_interval_checkempty(i)) {
|
||||
@ -1427,7 +1429,7 @@ static int snd_pcm_hw_rule_step(struct snd_pcm_hw_params *params,
|
||||
struct snd_pcm_hw_rule *rule)
|
||||
{
|
||||
unsigned long step = (unsigned long) rule->private;
|
||||
return snd_interval_step(hw_param_interval(params, rule->var), 0, step);
|
||||
return snd_interval_step(hw_param_interval(params, rule->var), step);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -148,6 +148,10 @@ static struct pcm_format_data pcm_formats[(INT)SNDRV_PCM_FORMAT_LAST+1] = {
|
||||
.width = 16, .phys = 16, .le = 1, .signd = 0,
|
||||
.silence = { 0x69, 0x69 },
|
||||
},
|
||||
[SNDRV_PCM_FORMAT_DSD_U32_LE] = {
|
||||
.width = 32, .phys = 32, .le = 1, .signd = 0,
|
||||
.silence = { 0x69, 0x69, 0x69, 0x69 },
|
||||
},
|
||||
/* FIXME: the following three formats are not defined properly yet */
|
||||
[SNDRV_PCM_FORMAT_MPEG] = {
|
||||
.le = -1, .signd = -1,
|
||||
|
@ -74,11 +74,68 @@ static int snd_pcm_open(struct file *file, struct snd_pcm *pcm, int stream);
|
||||
*
|
||||
*/
|
||||
|
||||
DEFINE_RWLOCK(snd_pcm_link_rwlock);
|
||||
EXPORT_SYMBOL(snd_pcm_link_rwlock);
|
||||
|
||||
static DEFINE_RWLOCK(snd_pcm_link_rwlock);
|
||||
static DECLARE_RWSEM(snd_pcm_link_rwsem);
|
||||
|
||||
void snd_pcm_stream_lock(struct snd_pcm_substream *substream)
|
||||
{
|
||||
if (substream->pcm->nonatomic) {
|
||||
down_read(&snd_pcm_link_rwsem);
|
||||
mutex_lock(&substream->self_group.mutex);
|
||||
} else {
|
||||
read_lock(&snd_pcm_link_rwlock);
|
||||
spin_lock(&substream->self_group.lock);
|
||||
}
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(snd_pcm_stream_lock);
|
||||
|
||||
void snd_pcm_stream_unlock(struct snd_pcm_substream *substream)
|
||||
{
|
||||
if (substream->pcm->nonatomic) {
|
||||
mutex_unlock(&substream->self_group.mutex);
|
||||
up_read(&snd_pcm_link_rwsem);
|
||||
} else {
|
||||
spin_unlock(&substream->self_group.lock);
|
||||
read_unlock(&snd_pcm_link_rwlock);
|
||||
}
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(snd_pcm_stream_unlock);
|
||||
|
||||
void snd_pcm_stream_lock_irq(struct snd_pcm_substream *substream)
|
||||
{
|
||||
if (!substream->pcm->nonatomic)
|
||||
local_irq_disable();
|
||||
snd_pcm_stream_lock(substream);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(snd_pcm_stream_lock_irq);
|
||||
|
||||
void snd_pcm_stream_unlock_irq(struct snd_pcm_substream *substream)
|
||||
{
|
||||
snd_pcm_stream_unlock(substream);
|
||||
if (!substream->pcm->nonatomic)
|
||||
local_irq_enable();
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(snd_pcm_stream_unlock_irq);
|
||||
|
||||
unsigned long _snd_pcm_stream_lock_irqsave(struct snd_pcm_substream *substream)
|
||||
{
|
||||
unsigned long flags = 0;
|
||||
if (!substream->pcm->nonatomic)
|
||||
local_irq_save(flags);
|
||||
snd_pcm_stream_lock(substream);
|
||||
return flags;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(_snd_pcm_stream_lock_irqsave);
|
||||
|
||||
void snd_pcm_stream_unlock_irqrestore(struct snd_pcm_substream *substream,
|
||||
unsigned long flags)
|
||||
{
|
||||
snd_pcm_stream_unlock(substream);
|
||||
if (!substream->pcm->nonatomic)
|
||||
local_irq_restore(flags);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(snd_pcm_stream_unlock_irqrestore);
|
||||
|
||||
static inline mm_segment_t snd_enter_user(void)
|
||||
{
|
||||
mm_segment_t fs = get_fs();
|
||||
@ -727,9 +784,14 @@ static int snd_pcm_action_group(struct action_ops *ops,
|
||||
int res = 0;
|
||||
|
||||
snd_pcm_group_for_each_entry(s, substream) {
|
||||
if (do_lock && s != substream)
|
||||
spin_lock_nested(&s->self_group.lock,
|
||||
SINGLE_DEPTH_NESTING);
|
||||
if (do_lock && s != substream) {
|
||||
if (s->pcm->nonatomic)
|
||||
mutex_lock_nested(&s->self_group.mutex,
|
||||
SINGLE_DEPTH_NESTING);
|
||||
else
|
||||
spin_lock_nested(&s->self_group.lock,
|
||||
SINGLE_DEPTH_NESTING);
|
||||
}
|
||||
res = ops->pre_action(s, state);
|
||||
if (res < 0)
|
||||
goto _unlock;
|
||||
@ -755,8 +817,12 @@ static int snd_pcm_action_group(struct action_ops *ops,
|
||||
if (do_lock) {
|
||||
/* unlock streams */
|
||||
snd_pcm_group_for_each_entry(s1, substream) {
|
||||
if (s1 != substream)
|
||||
spin_unlock(&s1->self_group.lock);
|
||||
if (s1 != substream) {
|
||||
if (s->pcm->nonatomic)
|
||||
mutex_unlock(&s1->self_group.mutex);
|
||||
else
|
||||
spin_unlock(&s1->self_group.lock);
|
||||
}
|
||||
if (s1 == s) /* end */
|
||||
break;
|
||||
}
|
||||
@ -784,6 +850,27 @@ static int snd_pcm_action_single(struct action_ops *ops,
|
||||
return res;
|
||||
}
|
||||
|
||||
/* call in mutex-protected context */
|
||||
static int snd_pcm_action_mutex(struct action_ops *ops,
|
||||
struct snd_pcm_substream *substream,
|
||||
int state)
|
||||
{
|
||||
int res;
|
||||
|
||||
if (snd_pcm_stream_linked(substream)) {
|
||||
if (!mutex_trylock(&substream->group->mutex)) {
|
||||
mutex_unlock(&substream->self_group.mutex);
|
||||
mutex_lock(&substream->group->mutex);
|
||||
mutex_lock(&substream->self_group.mutex);
|
||||
}
|
||||
res = snd_pcm_action_group(ops, substream, state, 1);
|
||||
mutex_unlock(&substream->group->mutex);
|
||||
} else {
|
||||
res = snd_pcm_action_single(ops, substream, state);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
/*
|
||||
* Note: call with stream lock
|
||||
*/
|
||||
@ -793,6 +880,9 @@ static int snd_pcm_action(struct action_ops *ops,
|
||||
{
|
||||
int res;
|
||||
|
||||
if (substream->pcm->nonatomic)
|
||||
return snd_pcm_action_mutex(ops, substream, state);
|
||||
|
||||
if (snd_pcm_stream_linked(substream)) {
|
||||
if (!spin_trylock(&substream->group->lock)) {
|
||||
spin_unlock(&substream->self_group.lock);
|
||||
@ -807,6 +897,29 @@ static int snd_pcm_action(struct action_ops *ops,
|
||||
return res;
|
||||
}
|
||||
|
||||
static int snd_pcm_action_lock_mutex(struct action_ops *ops,
|
||||
struct snd_pcm_substream *substream,
|
||||
int state)
|
||||
{
|
||||
int res;
|
||||
|
||||
down_read(&snd_pcm_link_rwsem);
|
||||
if (snd_pcm_stream_linked(substream)) {
|
||||
mutex_lock(&substream->group->mutex);
|
||||
mutex_lock_nested(&substream->self_group.mutex,
|
||||
SINGLE_DEPTH_NESTING);
|
||||
res = snd_pcm_action_group(ops, substream, state, 1);
|
||||
mutex_unlock(&substream->self_group.mutex);
|
||||
mutex_unlock(&substream->group->mutex);
|
||||
} else {
|
||||
mutex_lock(&substream->self_group.mutex);
|
||||
res = snd_pcm_action_single(ops, substream, state);
|
||||
mutex_unlock(&substream->self_group.mutex);
|
||||
}
|
||||
up_read(&snd_pcm_link_rwsem);
|
||||
return res;
|
||||
}
|
||||
|
||||
/*
|
||||
* Note: don't use any locks before
|
||||
*/
|
||||
@ -816,6 +929,9 @@ static int snd_pcm_action_lock_irq(struct action_ops *ops,
|
||||
{
|
||||
int res;
|
||||
|
||||
if (substream->pcm->nonatomic)
|
||||
return snd_pcm_action_lock_mutex(ops, substream, state);
|
||||
|
||||
read_lock_irq(&snd_pcm_link_rwlock);
|
||||
if (snd_pcm_stream_linked(substream)) {
|
||||
spin_lock(&substream->group->lock);
|
||||
@ -1634,7 +1750,8 @@ static int snd_pcm_link(struct snd_pcm_substream *substream, int fd)
|
||||
down_write(&snd_pcm_link_rwsem);
|
||||
write_lock_irq(&snd_pcm_link_rwlock);
|
||||
if (substream->runtime->status->state == SNDRV_PCM_STATE_OPEN ||
|
||||
substream->runtime->status->state != substream1->runtime->status->state) {
|
||||
substream->runtime->status->state != substream1->runtime->status->state ||
|
||||
substream->pcm->nonatomic != substream1->pcm->nonatomic) {
|
||||
res = -EBADFD;
|
||||
goto _end;
|
||||
}
|
||||
@ -1646,6 +1763,7 @@ static int snd_pcm_link(struct snd_pcm_substream *substream, int fd)
|
||||
substream->group = group;
|
||||
group = NULL;
|
||||
spin_lock_init(&substream->group->lock);
|
||||
mutex_init(&substream->group->mutex);
|
||||
INIT_LIST_HEAD(&substream->group->substreams);
|
||||
list_add_tail(&substream->link_list, &substream->group->substreams);
|
||||
substream->group->count = 1;
|
||||
|
@ -117,7 +117,7 @@ static int vx_reset_chk(struct vx_core *chip)
|
||||
*
|
||||
* returns 0 if successful, or a negative error code.
|
||||
* the error code can be VX-specific, retrieved via vx_get_error().
|
||||
* NB: call with spinlock held!
|
||||
* NB: call with mutex held!
|
||||
*/
|
||||
static int vx_transfer_end(struct vx_core *chip, int cmd)
|
||||
{
|
||||
@ -155,7 +155,7 @@ static int vx_transfer_end(struct vx_core *chip, int cmd)
|
||||
*
|
||||
* returns 0 if successful, or a negative error code.
|
||||
* the error code can be VX-specific, retrieved via vx_get_error().
|
||||
* NB: call with spinlock held!
|
||||
* NB: call with mutex held!
|
||||
*/
|
||||
static int vx_read_status(struct vx_core *chip, struct vx_rmh *rmh)
|
||||
{
|
||||
@ -236,7 +236,7 @@ static int vx_read_status(struct vx_core *chip, struct vx_rmh *rmh)
|
||||
* returns 0 if successful, or a negative error code.
|
||||
* the error code can be VX-specific, retrieved via vx_get_error().
|
||||
*
|
||||
* this function doesn't call spinlock at all.
|
||||
* this function doesn't call mutex lock at all.
|
||||
*/
|
||||
int vx_send_msg_nolock(struct vx_core *chip, struct vx_rmh *rmh)
|
||||
{
|
||||
@ -337,7 +337,7 @@ int vx_send_msg_nolock(struct vx_core *chip, struct vx_rmh *rmh)
|
||||
|
||||
|
||||
/*
|
||||
* vx_send_msg - send a DSP message with spinlock
|
||||
* vx_send_msg - send a DSP message with mutex
|
||||
* @rmh: the rmh record to send and receive
|
||||
*
|
||||
* returns 0 if successful, or a negative error code.
|
||||
@ -345,12 +345,11 @@ int vx_send_msg_nolock(struct vx_core *chip, struct vx_rmh *rmh)
|
||||
*/
|
||||
int vx_send_msg(struct vx_core *chip, struct vx_rmh *rmh)
|
||||
{
|
||||
unsigned long flags;
|
||||
int err;
|
||||
|
||||
spin_lock_irqsave(&chip->lock, flags);
|
||||
mutex_lock(&chip->lock);
|
||||
err = vx_send_msg_nolock(chip, rmh);
|
||||
spin_unlock_irqrestore(&chip->lock, flags);
|
||||
mutex_unlock(&chip->lock);
|
||||
return err;
|
||||
}
|
||||
|
||||
@ -362,7 +361,7 @@ int vx_send_msg(struct vx_core *chip, struct vx_rmh *rmh)
|
||||
* returns 0 if successful, or a negative error code.
|
||||
* the error code can be VX-specific, retrieved via vx_get_error().
|
||||
*
|
||||
* this function doesn't call spinlock at all.
|
||||
* this function doesn't call mutex at all.
|
||||
*
|
||||
* unlike RMH, no command is sent to DSP.
|
||||
*/
|
||||
@ -398,19 +397,18 @@ int vx_send_rih_nolock(struct vx_core *chip, int cmd)
|
||||
|
||||
|
||||
/*
|
||||
* vx_send_rih - send an RIH with spinlock
|
||||
* vx_send_rih - send an RIH with mutex
|
||||
* @cmd: the command to send
|
||||
*
|
||||
* see vx_send_rih_nolock().
|
||||
*/
|
||||
int vx_send_rih(struct vx_core *chip, int cmd)
|
||||
{
|
||||
unsigned long flags;
|
||||
int err;
|
||||
|
||||
spin_lock_irqsave(&chip->lock, flags);
|
||||
mutex_lock(&chip->lock);
|
||||
err = vx_send_rih_nolock(chip, cmd);
|
||||
spin_unlock_irqrestore(&chip->lock, flags);
|
||||
mutex_unlock(&chip->lock);
|
||||
return err;
|
||||
}
|
||||
|
||||
@ -482,30 +480,30 @@ static int vx_test_irq_src(struct vx_core *chip, unsigned int *ret)
|
||||
int err;
|
||||
|
||||
vx_init_rmh(&chip->irq_rmh, CMD_TEST_IT);
|
||||
spin_lock(&chip->lock);
|
||||
mutex_lock(&chip->lock);
|
||||
err = vx_send_msg_nolock(chip, &chip->irq_rmh);
|
||||
if (err < 0)
|
||||
*ret = 0;
|
||||
else
|
||||
*ret = chip->irq_rmh.Stat[0];
|
||||
spin_unlock(&chip->lock);
|
||||
mutex_unlock(&chip->lock);
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* vx_interrupt - soft irq handler
|
||||
* snd_vx_threaded_irq_handler - threaded irq handler
|
||||
*/
|
||||
static void vx_interrupt(unsigned long private_data)
|
||||
irqreturn_t snd_vx_threaded_irq_handler(int irq, void *dev)
|
||||
{
|
||||
struct vx_core *chip = (struct vx_core *) private_data;
|
||||
struct vx_core *chip = dev;
|
||||
unsigned int events;
|
||||
|
||||
if (chip->chip_status & VX_STAT_IS_STALE)
|
||||
return;
|
||||
return IRQ_HANDLED;
|
||||
|
||||
if (vx_test_irq_src(chip, &events) < 0)
|
||||
return;
|
||||
return IRQ_HANDLED;
|
||||
|
||||
#if 0
|
||||
if (events & 0x000800)
|
||||
@ -519,7 +517,7 @@ static void vx_interrupt(unsigned long private_data)
|
||||
*/
|
||||
if (events & FATAL_DSP_ERROR) {
|
||||
snd_printk(KERN_ERR "vx_core: fatal DSP error!!\n");
|
||||
return;
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
/* The start on time code conditions are filled (ie the time code
|
||||
@ -534,8 +532,9 @@ static void vx_interrupt(unsigned long private_data)
|
||||
|
||||
/* update the pcm streams */
|
||||
vx_pcm_update_intr(chip, events);
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL(snd_vx_threaded_irq_handler);
|
||||
|
||||
/**
|
||||
* snd_vx_irq_handler - interrupt handler
|
||||
@ -548,8 +547,8 @@ irqreturn_t snd_vx_irq_handler(int irq, void *dev)
|
||||
(chip->chip_status & VX_STAT_IS_STALE))
|
||||
return IRQ_NONE;
|
||||
if (! vx_test_and_ack(chip))
|
||||
tasklet_schedule(&chip->tq);
|
||||
return IRQ_HANDLED;
|
||||
return IRQ_WAKE_THREAD;
|
||||
return IRQ_NONE;
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL(snd_vx_irq_handler);
|
||||
@ -790,13 +789,11 @@ struct vx_core *snd_vx_create(struct snd_card *card, struct snd_vx_hardware *hw,
|
||||
snd_printk(KERN_ERR "vx_core: no memory\n");
|
||||
return NULL;
|
||||
}
|
||||
spin_lock_init(&chip->lock);
|
||||
spin_lock_init(&chip->irq_lock);
|
||||
mutex_init(&chip->lock);
|
||||
chip->irq = -1;
|
||||
chip->hw = hw;
|
||||
chip->type = hw->type;
|
||||
chip->ops = ops;
|
||||
tasklet_init(&chip->tq, vx_interrupt, (unsigned long)chip);
|
||||
mutex_init(&chip->mixer_mutex);
|
||||
|
||||
chip->card = card;
|
||||
|
@ -32,17 +32,15 @@
|
||||
*/
|
||||
static void vx_write_codec_reg(struct vx_core *chip, int codec, unsigned int data)
|
||||
{
|
||||
unsigned long flags;
|
||||
|
||||
if (snd_BUG_ON(!chip->ops->write_codec))
|
||||
return;
|
||||
|
||||
if (chip->chip_status & VX_STAT_IS_STALE)
|
||||
return;
|
||||
|
||||
spin_lock_irqsave(&chip->lock, flags);
|
||||
mutex_lock(&chip->lock);
|
||||
chip->ops->write_codec(chip, codec, data);
|
||||
spin_unlock_irqrestore(&chip->lock, flags);
|
||||
mutex_unlock(&chip->lock);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -178,14 +176,12 @@ void vx_reset_codec(struct vx_core *chip, int cold_reset)
|
||||
*/
|
||||
static void vx_change_audio_source(struct vx_core *chip, int src)
|
||||
{
|
||||
unsigned long flags;
|
||||
|
||||
if (chip->chip_status & VX_STAT_IS_STALE)
|
||||
return;
|
||||
|
||||
spin_lock_irqsave(&chip->lock, flags);
|
||||
mutex_lock(&chip->lock);
|
||||
chip->ops->change_audio_source(chip, src);
|
||||
spin_unlock_irqrestore(&chip->lock, flags);
|
||||
mutex_unlock(&chip->lock);
|
||||
}
|
||||
|
||||
|
||||
|
@ -229,7 +229,7 @@ static int vx_get_pipe_state(struct vx_core *chip, struct vx_pipe *pipe, int *st
|
||||
|
||||
vx_init_rmh(&rmh, CMD_PIPE_STATE);
|
||||
vx_set_pipe_cmd_params(&rmh, pipe->is_capture, pipe->number, 0);
|
||||
err = vx_send_msg_nolock(chip, &rmh); /* no lock needed for trigger */
|
||||
err = vx_send_msg(chip, &rmh);
|
||||
if (! err)
|
||||
*state = (rmh.Stat[0] & (1 << pipe->number)) ? 1 : 0;
|
||||
return err;
|
||||
@ -280,7 +280,7 @@ static int vx_pipe_can_start(struct vx_core *chip, struct vx_pipe *pipe)
|
||||
vx_set_pipe_cmd_params(&rmh, pipe->is_capture, pipe->number, 0);
|
||||
rmh.Cmd[0] |= 1;
|
||||
|
||||
err = vx_send_msg_nolock(chip, &rmh); /* no lock needed for trigger */
|
||||
err = vx_send_msg(chip, &rmh);
|
||||
if (! err) {
|
||||
if (rmh.Stat[0])
|
||||
err = 1;
|
||||
@ -300,7 +300,7 @@ static int vx_conf_pipe(struct vx_core *chip, struct vx_pipe *pipe)
|
||||
if (pipe->is_capture)
|
||||
rmh.Cmd[0] |= COMMAND_RECORD_MASK;
|
||||
rmh.Cmd[1] = 1 << pipe->number;
|
||||
return vx_send_msg_nolock(chip, &rmh); /* no lock needed for trigger */
|
||||
return vx_send_msg(chip, &rmh);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -311,7 +311,7 @@ static int vx_send_irqa(struct vx_core *chip)
|
||||
struct vx_rmh rmh;
|
||||
|
||||
vx_init_rmh(&rmh, CMD_SEND_IRQA);
|
||||
return vx_send_msg_nolock(chip, &rmh); /* no lock needed for trigger */
|
||||
return vx_send_msg(chip, &rmh);
|
||||
}
|
||||
|
||||
|
||||
@ -389,7 +389,7 @@ static int vx_stop_pipe(struct vx_core *chip, struct vx_pipe *pipe)
|
||||
struct vx_rmh rmh;
|
||||
vx_init_rmh(&rmh, CMD_STOP_PIPE);
|
||||
vx_set_pipe_cmd_params(&rmh, pipe->is_capture, pipe->number, 0);
|
||||
return vx_send_msg_nolock(chip, &rmh); /* no lock needed for trigger */
|
||||
return vx_send_msg(chip, &rmh);
|
||||
}
|
||||
|
||||
|
||||
@ -477,7 +477,7 @@ static int vx_start_stream(struct vx_core *chip, struct vx_pipe *pipe)
|
||||
vx_init_rmh(&rmh, CMD_START_ONE_STREAM);
|
||||
vx_set_stream_cmd_params(&rmh, pipe->is_capture, pipe->number);
|
||||
vx_set_differed_time(chip, &rmh, pipe);
|
||||
return vx_send_msg_nolock(chip, &rmh); /* no lock needed for trigger */
|
||||
return vx_send_msg(chip, &rmh);
|
||||
}
|
||||
|
||||
|
||||
@ -492,7 +492,7 @@ static int vx_stop_stream(struct vx_core *chip, struct vx_pipe *pipe)
|
||||
|
||||
vx_init_rmh(&rmh, CMD_STOP_STREAM);
|
||||
vx_set_stream_cmd_params(&rmh, pipe->is_capture, pipe->number);
|
||||
return vx_send_msg_nolock(chip, &rmh); /* no lock needed for trigger */
|
||||
return vx_send_msg(chip, &rmh);
|
||||
}
|
||||
|
||||
|
||||
@ -520,8 +520,6 @@ static struct snd_pcm_hardware vx_pcm_playback_hw = {
|
||||
};
|
||||
|
||||
|
||||
static void vx_pcm_delayed_start(unsigned long arg);
|
||||
|
||||
/*
|
||||
* vx_pcm_playback_open - open callback for playback
|
||||
*/
|
||||
@ -553,7 +551,6 @@ static int vx_pcm_playback_open(struct snd_pcm_substream *subs)
|
||||
pipe->references++;
|
||||
|
||||
pipe->substream = subs;
|
||||
tasklet_init(&pipe->start_tq, vx_pcm_delayed_start, (unsigned long)subs);
|
||||
chip->playback_pipes[audio] = pipe;
|
||||
|
||||
runtime->hw = vx_pcm_playback_hw;
|
||||
@ -646,12 +643,12 @@ static int vx_pcm_playback_transfer_chunk(struct vx_core *chip,
|
||||
/* we don't need irqsave here, because this function
|
||||
* is called from either trigger callback or irq handler
|
||||
*/
|
||||
spin_lock(&chip->lock);
|
||||
mutex_lock(&chip->lock);
|
||||
vx_pseudo_dma_write(chip, runtime, pipe, size);
|
||||
err = vx_notify_end_of_buffer(chip, pipe);
|
||||
/* disconnect the host, SIZE_HBUF command always switches to the stream mode */
|
||||
vx_send_rih_nolock(chip, IRQ_CONNECT_STREAM_NEXT);
|
||||
spin_unlock(&chip->lock);
|
||||
mutex_unlock(&chip->lock);
|
||||
return err;
|
||||
}
|
||||
|
||||
@ -727,31 +724,6 @@ static void vx_pcm_playback_update(struct vx_core *chip,
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* start the stream and pipe.
|
||||
* this function is called from tasklet, which is invoked by the trigger
|
||||
* START callback.
|
||||
*/
|
||||
static void vx_pcm_delayed_start(unsigned long arg)
|
||||
{
|
||||
struct snd_pcm_substream *subs = (struct snd_pcm_substream *)arg;
|
||||
struct vx_core *chip = subs->pcm->private_data;
|
||||
struct vx_pipe *pipe = subs->runtime->private_data;
|
||||
int err;
|
||||
|
||||
/* printk( KERN_DEBUG "DDDD tasklet delayed start jiffies = %ld\n", jiffies);*/
|
||||
|
||||
if ((err = vx_start_stream(chip, pipe)) < 0) {
|
||||
snd_printk(KERN_ERR "vx: cannot start stream\n");
|
||||
return;
|
||||
}
|
||||
if ((err = vx_toggle_pipe(chip, pipe, 1)) < 0) {
|
||||
snd_printk(KERN_ERR "vx: cannot start pipe\n");
|
||||
return;
|
||||
}
|
||||
/* printk( KERN_DEBUG "dddd tasklet delayed start jiffies = %ld \n", jiffies);*/
|
||||
}
|
||||
|
||||
/*
|
||||
* vx_pcm_playback_trigger - trigger callback for playback
|
||||
*/
|
||||
@ -769,11 +741,17 @@ static int vx_pcm_trigger(struct snd_pcm_substream *subs, int cmd)
|
||||
case SNDRV_PCM_TRIGGER_RESUME:
|
||||
if (! pipe->is_capture)
|
||||
vx_pcm_playback_transfer(chip, subs, pipe, 2);
|
||||
/* FIXME:
|
||||
* we trigger the pipe using tasklet, so that the interrupts are
|
||||
* issued surely after the trigger is completed.
|
||||
*/
|
||||
tasklet_schedule(&pipe->start_tq);
|
||||
err = vx_start_stream(chip, pipe);
|
||||
if (err < 0) {
|
||||
pr_debug("vx: cannot start stream\n");
|
||||
return err;
|
||||
}
|
||||
err = vx_toggle_pipe(chip, pipe, 1);
|
||||
if (err < 0) {
|
||||
pr_debug("vx: cannot start pipe\n");
|
||||
vx_stop_stream(chip, pipe);
|
||||
return err;
|
||||
}
|
||||
chip->pcm_running++;
|
||||
pipe->running = 1;
|
||||
break;
|
||||
@ -955,7 +933,6 @@ static int vx_pcm_capture_open(struct snd_pcm_substream *subs)
|
||||
if (err < 0)
|
||||
return err;
|
||||
pipe->substream = subs;
|
||||
tasklet_init(&pipe->start_tq, vx_pcm_delayed_start, (unsigned long)subs);
|
||||
chip->capture_pipes[audio] = pipe;
|
||||
|
||||
/* check if monitoring is needed */
|
||||
@ -1082,7 +1059,7 @@ static void vx_pcm_capture_update(struct vx_core *chip, struct snd_pcm_substream
|
||||
count -= 3;
|
||||
}
|
||||
/* disconnect the host, SIZE_HBUF command always switches to the stream mode */
|
||||
vx_send_rih_nolock(chip, IRQ_CONNECT_STREAM_NEXT);
|
||||
vx_send_rih(chip, IRQ_CONNECT_STREAM_NEXT);
|
||||
/* read the last pending 6 bytes */
|
||||
count = DMA_READ_ALIGN;
|
||||
while (count > 0) {
|
||||
@ -1099,7 +1076,7 @@ static void vx_pcm_capture_update(struct vx_core *chip, struct snd_pcm_substream
|
||||
|
||||
_error:
|
||||
/* disconnect the host, SIZE_HBUF command always switches to the stream mode */
|
||||
vx_send_rih_nolock(chip, IRQ_CONNECT_STREAM_NEXT);
|
||||
vx_send_rih(chip, IRQ_CONNECT_STREAM_NEXT);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -1275,6 +1252,7 @@ int snd_vx_pcm_new(struct vx_core *chip)
|
||||
pcm->private_data = chip;
|
||||
pcm->private_free = snd_vx_pcm_free;
|
||||
pcm->info_flags = 0;
|
||||
pcm->nonatomic = true;
|
||||
strcpy(pcm->name, chip->card->shortname);
|
||||
chip->pcm[i] = pcm;
|
||||
}
|
||||
|
@ -60,9 +60,9 @@ static int vx_modify_board_inputs(struct vx_core *chip)
|
||||
*/
|
||||
static int vx_read_one_cbit(struct vx_core *chip, int index)
|
||||
{
|
||||
unsigned long flags;
|
||||
int val;
|
||||
spin_lock_irqsave(&chip->lock, flags);
|
||||
|
||||
mutex_lock(&chip->lock);
|
||||
if (chip->type >= VX_TYPE_VXPOCKET) {
|
||||
vx_outb(chip, CSUER, 1); /* read */
|
||||
vx_outb(chip, RUER, index & XX_UER_CBITS_OFFSET_MASK);
|
||||
@ -72,7 +72,7 @@ static int vx_read_one_cbit(struct vx_core *chip, int index)
|
||||
vx_outl(chip, RUER, index & XX_UER_CBITS_OFFSET_MASK);
|
||||
val = (vx_inl(chip, RUER) >> 7) & 0x01;
|
||||
}
|
||||
spin_unlock_irqrestore(&chip->lock, flags);
|
||||
mutex_unlock(&chip->lock);
|
||||
return val;
|
||||
}
|
||||
|
||||
@ -83,9 +83,8 @@ static int vx_read_one_cbit(struct vx_core *chip, int index)
|
||||
*/
|
||||
static void vx_write_one_cbit(struct vx_core *chip, int index, int val)
|
||||
{
|
||||
unsigned long flags;
|
||||
val = !!val; /* 0 or 1 */
|
||||
spin_lock_irqsave(&chip->lock, flags);
|
||||
mutex_lock(&chip->lock);
|
||||
if (vx_is_pcmcia(chip)) {
|
||||
vx_outb(chip, CSUER, 0); /* write */
|
||||
vx_outb(chip, RUER, (val << 7) | (index & XX_UER_CBITS_OFFSET_MASK));
|
||||
@ -93,7 +92,7 @@ static void vx_write_one_cbit(struct vx_core *chip, int index, int val)
|
||||
vx_outl(chip, CSUER, 0); /* write */
|
||||
vx_outl(chip, RUER, (val << 7) | (index & XX_UER_CBITS_OFFSET_MASK));
|
||||
}
|
||||
spin_unlock_irqrestore(&chip->lock, flags);
|
||||
mutex_unlock(&chip->lock);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -190,14 +189,12 @@ static int vx_calc_clock_from_freq(struct vx_core *chip, int freq)
|
||||
*/
|
||||
static void vx_change_clock_source(struct vx_core *chip, int source)
|
||||
{
|
||||
unsigned long flags;
|
||||
|
||||
/* we mute DAC to prevent clicks */
|
||||
vx_toggle_dac_mute(chip, 1);
|
||||
spin_lock_irqsave(&chip->lock, flags);
|
||||
mutex_lock(&chip->lock);
|
||||
chip->ops->set_clock_source(chip, source);
|
||||
chip->clock_source = source;
|
||||
spin_unlock_irqrestore(&chip->lock, flags);
|
||||
mutex_unlock(&chip->lock);
|
||||
/* unmute */
|
||||
vx_toggle_dac_mute(chip, 0);
|
||||
}
|
||||
@ -209,11 +206,11 @@ static void vx_change_clock_source(struct vx_core *chip, int source)
|
||||
void vx_set_internal_clock(struct vx_core *chip, unsigned int freq)
|
||||
{
|
||||
int clock;
|
||||
unsigned long flags;
|
||||
|
||||
/* Get real clock value */
|
||||
clock = vx_calc_clock_from_freq(chip, freq);
|
||||
snd_printdd(KERN_DEBUG "set internal clock to 0x%x from freq %d\n", clock, freq);
|
||||
spin_lock_irqsave(&chip->lock, flags);
|
||||
mutex_lock(&chip->lock);
|
||||
if (vx_is_pcmcia(chip)) {
|
||||
vx_outb(chip, HIFREQ, (clock >> 8) & 0x0f);
|
||||
vx_outb(chip, LOFREQ, clock & 0xff);
|
||||
@ -221,7 +218,7 @@ void vx_set_internal_clock(struct vx_core *chip, unsigned int freq)
|
||||
vx_outl(chip, HIFREQ, (clock >> 8) & 0x0f);
|
||||
vx_outl(chip, LOFREQ, clock & 0xff);
|
||||
}
|
||||
spin_unlock_irqrestore(&chip->lock, flags);
|
||||
mutex_unlock(&chip->lock);
|
||||
}
|
||||
|
||||
|
||||
|
@ -48,10 +48,10 @@ static void vortex_fix_latency(struct pci_dev *vortex)
|
||||
{
|
||||
int rc;
|
||||
if (!(rc = pci_write_config_byte(vortex, 0x40, 0xff))) {
|
||||
printk(KERN_INFO CARD_NAME
|
||||
pr_info( CARD_NAME
|
||||
": vortex latency is 0xff\n");
|
||||
} else {
|
||||
printk(KERN_WARNING CARD_NAME
|
||||
pr_warn( CARD_NAME
|
||||
": could not set vortex latency: pci error 0x%x\n", rc);
|
||||
}
|
||||
}
|
||||
@ -70,10 +70,10 @@ static void vortex_fix_agp_bridge(struct pci_dev *via)
|
||||
if (!(rc = pci_read_config_byte(via, 0x42, &value))
|
||||
&& ((value & 0x10)
|
||||
|| !(rc = pci_write_config_byte(via, 0x42, value | 0x10)))) {
|
||||
printk(KERN_INFO CARD_NAME
|
||||
pr_info( CARD_NAME
|
||||
": bridge config is 0x%x\n", value | 0x10);
|
||||
} else {
|
||||
printk(KERN_WARNING CARD_NAME
|
||||
pr_warn( CARD_NAME
|
||||
": could not set vortex latency: pci error 0x%x\n", rc);
|
||||
}
|
||||
}
|
||||
@ -97,7 +97,7 @@ static void snd_vortex_workaround(struct pci_dev *vortex, int fix)
|
||||
PCI_DEVICE_ID_AMD_FE_GATE_7007, NULL);
|
||||
}
|
||||
if (via) {
|
||||
printk(KERN_INFO CARD_NAME ": Activating latency workaround...\n");
|
||||
pr_info( CARD_NAME ": Activating latency workaround...\n");
|
||||
vortex_fix_latency(vortex);
|
||||
vortex_fix_agp_bridge(via);
|
||||
}
|
||||
@ -153,7 +153,7 @@ snd_vortex_create(struct snd_card *card, struct pci_dev *pci, vortex_t ** rchip)
|
||||
return err;
|
||||
if (pci_set_dma_mask(pci, DMA_BIT_MASK(32)) < 0 ||
|
||||
pci_set_consistent_dma_mask(pci, DMA_BIT_MASK(32)) < 0) {
|
||||
printk(KERN_ERR "error to set DMA mask\n");
|
||||
pr_err( "error to set DMA mask\n");
|
||||
pci_disable_device(pci);
|
||||
return -ENXIO;
|
||||
}
|
||||
@ -182,7 +182,7 @@ snd_vortex_create(struct snd_card *card, struct pci_dev *pci, vortex_t ** rchip)
|
||||
|
||||
chip->mmio = pci_ioremap_bar(pci, 0);
|
||||
if (!chip->mmio) {
|
||||
printk(KERN_ERR "MMIO area remap failed.\n");
|
||||
pr_err( "MMIO area remap failed.\n");
|
||||
err = -ENOMEM;
|
||||
goto ioremap_out;
|
||||
}
|
||||
@ -191,14 +191,14 @@ snd_vortex_create(struct snd_card *card, struct pci_dev *pci, vortex_t ** rchip)
|
||||
* This must be done before we do request_irq otherwise we can get spurious
|
||||
* interrupts that we do not handle properly and make a mess of things */
|
||||
if ((err = vortex_core_init(chip)) != 0) {
|
||||
printk(KERN_ERR "hw core init failed\n");
|
||||
pr_err( "hw core init failed\n");
|
||||
goto core_out;
|
||||
}
|
||||
|
||||
if ((err = request_irq(pci->irq, vortex_interrupt,
|
||||
IRQF_SHARED, KBUILD_MODNAME,
|
||||
chip)) != 0) {
|
||||
printk(KERN_ERR "cannot grab irq\n");
|
||||
pr_err( "cannot grab irq\n");
|
||||
goto irq_out;
|
||||
}
|
||||
chip->irq = pci->irq;
|
||||
@ -342,10 +342,10 @@ snd_vortex_probe(struct pci_dev *pci, const struct pci_device_id *pci_id)
|
||||
chip->rev = pci->revision;
|
||||
#ifdef CHIP_AU8830
|
||||
if ((chip->rev) != 0xfe && (chip->rev) != 0xfa) {
|
||||
printk(KERN_ALERT
|
||||
pr_alert(
|
||||
"vortex: The revision (%x) of your card has not been seen before.\n",
|
||||
chip->rev);
|
||||
printk(KERN_ALERT
|
||||
pr_alert(
|
||||
"vortex: Please email the results of 'lspci -vv' to openvortex-dev@nongnu.org.\n");
|
||||
snd_card_free(card);
|
||||
err = -ENODEV;
|
||||
|
@ -463,7 +463,7 @@ static void a3dsrc_ZeroSliceIO(a3dsrc_t * a)
|
||||
static void a3dsrc_ZeroState(a3dsrc_t * a)
|
||||
{
|
||||
/*
|
||||
printk(KERN_DEBUG "vortex: ZeroState slice: %d, source %d\n",
|
||||
pr_debug( "vortex: ZeroState slice: %d, source %d\n",
|
||||
a->slice, a->source);
|
||||
*/
|
||||
a3dsrc_SetAtmosState(a, 0, 0, 0, 0);
|
||||
@ -489,7 +489,7 @@ static void a3dsrc_ZeroStateA3D(a3dsrc_t * a)
|
||||
int i, var, var2;
|
||||
|
||||
if ((a->vortex) == NULL) {
|
||||
printk(KERN_ERR "vortex: ZeroStateA3D: ERROR: a->vortex is NULL\n");
|
||||
pr_err( "vortex: ZeroStateA3D: ERROR: a->vortex is NULL\n");
|
||||
return;
|
||||
}
|
||||
|
||||
@ -628,14 +628,14 @@ static void vortex_Vort3D_connect(vortex_t * v, int en)
|
||||
v->mixxtlk[0] =
|
||||
vortex_adb_checkinout(v, v->fixed_res, en, VORTEX_RESOURCE_MIXIN);
|
||||
if (v->mixxtlk[0] < 0) {
|
||||
printk
|
||||
pr_warn
|
||||
("vortex: vortex_Vort3D: ERROR: not enough free mixer resources.\n");
|
||||
return;
|
||||
}
|
||||
v->mixxtlk[1] =
|
||||
vortex_adb_checkinout(v, v->fixed_res, en, VORTEX_RESOURCE_MIXIN);
|
||||
if (v->mixxtlk[1] < 0) {
|
||||
printk
|
||||
pr_warn
|
||||
("vortex: vortex_Vort3D: ERROR: not enough free mixer resources.\n");
|
||||
return;
|
||||
}
|
||||
@ -679,7 +679,7 @@ static void vortex_Vort3D_connect(vortex_t * v, int en)
|
||||
static void vortex_Vort3D_InitializeSource(a3dsrc_t * a, int en)
|
||||
{
|
||||
if (a->vortex == NULL) {
|
||||
printk
|
||||
pr_warn
|
||||
("vortex: Vort3D_InitializeSource: A3D source not initialized\n");
|
||||
return;
|
||||
}
|
||||
|
@ -285,7 +285,7 @@ vortex_mixer_addWTD(vortex_t * vortex, unsigned char mix, unsigned char ch)
|
||||
temp = hwread(vortex->mmio, prev);
|
||||
//printk(KERN_INFO "vortex: mixAddWTD: while addr=%x, val=%x\n", prev, temp);
|
||||
if ((++lifeboat) > 0xf) {
|
||||
printk(KERN_ERR
|
||||
pr_err(
|
||||
"vortex_mixer_addWTD: lifeboat overflow\n");
|
||||
return 0;
|
||||
}
|
||||
@ -303,7 +303,7 @@ vortex_mixer_delWTD(vortex_t * vortex, unsigned char mix, unsigned char ch)
|
||||
|
||||
eax = hwread(vortex->mmio, VORTEX_MIXER_SR);
|
||||
if (((1 << ch) & eax) == 0) {
|
||||
printk(KERN_ERR "mix ALARM %x\n", eax);
|
||||
pr_err( "mix ALARM %x\n", eax);
|
||||
return 0;
|
||||
}
|
||||
ebp = VORTEX_MIXER_CHNBASE + (ch << 2);
|
||||
@ -324,7 +324,7 @@ vortex_mixer_delWTD(vortex_t * vortex, unsigned char mix, unsigned char ch)
|
||||
//printk(KERN_INFO "vortex: mixdelWTD: 1 addr=%x, val=%x, src=%x\n", ebx, edx, src);
|
||||
while ((edx & 0xf) != mix) {
|
||||
if ((esi) > 0xf) {
|
||||
printk(KERN_ERR
|
||||
pr_err(
|
||||
"vortex: mixdelWTD: error lifeboat overflow\n");
|
||||
return 0;
|
||||
}
|
||||
@ -492,7 +492,7 @@ vortex_src_persist_convratio(vortex_t * vortex, unsigned char src, int ratio)
|
||||
hwwrite(vortex->mmio, VORTEX_SRC_CONVRATIO + (src << 2), ratio);
|
||||
temp = hwread(vortex->mmio, VORTEX_SRC_CONVRATIO + (src << 2));
|
||||
if ((++lifeboat) > 0x9) {
|
||||
printk(KERN_ERR "Vortex: Src cvr fail\n");
|
||||
pr_err( "Vortex: Src cvr fail\n");
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -545,7 +545,7 @@ vortex_src_checkratio(vortex_t * vortex, unsigned char src,
|
||||
hwwrite(vortex->mmio, VORTEX_SRC_CONVRATIO + (src << 2), desired_ratio);
|
||||
|
||||
if ((lifeboat++) > 15) {
|
||||
printk(KERN_ERR "Vortex: could not set src-%d from %d to %d\n",
|
||||
pr_err( "Vortex: could not set src-%d from %d to %d\n",
|
||||
src, hw_ratio, desired_ratio);
|
||||
break;
|
||||
}
|
||||
@ -684,7 +684,7 @@ vortex_src_addWTD(vortex_t * vortex, unsigned char src, unsigned char ch)
|
||||
temp = hwread(vortex->mmio, prev);
|
||||
//printk(KERN_INFO "vortex: srcAddWTD: while addr=%x, val=%x\n", prev, temp);
|
||||
if ((++lifeboat) > 0xf) {
|
||||
printk(KERN_ERR
|
||||
pr_err(
|
||||
"vortex_src_addWTD: lifeboat overflow\n");
|
||||
return 0;
|
||||
}
|
||||
@ -703,7 +703,7 @@ vortex_src_delWTD(vortex_t * vortex, unsigned char src, unsigned char ch)
|
||||
|
||||
eax = hwread(vortex->mmio, VORTEX_SRCBLOCK_SR);
|
||||
if (((1 << ch) & eax) == 0) {
|
||||
printk(KERN_ERR "src alarm\n");
|
||||
pr_err( "src alarm\n");
|
||||
return 0;
|
||||
}
|
||||
ebp = VORTEX_SRC_CHNBASE + (ch << 2);
|
||||
@ -724,7 +724,7 @@ vortex_src_delWTD(vortex_t * vortex, unsigned char src, unsigned char ch)
|
||||
//printk(KERN_INFO "vortex: srcdelWTD: 1 addr=%x, val=%x, src=%x\n", ebx, edx, src);
|
||||
while ((edx & 0xf) != src) {
|
||||
if ((esi) > 0xf) {
|
||||
printk
|
||||
pr_warn
|
||||
("vortex: srcdelWTD: error, lifeboat overflow\n");
|
||||
return 0;
|
||||
}
|
||||
@ -819,7 +819,7 @@ vortex_fifo_setadbctrl(vortex_t * vortex, int fifo, int stereo, int priority,
|
||||
do {
|
||||
temp = hwread(vortex->mmio, VORTEX_FIFO_ADBCTRL + (fifo << 2));
|
||||
if (lifeboat++ > 0xbb8) {
|
||||
printk(KERN_ERR
|
||||
pr_err(
|
||||
"Vortex: vortex_fifo_setadbctrl fail\n");
|
||||
break;
|
||||
}
|
||||
@ -915,7 +915,7 @@ vortex_fifo_setwtctrl(vortex_t * vortex, int fifo, int ctrl, int priority,
|
||||
do {
|
||||
temp = hwread(vortex->mmio, VORTEX_FIFO_WTCTRL + (fifo << 2));
|
||||
if (lifeboat++ > 0xbb8) {
|
||||
printk(KERN_ERR "Vortex: vortex_fifo_setwtctrl fail\n");
|
||||
pr_err( "Vortex: vortex_fifo_setwtctrl fail\n");
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -970,7 +970,7 @@ vortex_fifo_setwtctrl(vortex_t * vortex, int fifo, int ctrl, int priority,
|
||||
do {
|
||||
temp = hwread(vortex->mmio, VORTEX_FIFO_WTCTRL + (fifo << 2));
|
||||
if (lifeboat++ > 0xbb8) {
|
||||
printk(KERN_ERR "Vortex: vortex_fifo_setwtctrl fail (hanging)\n");
|
||||
pr_err( "Vortex: vortex_fifo_setwtctrl fail (hanging)\n");
|
||||
break;
|
||||
}
|
||||
} while ((temp & FIFO_RDONLY)&&(temp & FIFO_VALID)&&(temp != 0xFFFFFFFF));
|
||||
@ -1042,7 +1042,7 @@ static void vortex_fifo_init(vortex_t * vortex)
|
||||
for (x = NR_ADB - 1; x >= 0; x--) {
|
||||
hwwrite(vortex->mmio, addr, (FIFO_U0 | FIFO_U1));
|
||||
if (hwread(vortex->mmio, addr) != (FIFO_U0 | FIFO_U1))
|
||||
printk(KERN_ERR "bad adb fifo reset!");
|
||||
pr_err( "bad adb fifo reset!");
|
||||
vortex_fifo_clearadbdata(vortex, x, FIFO_SIZE);
|
||||
addr -= 4;
|
||||
}
|
||||
@ -1053,7 +1053,7 @@ static void vortex_fifo_init(vortex_t * vortex)
|
||||
for (x = NR_WT - 1; x >= 0; x--) {
|
||||
hwwrite(vortex->mmio, addr, FIFO_U0);
|
||||
if (hwread(vortex->mmio, addr) != FIFO_U0)
|
||||
printk(KERN_ERR
|
||||
pr_err(
|
||||
"bad wt fifo reset (0x%08x, 0x%08x)!\n",
|
||||
addr, hwread(vortex->mmio, addr));
|
||||
vortex_fifo_clearwtdata(vortex, x, FIFO_SIZE);
|
||||
@ -1136,7 +1136,7 @@ vortex_adbdma_setbuffers(vortex_t * vortex, int adbdma,
|
||||
break;
|
||||
}
|
||||
/*
|
||||
printk(KERN_DEBUG "vortex: cfg0 = 0x%x\nvortex: cfg1=0x%x\n",
|
||||
pr_debug( "vortex: cfg0 = 0x%x\nvortex: cfg1=0x%x\n",
|
||||
dma->cfg0, dma->cfg1);
|
||||
*/
|
||||
hwwrite(vortex->mmio, VORTEX_ADBDMA_BUFCFG0 + (adbdma << 3), dma->cfg0);
|
||||
@ -1213,7 +1213,7 @@ static int vortex_adbdma_bufshift(vortex_t * vortex, int adbdma)
|
||||
if (dma->period_virt >= dma->nr_periods)
|
||||
dma->period_virt -= dma->nr_periods;
|
||||
if (delta != 1)
|
||||
printk(KERN_INFO "vortex: %d virt=%d, real=%d, delta=%d\n",
|
||||
pr_info( "vortex: %d virt=%d, real=%d, delta=%d\n",
|
||||
adbdma, dma->period_virt, dma->period_real, delta);
|
||||
|
||||
return delta;
|
||||
@ -1482,7 +1482,7 @@ static int vortex_wtdma_bufshift(vortex_t * vortex, int wtdma)
|
||||
dma->period_real = page;
|
||||
|
||||
if (delta != 1)
|
||||
printk(KERN_WARNING "vortex: wt virt = %d, delta = %d\n",
|
||||
pr_warn( "vortex: wt virt = %d, delta = %d\n",
|
||||
dma->period_virt, delta);
|
||||
|
||||
return delta;
|
||||
@ -1667,7 +1667,7 @@ vortex_adb_addroutes(vortex_t * vortex, unsigned char channel,
|
||||
hwread(vortex->mmio,
|
||||
VORTEX_ADB_RTBASE + (temp << 2)) & ADB_MASK;
|
||||
if ((lifeboat++) > ADB_MASK) {
|
||||
printk(KERN_ERR
|
||||
pr_err(
|
||||
"vortex_adb_addroutes: unending route! 0x%x\n",
|
||||
*route);
|
||||
return;
|
||||
@ -1703,7 +1703,7 @@ vortex_adb_delroutes(vortex_t * vortex, unsigned char channel,
|
||||
hwread(vortex->mmio,
|
||||
VORTEX_ADB_RTBASE + (prev << 2)) & ADB_MASK;
|
||||
if (((lifeboat++) > ADB_MASK) || (temp == ADB_MASK)) {
|
||||
printk(KERN_ERR
|
||||
pr_err(
|
||||
"vortex_adb_delroutes: route not found! 0x%x\n",
|
||||
route0);
|
||||
return;
|
||||
@ -1967,7 +1967,7 @@ vortex_connect_codecplay(vortex_t * vortex, int en, unsigned char mixers[])
|
||||
ADB_CODECOUT(0 + 4));
|
||||
vortex_connection_mix_adb(vortex, en, 0x11, mixers[3],
|
||||
ADB_CODECOUT(1 + 4));
|
||||
/* printk(KERN_DEBUG "SDAC detected "); */
|
||||
/* pr_debug( "SDAC detected "); */
|
||||
}
|
||||
#else
|
||||
// Use plain direct output to codec.
|
||||
@ -2022,7 +2022,7 @@ vortex_adb_checkinout(vortex_t * vortex, int resmap[], int out, int restype)
|
||||
else
|
||||
vortex->dma_adb[i].resources[restype] |= (1 << i);
|
||||
/*
|
||||
printk(KERN_DEBUG
|
||||
pr_debug(
|
||||
"vortex: ResManager: type %d out %d\n",
|
||||
restype, i);
|
||||
*/
|
||||
@ -2037,7 +2037,7 @@ vortex_adb_checkinout(vortex_t * vortex, int resmap[], int out, int restype)
|
||||
if (resmap[restype] & (1 << i)) {
|
||||
resmap[restype] &= ~(1 << i);
|
||||
/*
|
||||
printk(KERN_DEBUG
|
||||
pr_debug(
|
||||
"vortex: ResManager: type %d in %d\n",
|
||||
restype, i);
|
||||
*/
|
||||
@ -2045,7 +2045,7 @@ vortex_adb_checkinout(vortex_t * vortex, int resmap[], int out, int restype)
|
||||
}
|
||||
}
|
||||
}
|
||||
printk(KERN_ERR "vortex: FATAL: ResManager: resource type %d exhausted.\n", restype);
|
||||
pr_err( "vortex: FATAL: ResManager: resource type %d exhausted.\n", restype);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
@ -2173,7 +2173,7 @@ vortex_adb_allocroute(vortex_t *vortex, int dma, int nr_ch, int dir,
|
||||
memset(stream->resources, 0,
|
||||
sizeof(unsigned char) *
|
||||
VORTEX_RESOURCE_LAST);
|
||||
printk(KERN_ERR "vortex: out of A3D sources. Sorry\n");
|
||||
pr_err( "vortex: out of A3D sources. Sorry\n");
|
||||
return -EBUSY;
|
||||
}
|
||||
/* (De)Initialize A3D hardware source. */
|
||||
@ -2421,7 +2421,7 @@ static irqreturn_t vortex_interrupt(int irq, void *dev_id)
|
||||
hwread(vortex->mmio, VORTEX_IRQ_SOURCE);
|
||||
// Is at least one IRQ flag set?
|
||||
if (source == 0) {
|
||||
printk(KERN_ERR "vortex: missing irq source\n");
|
||||
pr_err( "vortex: missing irq source\n");
|
||||
return IRQ_NONE;
|
||||
}
|
||||
|
||||
@ -2429,19 +2429,19 @@ static irqreturn_t vortex_interrupt(int irq, void *dev_id)
|
||||
// Attend every interrupt source.
|
||||
if (unlikely(source & IRQ_ERR_MASK)) {
|
||||
if (source & IRQ_FATAL) {
|
||||
printk(KERN_ERR "vortex: IRQ fatal error\n");
|
||||
pr_err( "vortex: IRQ fatal error\n");
|
||||
}
|
||||
if (source & IRQ_PARITY) {
|
||||
printk(KERN_ERR "vortex: IRQ parity error\n");
|
||||
pr_err( "vortex: IRQ parity error\n");
|
||||
}
|
||||
if (source & IRQ_REG) {
|
||||
printk(KERN_ERR "vortex: IRQ reg error\n");
|
||||
pr_err( "vortex: IRQ reg error\n");
|
||||
}
|
||||
if (source & IRQ_FIFO) {
|
||||
printk(KERN_ERR "vortex: IRQ fifo error\n");
|
||||
pr_err( "vortex: IRQ fifo error\n");
|
||||
}
|
||||
if (source & IRQ_DMA) {
|
||||
printk(KERN_ERR "vortex: IRQ dma error\n");
|
||||
pr_err( "vortex: IRQ dma error\n");
|
||||
}
|
||||
handled = 1;
|
||||
}
|
||||
@ -2489,7 +2489,7 @@ static irqreturn_t vortex_interrupt(int irq, void *dev_id)
|
||||
}
|
||||
|
||||
if (!handled) {
|
||||
printk(KERN_ERR "vortex: unknown irq source %x\n", source);
|
||||
pr_err( "vortex: unknown irq source %x\n", source);
|
||||
}
|
||||
return IRQ_RETVAL(handled);
|
||||
}
|
||||
@ -2546,7 +2546,7 @@ vortex_codec_write(struct snd_ac97 * codec, unsigned short addr, unsigned short
|
||||
while (!(hwread(card->mmio, VORTEX_CODEC_CTRL) & 0x100)) {
|
||||
udelay(100);
|
||||
if (lifeboat++ > POLL_COUNT) {
|
||||
printk(KERN_ERR "vortex: ac97 codec stuck busy\n");
|
||||
pr_err( "vortex: ac97 codec stuck busy\n");
|
||||
return;
|
||||
}
|
||||
}
|
||||
@ -2572,7 +2572,7 @@ static unsigned short vortex_codec_read(struct snd_ac97 * codec, unsigned short
|
||||
while (!(hwread(card->mmio, VORTEX_CODEC_CTRL) & 0x100)) {
|
||||
udelay(100);
|
||||
if (lifeboat++ > POLL_COUNT) {
|
||||
printk(KERN_ERR "vortex: ac97 codec stuck busy\n");
|
||||
pr_err( "vortex: ac97 codec stuck busy\n");
|
||||
return 0xffff;
|
||||
}
|
||||
}
|
||||
@ -2586,7 +2586,7 @@ static unsigned short vortex_codec_read(struct snd_ac97 * codec, unsigned short
|
||||
udelay(100);
|
||||
data = hwread(card->mmio, VORTEX_CODEC_IO);
|
||||
if (lifeboat++ > POLL_COUNT) {
|
||||
printk(KERN_ERR "vortex: ac97 address never arrived\n");
|
||||
pr_err( "vortex: ac97 address never arrived\n");
|
||||
return 0xffff;
|
||||
}
|
||||
} while ((data & VORTEX_CODEC_ADDMASK) !=
|
||||
@ -2683,7 +2683,7 @@ static void vortex_spdif_init(vortex_t * vortex, int spdif_sr, int spdif_mode)
|
||||
static int vortex_core_init(vortex_t *vortex)
|
||||
{
|
||||
|
||||
printk(KERN_INFO "Vortex: init.... ");
|
||||
pr_info( "Vortex: init.... ");
|
||||
/* Hardware Init. */
|
||||
hwwrite(vortex->mmio, VORTEX_CTRL, 0xffffffff);
|
||||
msleep(5);
|
||||
@ -2728,7 +2728,7 @@ static int vortex_core_init(vortex_t *vortex)
|
||||
//vortex_enable_timer_int(vortex);
|
||||
//vortex_disable_timer_int(vortex);
|
||||
|
||||
printk(KERN_INFO "done.\n");
|
||||
pr_info( "done.\n");
|
||||
spin_lock_init(&vortex->lock);
|
||||
|
||||
return 0;
|
||||
@ -2737,7 +2737,7 @@ static int vortex_core_init(vortex_t *vortex)
|
||||
static int vortex_core_shutdown(vortex_t * vortex)
|
||||
{
|
||||
|
||||
printk(KERN_INFO "Vortex: shutdown...");
|
||||
pr_info( "Vortex: shutdown...");
|
||||
#ifndef CHIP_AU8820
|
||||
vortex_eq_free(vortex);
|
||||
vortex_Vort3D_disable(vortex);
|
||||
@ -2759,7 +2759,7 @@ static int vortex_core_shutdown(vortex_t * vortex)
|
||||
msleep(5);
|
||||
hwwrite(vortex->mmio, VORTEX_IRQ_SOURCE, 0xffff);
|
||||
|
||||
printk(KERN_INFO "done.\n");
|
||||
pr_info( "done.\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -2793,7 +2793,7 @@ static int vortex_alsafmt_aspfmt(int alsafmt)
|
||||
break;
|
||||
default:
|
||||
fmt = 0x8;
|
||||
printk(KERN_ERR "vortex: format unsupported %d\n", alsafmt);
|
||||
pr_err( "vortex: format unsupported %d\n", alsafmt);
|
||||
break;
|
||||
}
|
||||
return fmt;
|
||||
|
@ -845,7 +845,7 @@ snd_vortex_peaks_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *u
|
||||
|
||||
vortex_Eqlzr_GetAllPeaks(vortex, peaks, &count);
|
||||
if (count != 20) {
|
||||
printk(KERN_ERR "vortex: peak count error 20 != %d \n", count);
|
||||
pr_err( "vortex: peak count error 20 != %d \n", count);
|
||||
return -1;
|
||||
}
|
||||
for (i = 0; i < 20; i++)
|
||||
|
@ -98,7 +98,7 @@ static int vortex_gameport_register(vortex_t *vortex)
|
||||
|
||||
vortex->gameport = gp = gameport_allocate_port();
|
||||
if (!gp) {
|
||||
printk(KERN_ERR "vortex: cannot allocate memory for gameport\n");
|
||||
pr_err( "vortex: cannot allocate memory for gameport\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
|
@ -73,7 +73,7 @@ static int snd_vortex_midi(vortex_t *vortex)
|
||||
/* Check if anything is OK. */
|
||||
temp = hwread(vortex->mmio, VORTEX_MIDI_DATA);
|
||||
if (temp != MPU401_ACK /*0xfe */ ) {
|
||||
printk(KERN_ERR "midi port doesn't acknowledge!\n");
|
||||
pr_err( "midi port doesn't acknowledge!\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
/* Enable MPU401 interrupts. */
|
||||
|
@ -227,11 +227,11 @@ snd_vortex_pcm_hw_params(struct snd_pcm_substream *substream,
|
||||
err =
|
||||
snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params));
|
||||
if (err < 0) {
|
||||
printk(KERN_ERR "Vortex: pcm page alloc failed!\n");
|
||||
pr_err( "Vortex: pcm page alloc failed!\n");
|
||||
return err;
|
||||
}
|
||||
/*
|
||||
printk(KERN_INFO "Vortex: periods %d, period_bytes %d, channels = %d\n", params_periods(hw_params),
|
||||
pr_info( "Vortex: periods %d, period_bytes %d, channels = %d\n", params_periods(hw_params),
|
||||
params_period_bytes(hw_params), params_channels(hw_params));
|
||||
*/
|
||||
spin_lock_irq(&chip->lock);
|
||||
@ -371,7 +371,7 @@ static int snd_vortex_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
|
||||
}
|
||||
#ifndef CHIP_AU8810
|
||||
else {
|
||||
printk(KERN_INFO "vortex: wt start %d\n", dma);
|
||||
pr_info( "vortex: wt start %d\n", dma);
|
||||
vortex_wtdma_startfifo(chip, dma);
|
||||
}
|
||||
#endif
|
||||
@ -384,7 +384,7 @@ static int snd_vortex_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
|
||||
vortex_adbdma_stopfifo(chip, dma);
|
||||
#ifndef CHIP_AU8810
|
||||
else {
|
||||
printk(KERN_INFO "vortex: wt stop %d\n", dma);
|
||||
pr_info( "vortex: wt stop %d\n", dma);
|
||||
vortex_wtdma_stopfifo(chip, dma);
|
||||
}
|
||||
#endif
|
||||
|
@ -90,7 +90,7 @@ static int vortex_wt_allocroute(vortex_t * vortex, int wt, int nr_ch)
|
||||
hwwrite(vortex->mmio, WT_PARM(wt, 2), 0);
|
||||
|
||||
temp = hwread(vortex->mmio, WT_PARM(wt, 3));
|
||||
printk(KERN_DEBUG "vortex: WT PARM3: %x\n", temp);
|
||||
pr_debug( "vortex: WT PARM3: %x\n", temp);
|
||||
//hwwrite(vortex->mmio, WT_PARM(wt, 3), temp);
|
||||
|
||||
hwwrite(vortex->mmio, WT_DELAY(wt, 0), 0);
|
||||
@ -98,7 +98,7 @@ static int vortex_wt_allocroute(vortex_t * vortex, int wt, int nr_ch)
|
||||
hwwrite(vortex->mmio, WT_DELAY(wt, 2), 0);
|
||||
hwwrite(vortex->mmio, WT_DELAY(wt, 3), 0);
|
||||
|
||||
printk(KERN_DEBUG "vortex: WT GMODE: %x\n", hwread(vortex->mmio, WT_GMODE(wt)));
|
||||
pr_debug( "vortex: WT GMODE: %x\n", hwread(vortex->mmio, WT_GMODE(wt)));
|
||||
|
||||
hwwrite(vortex->mmio, WT_PARM(wt, 2), 0xffffffff);
|
||||
hwwrite(vortex->mmio, WT_PARM(wt, 3), 0xcff1c810);
|
||||
@ -106,7 +106,7 @@ static int vortex_wt_allocroute(vortex_t * vortex, int wt, int nr_ch)
|
||||
voice->parm0 = voice->parm1 = 0xcfb23e2f;
|
||||
hwwrite(vortex->mmio, WT_PARM(wt, 0), voice->parm0);
|
||||
hwwrite(vortex->mmio, WT_PARM(wt, 1), voice->parm1);
|
||||
printk(KERN_DEBUG "vortex: WT GMODE 2 : %x\n", hwread(vortex->mmio, WT_GMODE(wt)));
|
||||
pr_debug( "vortex: WT GMODE 2 : %x\n", hwread(vortex->mmio, WT_GMODE(wt)));
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -196,14 +196,14 @@ vortex_wt_SetReg(vortex_t * vortex, unsigned char reg, int wt,
|
||||
|
||||
if ((reg == 5) || ((reg >= 7) && (reg <= 10)) || (reg == 0xc)) {
|
||||
if (wt >= (NR_WT / NR_WT_PB)) {
|
||||
printk
|
||||
pr_warn
|
||||
("vortex: WT SetReg: bank out of range. reg=0x%x, wt=%d\n",
|
||||
reg, wt);
|
||||
return 0;
|
||||
}
|
||||
} else {
|
||||
if (wt >= NR_WT) {
|
||||
printk(KERN_ERR "vortex: WT SetReg: voice out of range\n");
|
||||
pr_err( "vortex: WT SetReg: voice out of range\n");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
@ -214,42 +214,42 @@ vortex_wt_SetReg(vortex_t * vortex, unsigned char reg, int wt,
|
||||
/* Voice specific parameters */
|
||||
case 0: /* running */
|
||||
/*
|
||||
printk(KERN_DEBUG "vortex: WT SetReg(0x%x) = 0x%08x\n",
|
||||
pr_debug( "vortex: WT SetReg(0x%x) = 0x%08x\n",
|
||||
WT_RUN(wt), (int)val);
|
||||
*/
|
||||
hwwrite(vortex->mmio, WT_RUN(wt), val);
|
||||
return 0xc;
|
||||
case 1: /* param 0 */
|
||||
/*
|
||||
printk(KERN_DEBUG "vortex: WT SetReg(0x%x) = 0x%08x\n",
|
||||
pr_debug( "vortex: WT SetReg(0x%x) = 0x%08x\n",
|
||||
WT_PARM(wt,0), (int)val);
|
||||
*/
|
||||
hwwrite(vortex->mmio, WT_PARM(wt, 0), val);
|
||||
return 0xc;
|
||||
case 2: /* param 1 */
|
||||
/*
|
||||
printk(KERN_DEBUG "vortex: WT SetReg(0x%x) = 0x%08x\n",
|
||||
pr_debug( "vortex: WT SetReg(0x%x) = 0x%08x\n",
|
||||
WT_PARM(wt,1), (int)val);
|
||||
*/
|
||||
hwwrite(vortex->mmio, WT_PARM(wt, 1), val);
|
||||
return 0xc;
|
||||
case 3: /* param 2 */
|
||||
/*
|
||||
printk(KERN_DEBUG "vortex: WT SetReg(0x%x) = 0x%08x\n",
|
||||
pr_debug( "vortex: WT SetReg(0x%x) = 0x%08x\n",
|
||||
WT_PARM(wt,2), (int)val);
|
||||
*/
|
||||
hwwrite(vortex->mmio, WT_PARM(wt, 2), val);
|
||||
return 0xc;
|
||||
case 4: /* param 3 */
|
||||
/*
|
||||
printk(KERN_DEBUG "vortex: WT SetReg(0x%x) = 0x%08x\n",
|
||||
pr_debug( "vortex: WT SetReg(0x%x) = 0x%08x\n",
|
||||
WT_PARM(wt,3), (int)val);
|
||||
*/
|
||||
hwwrite(vortex->mmio, WT_PARM(wt, 3), val);
|
||||
return 0xc;
|
||||
case 6: /* mute */
|
||||
/*
|
||||
printk(KERN_DEBUG "vortex: WT SetReg(0x%x) = 0x%08x\n",
|
||||
pr_debug( "vortex: WT SetReg(0x%x) = 0x%08x\n",
|
||||
WT_MUTE(wt), (int)val);
|
||||
*/
|
||||
hwwrite(vortex->mmio, WT_MUTE(wt), val);
|
||||
@ -257,7 +257,7 @@ vortex_wt_SetReg(vortex_t * vortex, unsigned char reg, int wt,
|
||||
case 0xb:
|
||||
/* delay */
|
||||
/*
|
||||
printk(KERN_DEBUG "vortex: WT SetReg(0x%x) = 0x%08x\n",
|
||||
pr_debug( "vortex: WT SetReg(0x%x) = 0x%08x\n",
|
||||
WT_DELAY(wt,0), (int)val);
|
||||
*/
|
||||
hwwrite(vortex->mmio, WT_DELAY(wt, 3), val);
|
||||
@ -285,7 +285,7 @@ vortex_wt_SetReg(vortex_t * vortex, unsigned char reg, int wt,
|
||||
return 0;
|
||||
}
|
||||
/*
|
||||
printk(KERN_DEBUG "vortex: WT SetReg(0x%x) = 0x%08x\n", ecx, (int)val);
|
||||
pr_debug( "vortex: WT SetReg(0x%x) = 0x%08x\n", ecx, (int)val);
|
||||
*/
|
||||
hwwrite(vortex->mmio, ecx, val);
|
||||
return 1;
|
||||
|
@ -258,7 +258,8 @@ static int get_amixer_rsc(struct amixer_mgr *mgr,
|
||||
}
|
||||
spin_unlock_irqrestore(&mgr->mgr_lock, flags);
|
||||
if (err) {
|
||||
printk(KERN_ERR "ctxfi: Can't meet AMIXER resource request!\n");
|
||||
dev_err(mgr->card->dev,
|
||||
"Can't meet AMIXER resource request!\n");
|
||||
goto error;
|
||||
}
|
||||
|
||||
@ -296,7 +297,7 @@ static int put_amixer_rsc(struct amixer_mgr *mgr, struct amixer *amixer)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int amixer_mgr_create(void *hw, struct amixer_mgr **ramixer_mgr)
|
||||
int amixer_mgr_create(struct hw *hw, struct amixer_mgr **ramixer_mgr)
|
||||
{
|
||||
int err;
|
||||
struct amixer_mgr *amixer_mgr;
|
||||
@ -314,6 +315,7 @@ int amixer_mgr_create(void *hw, struct amixer_mgr **ramixer_mgr)
|
||||
|
||||
amixer_mgr->get_amixer = get_amixer_rsc;
|
||||
amixer_mgr->put_amixer = put_amixer_rsc;
|
||||
amixer_mgr->card = hw->card;
|
||||
|
||||
*ramixer_mgr = amixer_mgr;
|
||||
|
||||
@ -411,7 +413,8 @@ static int get_sum_rsc(struct sum_mgr *mgr,
|
||||
}
|
||||
spin_unlock_irqrestore(&mgr->mgr_lock, flags);
|
||||
if (err) {
|
||||
printk(KERN_ERR "ctxfi: Can't meet SUM resource request!\n");
|
||||
dev_err(mgr->card->dev,
|
||||
"Can't meet SUM resource request!\n");
|
||||
goto error;
|
||||
}
|
||||
|
||||
@ -449,7 +452,7 @@ static int put_sum_rsc(struct sum_mgr *mgr, struct sum *sum)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int sum_mgr_create(void *hw, struct sum_mgr **rsum_mgr)
|
||||
int sum_mgr_create(struct hw *hw, struct sum_mgr **rsum_mgr)
|
||||
{
|
||||
int err;
|
||||
struct sum_mgr *sum_mgr;
|
||||
@ -467,6 +470,7 @@ int sum_mgr_create(void *hw, struct sum_mgr **rsum_mgr)
|
||||
|
||||
sum_mgr->get_sum = get_sum_rsc;
|
||||
sum_mgr->put_sum = put_sum_rsc;
|
||||
sum_mgr->card = hw->card;
|
||||
|
||||
*rsum_mgr = sum_mgr;
|
||||
|
||||
|
@ -21,6 +21,7 @@
|
||||
|
||||
#include "ctresource.h"
|
||||
#include <linux/spinlock.h>
|
||||
#include <sound/core.h>
|
||||
|
||||
/* Define the descriptor of a summation node resource */
|
||||
struct sum {
|
||||
@ -35,6 +36,7 @@ struct sum_desc {
|
||||
|
||||
struct sum_mgr {
|
||||
struct rsc_mgr mgr; /* Basic resource manager info */
|
||||
struct snd_card *card; /* pointer to this card */
|
||||
spinlock_t mgr_lock;
|
||||
|
||||
/* request one sum resource */
|
||||
@ -45,7 +47,7 @@ struct sum_mgr {
|
||||
};
|
||||
|
||||
/* Constructor and destructor of daio resource manager */
|
||||
int sum_mgr_create(void *hw, struct sum_mgr **rsum_mgr);
|
||||
int sum_mgr_create(struct hw *hw, struct sum_mgr **rsum_mgr);
|
||||
int sum_mgr_destroy(struct sum_mgr *sum_mgr);
|
||||
|
||||
/* Define the descriptor of a amixer resource */
|
||||
@ -79,6 +81,7 @@ struct amixer_desc {
|
||||
|
||||
struct amixer_mgr {
|
||||
struct rsc_mgr mgr; /* Basic resource manager info */
|
||||
struct snd_card *card; /* pointer to this card */
|
||||
spinlock_t mgr_lock;
|
||||
|
||||
/* request one amixer resource */
|
||||
@ -90,7 +93,7 @@ struct amixer_mgr {
|
||||
};
|
||||
|
||||
/* Constructor and destructor of amixer resource manager */
|
||||
int amixer_mgr_create(void *hw, struct amixer_mgr **ramixer_mgr);
|
||||
int amixer_mgr_create(struct hw *hw, struct amixer_mgr **ramixer_mgr);
|
||||
int amixer_mgr_destroy(struct amixer_mgr *amixer_mgr);
|
||||
|
||||
#endif /* CTAMIXER_H */
|
||||
|
@ -106,11 +106,11 @@ static struct {
|
||||
.public_name = "Mixer"}
|
||||
};
|
||||
|
||||
typedef int (*create_t)(void *, void **);
|
||||
typedef int (*create_t)(struct hw *, void **);
|
||||
typedef int (*destroy_t)(void *);
|
||||
|
||||
static struct {
|
||||
int (*create)(void *hw, void **rmgr);
|
||||
int (*create)(struct hw *hw, void **rmgr);
|
||||
int (*destroy)(void *mgr);
|
||||
} rsc_mgr_funcs[NUM_RSCTYP] = {
|
||||
[SRC] = { .create = (create_t)src_mgr_create,
|
||||
@ -171,7 +171,8 @@ static unsigned long atc_get_ptp_phys(struct ct_atc *atc, int index)
|
||||
return atc->vm->get_ptp_phys(atc->vm, index);
|
||||
}
|
||||
|
||||
static unsigned int convert_format(snd_pcm_format_t snd_format)
|
||||
static unsigned int convert_format(snd_pcm_format_t snd_format,
|
||||
struct snd_card *card)
|
||||
{
|
||||
switch (snd_format) {
|
||||
case SNDRV_PCM_FORMAT_U8:
|
||||
@ -185,7 +186,7 @@ static unsigned int convert_format(snd_pcm_format_t snd_format)
|
||||
case SNDRV_PCM_FORMAT_FLOAT_LE:
|
||||
return SRC_SF_F32;
|
||||
default:
|
||||
printk(KERN_ERR "ctxfi: not recognized snd format is %d \n",
|
||||
dev_err(card->dev, "not recognized snd format is %d\n",
|
||||
snd_format);
|
||||
return SRC_SF_S16;
|
||||
}
|
||||
@ -268,7 +269,8 @@ static int atc_pcm_playback_prepare(struct ct_atc *atc, struct ct_atc_pcm *apcm)
|
||||
src = apcm->src;
|
||||
src->ops->set_pitch(src, pitch);
|
||||
src->ops->set_rom(src, select_rom(pitch));
|
||||
src->ops->set_sf(src, convert_format(apcm->substream->runtime->format));
|
||||
src->ops->set_sf(src, convert_format(apcm->substream->runtime->format,
|
||||
atc->card));
|
||||
src->ops->set_pm(src, (src->ops->next_interleave(src) != NULL));
|
||||
|
||||
/* Get AMIXER resource */
|
||||
@ -738,7 +740,8 @@ static int atc_pcm_capture_start(struct ct_atc *atc, struct ct_atc_pcm *apcm)
|
||||
|
||||
/* Set up recording SRC */
|
||||
src = apcm->src;
|
||||
src->ops->set_sf(src, convert_format(apcm->substream->runtime->format));
|
||||
src->ops->set_sf(src, convert_format(apcm->substream->runtime->format,
|
||||
atc->card));
|
||||
src->ops->set_sa(src, apcm->vm_block->addr);
|
||||
src->ops->set_la(src, apcm->vm_block->addr + apcm->vm_block->size);
|
||||
src->ops->set_ca(src, apcm->vm_block->addr);
|
||||
@ -807,7 +810,8 @@ static int spdif_passthru_playback_get_resources(struct ct_atc *atc,
|
||||
src = apcm->src;
|
||||
src->ops->set_pitch(src, pitch);
|
||||
src->ops->set_rom(src, select_rom(pitch));
|
||||
src->ops->set_sf(src, convert_format(apcm->substream->runtime->format));
|
||||
src->ops->set_sf(src, convert_format(apcm->substream->runtime->format,
|
||||
atc->card));
|
||||
src->ops->set_pm(src, (src->ops->next_interleave(src) != NULL));
|
||||
src->ops->set_bp(src, 1);
|
||||
|
||||
@ -1235,7 +1239,7 @@ static int ct_atc_destroy(struct ct_atc *atc)
|
||||
}
|
||||
|
||||
if (atc->hw)
|
||||
destroy_hw_obj((struct hw *)atc->hw);
|
||||
destroy_hw_obj(atc->hw);
|
||||
|
||||
/* Destroy device virtual memory manager object */
|
||||
if (atc->vm) {
|
||||
@ -1282,9 +1286,9 @@ static int atc_identify_card(struct ct_atc *atc, unsigned int ssid)
|
||||
p = snd_pci_quirk_lookup_id(vendor_id, device_id, list);
|
||||
if (p) {
|
||||
if (p->value < 0) {
|
||||
printk(KERN_ERR "ctxfi: "
|
||||
"Device %04x:%04x is black-listed\n",
|
||||
vendor_id, device_id);
|
||||
dev_err(atc->card->dev,
|
||||
"Device %04x:%04x is black-listed\n",
|
||||
vendor_id, device_id);
|
||||
return -ENOENT;
|
||||
}
|
||||
atc->model = p->value;
|
||||
@ -1315,8 +1319,8 @@ int ct_atc_create_alsa_devs(struct ct_atc *atc)
|
||||
err = alsa_dev_funcs[i].create(atc, i,
|
||||
alsa_dev_funcs[i].public_name);
|
||||
if (err) {
|
||||
printk(KERN_ERR "ctxfi: "
|
||||
"Creating alsa device %d failed!\n", i);
|
||||
dev_err(atc->card->dev,
|
||||
"Creating alsa device %d failed!\n", i);
|
||||
return err;
|
||||
}
|
||||
}
|
||||
@ -1332,9 +1336,10 @@ static int atc_create_hw_devs(struct ct_atc *atc)
|
||||
|
||||
err = create_hw_obj(atc->pci, atc->chip_type, atc->model, &hw);
|
||||
if (err) {
|
||||
printk(KERN_ERR "Failed to create hw obj!!!\n");
|
||||
dev_err(atc->card->dev, "Failed to create hw obj!!!\n");
|
||||
return err;
|
||||
}
|
||||
hw->card = atc->card;
|
||||
atc->hw = hw;
|
||||
|
||||
/* Initialize card hardware. */
|
||||
@ -1351,8 +1356,8 @@ static int atc_create_hw_devs(struct ct_atc *atc)
|
||||
|
||||
err = rsc_mgr_funcs[i].create(atc->hw, &atc->rsc_mgrs[i]);
|
||||
if (err) {
|
||||
printk(KERN_ERR "ctxfi: "
|
||||
"Failed to create rsc_mgr %d!!!\n", i);
|
||||
dev_err(atc->card->dev,
|
||||
"Failed to create rsc_mgr %d!!!\n", i);
|
||||
return err;
|
||||
}
|
||||
}
|
||||
@ -1399,8 +1404,9 @@ static int atc_get_resources(struct ct_atc *atc)
|
||||
err = daio_mgr->get_daio(daio_mgr, &da_desc,
|
||||
(struct daio **)&atc->daios[i]);
|
||||
if (err) {
|
||||
printk(KERN_ERR "ctxfi: Failed to get DAIO "
|
||||
"resource %d!!!\n", i);
|
||||
dev_err(atc->card->dev,
|
||||
"Failed to get DAIO resource %d!!!\n",
|
||||
i);
|
||||
return err;
|
||||
}
|
||||
atc->n_daio++;
|
||||
@ -1603,8 +1609,8 @@ static int atc_resume(struct ct_atc *atc)
|
||||
/* Do hardware resume. */
|
||||
err = atc_hw_resume(atc);
|
||||
if (err < 0) {
|
||||
printk(KERN_ERR "ctxfi: pci_enable_device failed, "
|
||||
"disabling device\n");
|
||||
dev_err(atc->card->dev,
|
||||
"pci_enable_device failed, disabling device\n");
|
||||
snd_card_disconnect(atc->card);
|
||||
return err;
|
||||
}
|
||||
@ -1701,7 +1707,7 @@ int ct_atc_create(struct snd_card *card, struct pci_dev *pci,
|
||||
/* Find card model */
|
||||
err = atc_identify_card(atc, ssid);
|
||||
if (err < 0) {
|
||||
printk(KERN_ERR "ctatc: Card not recognised\n");
|
||||
dev_err(card->dev, "ctatc: Card not recognised\n");
|
||||
goto error1;
|
||||
}
|
||||
|
||||
@ -1717,7 +1723,7 @@ int ct_atc_create(struct snd_card *card, struct pci_dev *pci,
|
||||
|
||||
err = ct_mixer_create(atc, (struct ct_mixer **)&atc->mixer);
|
||||
if (err) {
|
||||
printk(KERN_ERR "ctxfi: Failed to create mixer obj!!!\n");
|
||||
dev_err(card->dev, "Failed to create mixer obj!!!\n");
|
||||
goto error1;
|
||||
}
|
||||
|
||||
@ -1744,6 +1750,6 @@ int ct_atc_create(struct snd_card *card, struct pci_dev *pci,
|
||||
|
||||
error1:
|
||||
ct_atc_destroy(atc);
|
||||
printk(KERN_ERR "ctxfi: Something wrong!!!\n");
|
||||
dev_err(card->dev, "Something wrong!!!\n");
|
||||
return err;
|
||||
}
|
||||
|
@ -131,7 +131,7 @@ struct ct_atc {
|
||||
/* Don't touch! Used for internal object. */
|
||||
void *rsc_mgrs[NUM_RSCTYP]; /* chip resource managers */
|
||||
void *mixer; /* internal mixer object */
|
||||
void *hw; /* chip specific hardware access object */
|
||||
struct hw *hw; /* chip specific hardware access object */
|
||||
void **daios; /* digital audio io resources */
|
||||
void **pcm; /* SUMs for collecting all pcm stream */
|
||||
void **srcs; /* Sample Rate Converters for input signal */
|
||||
|
@ -140,19 +140,19 @@ static int dao_rsc_reinit(struct dao *dao, const struct dao_desc *desc);
|
||||
|
||||
static int dao_spdif_get_spos(struct dao *dao, unsigned int *spos)
|
||||
{
|
||||
((struct hw *)dao->hw)->dao_get_spos(dao->ctrl_blk, spos);
|
||||
dao->hw->dao_get_spos(dao->ctrl_blk, spos);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int dao_spdif_set_spos(struct dao *dao, unsigned int spos)
|
||||
{
|
||||
((struct hw *)dao->hw)->dao_set_spos(dao->ctrl_blk, spos);
|
||||
dao->hw->dao_set_spos(dao->ctrl_blk, spos);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int dao_commit_write(struct dao *dao)
|
||||
{
|
||||
((struct hw *)dao->hw)->dao_commit_write(dao->hw,
|
||||
dao->hw->dao_commit_write(dao->hw,
|
||||
daio_device_index(dao->daio.type, dao->hw), dao->ctrl_blk);
|
||||
return 0;
|
||||
}
|
||||
@ -277,16 +277,14 @@ static struct dao_rsc_ops dao_ops = {
|
||||
static int dai_set_srt_srcl(struct dai *dai, struct rsc *src)
|
||||
{
|
||||
src->ops->master(src);
|
||||
((struct hw *)dai->hw)->dai_srt_set_srcm(dai->ctrl_blk,
|
||||
src->ops->index(src));
|
||||
dai->hw->dai_srt_set_srcm(dai->ctrl_blk, src->ops->index(src));
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int dai_set_srt_srcr(struct dai *dai, struct rsc *src)
|
||||
{
|
||||
src->ops->master(src);
|
||||
((struct hw *)dai->hw)->dai_srt_set_srco(dai->ctrl_blk,
|
||||
src->ops->index(src));
|
||||
dai->hw->dai_srt_set_srco(dai->ctrl_blk, src->ops->index(src));
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -297,25 +295,25 @@ static int dai_set_srt_msr(struct dai *dai, unsigned int msr)
|
||||
for (rsr = 0; msr > 1; msr >>= 1)
|
||||
rsr++;
|
||||
|
||||
((struct hw *)dai->hw)->dai_srt_set_rsr(dai->ctrl_blk, rsr);
|
||||
dai->hw->dai_srt_set_rsr(dai->ctrl_blk, rsr);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int dai_set_enb_src(struct dai *dai, unsigned int enb)
|
||||
{
|
||||
((struct hw *)dai->hw)->dai_srt_set_ec(dai->ctrl_blk, enb);
|
||||
dai->hw->dai_srt_set_ec(dai->ctrl_blk, enb);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int dai_set_enb_srt(struct dai *dai, unsigned int enb)
|
||||
{
|
||||
((struct hw *)dai->hw)->dai_srt_set_et(dai->ctrl_blk, enb);
|
||||
dai->hw->dai_srt_set_et(dai->ctrl_blk, enb);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int dai_commit_write(struct dai *dai)
|
||||
{
|
||||
((struct hw *)dai->hw)->dai_commit_write(dai->hw,
|
||||
dai->hw->dai_commit_write(dai->hw,
|
||||
daio_device_index(dai->daio.type, dai->hw), dai->ctrl_blk);
|
||||
return 0;
|
||||
}
|
||||
@ -331,12 +329,12 @@ static struct dai_rsc_ops dai_ops = {
|
||||
|
||||
static int daio_rsc_init(struct daio *daio,
|
||||
const struct daio_desc *desc,
|
||||
void *hw)
|
||||
struct hw *hw)
|
||||
{
|
||||
int err;
|
||||
unsigned int idx_l, idx_r;
|
||||
|
||||
switch (((struct hw *)hw)->chip_type) {
|
||||
switch (hw->chip_type) {
|
||||
case ATC20K1:
|
||||
idx_l = idx_20k1[desc->type].left;
|
||||
idx_r = idx_20k1[desc->type].right;
|
||||
@ -360,7 +358,7 @@ static int daio_rsc_init(struct daio *daio,
|
||||
if (desc->type <= DAIO_OUT_MAX) {
|
||||
daio->rscl.ops = daio->rscr.ops = &daio_out_rsc_ops;
|
||||
} else {
|
||||
switch (((struct hw *)hw)->chip_type) {
|
||||
switch (hw->chip_type) {
|
||||
case ATC20K1:
|
||||
daio->rscl.ops = daio->rscr.ops = &daio_in_rsc_ops_20k1;
|
||||
break;
|
||||
@ -445,7 +443,7 @@ static int dao_rsc_uninit(struct dao *dao)
|
||||
kfree(dao->imappers);
|
||||
dao->imappers = NULL;
|
||||
}
|
||||
((struct hw *)dao->hw)->dao_put_ctrl_blk(dao->ctrl_blk);
|
||||
dao->hw->dao_put_ctrl_blk(dao->ctrl_blk);
|
||||
dao->hw = dao->ctrl_blk = NULL;
|
||||
daio_rsc_uninit(&dao->daio);
|
||||
|
||||
@ -502,7 +500,7 @@ error1:
|
||||
|
||||
static int dai_rsc_uninit(struct dai *dai)
|
||||
{
|
||||
((struct hw *)dai->hw)->dai_put_ctrl_blk(dai->ctrl_blk);
|
||||
dai->hw->dai_put_ctrl_blk(dai->ctrl_blk);
|
||||
dai->hw = dai->ctrl_blk = NULL;
|
||||
daio_rsc_uninit(&dai->daio);
|
||||
return 0;
|
||||
@ -541,7 +539,8 @@ static int get_daio_rsc(struct daio_mgr *mgr,
|
||||
err = daio_mgr_get_rsc(&mgr->mgr, desc->type);
|
||||
spin_unlock_irqrestore(&mgr->mgr_lock, flags);
|
||||
if (err) {
|
||||
printk(KERN_ERR "Can't meet DAIO resource request!\n");
|
||||
dev_err(mgr->card->dev,
|
||||
"Can't meet DAIO resource request!\n");
|
||||
return err;
|
||||
}
|
||||
|
||||
@ -692,7 +691,7 @@ static int daio_mgr_commit_write(struct daio_mgr *mgr)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int daio_mgr_create(void *hw, struct daio_mgr **rdaio_mgr)
|
||||
int daio_mgr_create(struct hw *hw, struct daio_mgr **rdaio_mgr)
|
||||
{
|
||||
int err, i;
|
||||
struct daio_mgr *daio_mgr;
|
||||
@ -727,12 +726,13 @@ int daio_mgr_create(void *hw, struct daio_mgr **rdaio_mgr)
|
||||
daio_mgr->imap_add = daio_imap_add;
|
||||
daio_mgr->imap_delete = daio_imap_delete;
|
||||
daio_mgr->commit_write = daio_mgr_commit_write;
|
||||
daio_mgr->card = hw->card;
|
||||
|
||||
for (i = 0; i < 8; i++) {
|
||||
((struct hw *)hw)->daio_mgr_dsb_dao(daio_mgr->mgr.ctrl_blk, i);
|
||||
((struct hw *)hw)->daio_mgr_dsb_dai(daio_mgr->mgr.ctrl_blk, i);
|
||||
hw->daio_mgr_dsb_dao(daio_mgr->mgr.ctrl_blk, i);
|
||||
hw->daio_mgr_dsb_dai(daio_mgr->mgr.ctrl_blk, i);
|
||||
}
|
||||
((struct hw *)hw)->daio_mgr_commit_write(hw, daio_mgr->mgr.ctrl_blk);
|
||||
hw->daio_mgr_commit_write(hw, daio_mgr->mgr.ctrl_blk);
|
||||
|
||||
*rdaio_mgr = daio_mgr;
|
||||
|
||||
|
@ -23,6 +23,7 @@
|
||||
#include "ctimap.h"
|
||||
#include <linux/spinlock.h>
|
||||
#include <linux/list.h>
|
||||
#include <sound/core.h>
|
||||
|
||||
/* Define the descriptor of a daio resource */
|
||||
enum DAIOTYP {
|
||||
@ -53,14 +54,14 @@ struct dao {
|
||||
struct dao_rsc_ops *ops; /* DAO specific operations */
|
||||
struct imapper **imappers;
|
||||
struct daio_mgr *mgr;
|
||||
void *hw;
|
||||
struct hw *hw;
|
||||
void *ctrl_blk;
|
||||
};
|
||||
|
||||
struct dai {
|
||||
struct daio daio;
|
||||
struct dai_rsc_ops *ops; /* DAI specific operations */
|
||||
void *hw;
|
||||
struct hw *hw;
|
||||
void *ctrl_blk;
|
||||
};
|
||||
|
||||
@ -98,6 +99,7 @@ struct daio_desc {
|
||||
|
||||
struct daio_mgr {
|
||||
struct rsc_mgr mgr; /* Basic resource manager info */
|
||||
struct snd_card *card; /* pointer to this card */
|
||||
spinlock_t mgr_lock;
|
||||
spinlock_t imap_lock;
|
||||
struct list_head imappers;
|
||||
@ -117,7 +119,7 @@ struct daio_mgr {
|
||||
};
|
||||
|
||||
/* Constructor and destructor of daio resource manager */
|
||||
int daio_mgr_create(void *hw, struct daio_mgr **rdaio_mgr);
|
||||
int daio_mgr_create(struct hw *hw, struct daio_mgr **rdaio_mgr);
|
||||
int daio_mgr_destroy(struct daio_mgr *daio_mgr);
|
||||
|
||||
#endif /* CTDAIO_H */
|
||||
|
@ -20,6 +20,7 @@
|
||||
|
||||
#include <linux/types.h>
|
||||
#include <linux/pci.h>
|
||||
#include <sound/core.h>
|
||||
|
||||
enum CHIPTYP {
|
||||
ATC20K1,
|
||||
@ -184,9 +185,10 @@ struct hw {
|
||||
void *irq_callback_data;
|
||||
|
||||
struct pci_dev *pci; /* the pci kernel structure of this card */
|
||||
struct snd_card *card; /* pointer to this card */
|
||||
int irq;
|
||||
unsigned long io_base;
|
||||
unsigned long mem_base;
|
||||
void __iomem *mem_base;
|
||||
|
||||
enum CHIPTYP chip_type;
|
||||
enum CTCARDS model;
|
||||
|
@ -1268,7 +1268,8 @@ static int hw_trn_init(struct hw *hw, const struct trn_conf *info)
|
||||
|
||||
/* Set up device page table */
|
||||
if ((~0UL) == info->vm_pgt_phys) {
|
||||
printk(KERN_ERR "Wrong device page table page address!\n");
|
||||
dev_err(hw->card->dev,
|
||||
"Wrong device page table page address!\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
@ -1327,7 +1328,7 @@ static int hw_pll_init(struct hw *hw, unsigned int rsr)
|
||||
mdelay(40);
|
||||
}
|
||||
if (i >= 3) {
|
||||
printk(KERN_ALERT "PLL initialization failed!!!\n");
|
||||
dev_alert(hw->card->dev, "PLL initialization failed!!!\n");
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
@ -1351,7 +1352,7 @@ static int hw_auto_init(struct hw *hw)
|
||||
break;
|
||||
}
|
||||
if (!get_field(gctl, GCTL_AID)) {
|
||||
printk(KERN_ALERT "Card Auto-init failed!!!\n");
|
||||
dev_alert(hw->card->dev, "Card Auto-init failed!!!\n");
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
@ -1802,7 +1803,7 @@ static int uaa_to_xfi(struct pci_dev *pci)
|
||||
unsigned int is_uaa;
|
||||
unsigned int data[4] = {0};
|
||||
unsigned int io_base;
|
||||
void *mem_base;
|
||||
void __iomem *mem_base;
|
||||
int i;
|
||||
const u32 CTLX = CTLBITS('C', 'T', 'L', 'X');
|
||||
const u32 CTL_ = CTLBITS('C', 'T', 'L', '-');
|
||||
@ -1911,9 +1912,9 @@ static int hw_card_start(struct hw *hw)
|
||||
/* Set DMA transfer mask */
|
||||
if (pci_set_dma_mask(pci, CT_XFI_DMA_MASK) < 0 ||
|
||||
pci_set_consistent_dma_mask(pci, CT_XFI_DMA_MASK) < 0) {
|
||||
printk(KERN_ERR "architecture does not support PCI "
|
||||
"busmaster DMA with mask 0x%llx\n",
|
||||
CT_XFI_DMA_MASK);
|
||||
dev_err(hw->card->dev,
|
||||
"architecture does not support PCI busmaster DMA with mask 0x%llx\n",
|
||||
CT_XFI_DMA_MASK);
|
||||
err = -ENXIO;
|
||||
goto error1;
|
||||
}
|
||||
@ -1942,7 +1943,8 @@ static int hw_card_start(struct hw *hw)
|
||||
err = request_irq(pci->irq, ct_20k1_interrupt, IRQF_SHARED,
|
||||
KBUILD_MODNAME, hw);
|
||||
if (err < 0) {
|
||||
printk(KERN_ERR "XFi: Cannot get irq %d\n", pci->irq);
|
||||
dev_err(hw->card->dev,
|
||||
"XFi: Cannot get irq %d\n", pci->irq);
|
||||
goto error2;
|
||||
}
|
||||
hw->irq = pci->irq;
|
||||
@ -1985,9 +1987,9 @@ static int hw_card_shutdown(struct hw *hw)
|
||||
hw->irq = -1;
|
||||
|
||||
if (hw->mem_base)
|
||||
iounmap((void *)hw->mem_base);
|
||||
iounmap(hw->mem_base);
|
||||
|
||||
hw->mem_base = (unsigned long)NULL;
|
||||
hw->mem_base = NULL;
|
||||
|
||||
if (hw->io_base)
|
||||
pci_release_regions(hw->pci);
|
||||
|
@ -1187,7 +1187,8 @@ static int hw_daio_init(struct hw *hw, const struct daio_conf *info)
|
||||
hw_write_20kx(hw, AUDIO_IO_TX_BLRCLK, 0x21212121);
|
||||
hw_write_20kx(hw, AUDIO_IO_RX_BLRCLK, 0);
|
||||
} else {
|
||||
printk(KERN_ALERT "ctxfi: ERROR!!! Invalid sampling rate!!!\n");
|
||||
dev_alert(hw->card->dev,
|
||||
"ERROR!!! Invalid sampling rate!!!\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
@ -1246,8 +1247,8 @@ static int hw_trn_init(struct hw *hw, const struct trn_conf *info)
|
||||
|
||||
/* Set up device page table */
|
||||
if ((~0UL) == info->vm_pgt_phys) {
|
||||
printk(KERN_ALERT "ctxfi: "
|
||||
"Wrong device page table page address!!!\n");
|
||||
dev_alert(hw->card->dev,
|
||||
"Wrong device page table page address!!!\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
@ -1352,7 +1353,8 @@ static int hw_pll_init(struct hw *hw, unsigned int rsr)
|
||||
break;
|
||||
}
|
||||
if (i >= 1000) {
|
||||
printk(KERN_ALERT "ctxfi: PLL initialization failed!!!\n");
|
||||
dev_alert(hw->card->dev,
|
||||
"PLL initialization failed!!!\n");
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
@ -1376,7 +1378,7 @@ static int hw_auto_init(struct hw *hw)
|
||||
break;
|
||||
}
|
||||
if (!get_field(gctl, GCTL_AID)) {
|
||||
printk(KERN_ALERT "ctxfi: Card Auto-init failed!!!\n");
|
||||
dev_alert(hw->card->dev, "Card Auto-init failed!!!\n");
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
@ -1847,7 +1849,7 @@ static int hw_adc_init(struct hw *hw, const struct adc_conf *info)
|
||||
/* Initialize I2C */
|
||||
err = hw20k2_i2c_init(hw, 0x1A, 1, 1);
|
||||
if (err < 0) {
|
||||
printk(KERN_ALERT "ctxfi: Failure to acquire I2C!!!\n");
|
||||
dev_alert(hw->card->dev, "Failure to acquire I2C!!!\n");
|
||||
goto error;
|
||||
}
|
||||
|
||||
@ -1890,8 +1892,9 @@ static int hw_adc_init(struct hw *hw, const struct adc_conf *info)
|
||||
hw20k2_i2c_write(hw, MAKE_WM8775_ADDR(WM8775_MMC, 0x0A),
|
||||
MAKE_WM8775_DATA(0x0A));
|
||||
} else {
|
||||
printk(KERN_ALERT "ctxfi: Invalid master sampling "
|
||||
"rate (msr %d)!!!\n", info->msr);
|
||||
dev_alert(hw->card->dev,
|
||||
"Invalid master sampling rate (msr %d)!!!\n",
|
||||
info->msr);
|
||||
err = -EINVAL;
|
||||
goto error;
|
||||
}
|
||||
@ -2034,8 +2037,9 @@ static int hw_card_start(struct hw *hw)
|
||||
/* Set DMA transfer mask */
|
||||
if (pci_set_dma_mask(pci, CT_XFI_DMA_MASK) < 0 ||
|
||||
pci_set_consistent_dma_mask(pci, CT_XFI_DMA_MASK) < 0) {
|
||||
printk(KERN_ERR "ctxfi: architecture does not support PCI "
|
||||
"busmaster DMA with mask 0x%llx\n", CT_XFI_DMA_MASK);
|
||||
dev_err(hw->card->dev,
|
||||
"architecture does not support PCI busmaster DMA with mask 0x%llx\n",
|
||||
CT_XFI_DMA_MASK);
|
||||
err = -ENXIO;
|
||||
goto error1;
|
||||
}
|
||||
@ -2046,8 +2050,8 @@ static int hw_card_start(struct hw *hw)
|
||||
goto error1;
|
||||
|
||||
hw->io_base = pci_resource_start(hw->pci, 2);
|
||||
hw->mem_base = (unsigned long)ioremap(hw->io_base,
|
||||
pci_resource_len(hw->pci, 2));
|
||||
hw->mem_base = ioremap(hw->io_base,
|
||||
pci_resource_len(hw->pci, 2));
|
||||
if (!hw->mem_base) {
|
||||
err = -ENOENT;
|
||||
goto error2;
|
||||
@ -2063,7 +2067,8 @@ static int hw_card_start(struct hw *hw)
|
||||
err = request_irq(pci->irq, ct_20k2_interrupt, IRQF_SHARED,
|
||||
KBUILD_MODNAME, hw);
|
||||
if (err < 0) {
|
||||
printk(KERN_ERR "XFi: Cannot get irq %d\n", pci->irq);
|
||||
dev_err(hw->card->dev,
|
||||
"XFi: Cannot get irq %d\n", pci->irq);
|
||||
goto error2;
|
||||
}
|
||||
hw->irq = pci->irq;
|
||||
@ -2107,9 +2112,9 @@ static int hw_card_shutdown(struct hw *hw)
|
||||
hw->irq = -1;
|
||||
|
||||
if (hw->mem_base)
|
||||
iounmap((void *)hw->mem_base);
|
||||
iounmap(hw->mem_base);
|
||||
|
||||
hw->mem_base = (unsigned long)NULL;
|
||||
hw->mem_base = NULL;
|
||||
|
||||
if (hw->io_base)
|
||||
pci_release_regions(hw->pci);
|
||||
@ -2229,12 +2234,12 @@ static int hw_resume(struct hw *hw, struct card_conf *info)
|
||||
|
||||
static u32 hw_read_20kx(struct hw *hw, u32 reg)
|
||||
{
|
||||
return readl((void *)(hw->mem_base + reg));
|
||||
return readl(hw->mem_base + reg);
|
||||
}
|
||||
|
||||
static void hw_write_20kx(struct hw *hw, u32 reg, u32 data)
|
||||
{
|
||||
writel(data, (void *)(hw->mem_base + reg));
|
||||
writel(data, hw->mem_base + reg);
|
||||
}
|
||||
|
||||
static struct hw ct20k2_preset = {
|
||||
|
@ -854,8 +854,8 @@ static int ct_mixer_get_resources(struct ct_mixer *mixer)
|
||||
for (i = 0; i < (NUM_CT_SUMS * CHN_NUM); i++) {
|
||||
err = sum_mgr->get_sum(sum_mgr, &sum_desc, &sum);
|
||||
if (err) {
|
||||
printk(KERN_ERR "ctxfi:Failed to get sum resources for "
|
||||
"front output!\n");
|
||||
dev_err(mixer->atc->card->dev,
|
||||
"Failed to get sum resources for front output!\n");
|
||||
break;
|
||||
}
|
||||
mixer->sums[i] = sum;
|
||||
@ -869,8 +869,8 @@ static int ct_mixer_get_resources(struct ct_mixer *mixer)
|
||||
for (i = 0; i < (NUM_CT_AMIXERS * CHN_NUM); i++) {
|
||||
err = amixer_mgr->get_amixer(amixer_mgr, &am_desc, &amixer);
|
||||
if (err) {
|
||||
printk(KERN_ERR "ctxfi:Failed to get amixer resources "
|
||||
"for mixer obj!\n");
|
||||
dev_err(mixer->atc->card->dev,
|
||||
"Failed to get amixer resources for mixer obj!\n");
|
||||
break;
|
||||
}
|
||||
mixer->amixers[i] = amixer;
|
||||
|
@ -217,7 +217,8 @@ static int ct_pcm_playback_prepare(struct snd_pcm_substream *substream)
|
||||
err = atc->pcm_playback_prepare(atc, apcm);
|
||||
|
||||
if (err < 0) {
|
||||
printk(KERN_ERR "ctxfi: Preparing pcm playback failed!!!\n");
|
||||
dev_err(atc->card->dev,
|
||||
"Preparing pcm playback failed!!!\n");
|
||||
return err;
|
||||
}
|
||||
|
||||
@ -324,7 +325,8 @@ static int ct_pcm_capture_prepare(struct snd_pcm_substream *substream)
|
||||
|
||||
err = atc->pcm_capture_prepare(atc, apcm);
|
||||
if (err < 0) {
|
||||
printk(KERN_ERR "ctxfi: Preparing pcm capture failed!!!\n");
|
||||
dev_err(atc->card->dev,
|
||||
"Preparing pcm capture failed!!!\n");
|
||||
return err;
|
||||
}
|
||||
|
||||
@ -435,7 +437,8 @@ int ct_alsa_pcm_create(struct ct_atc *atc,
|
||||
err = snd_pcm_new(atc->card, "ctxfi", device,
|
||||
playback_count, capture_count, &pcm);
|
||||
if (err < 0) {
|
||||
printk(KERN_ERR "ctxfi: snd_pcm_new failed!! Err=%d\n", err);
|
||||
dev_err(atc->card->dev, "snd_pcm_new failed!! Err=%d\n",
|
||||
err);
|
||||
return err;
|
||||
}
|
||||
|
||||
|
@ -134,7 +134,8 @@ static struct rsc_ops rsc_generic_ops = {
|
||||
.next_conj = rsc_next_conj,
|
||||
};
|
||||
|
||||
int rsc_init(struct rsc *rsc, u32 idx, enum RSCTYP type, u32 msr, void *hw)
|
||||
int
|
||||
rsc_init(struct rsc *rsc, u32 idx, enum RSCTYP type, u32 msr, struct hw *hw)
|
||||
{
|
||||
int err = 0;
|
||||
|
||||
@ -151,25 +152,24 @@ int rsc_init(struct rsc *rsc, u32 idx, enum RSCTYP type, u32 msr, void *hw)
|
||||
|
||||
switch (type) {
|
||||
case SRC:
|
||||
err = ((struct hw *)hw)->src_rsc_get_ctrl_blk(&rsc->ctrl_blk);
|
||||
err = hw->src_rsc_get_ctrl_blk(&rsc->ctrl_blk);
|
||||
break;
|
||||
case AMIXER:
|
||||
err = ((struct hw *)hw)->
|
||||
amixer_rsc_get_ctrl_blk(&rsc->ctrl_blk);
|
||||
err = hw->amixer_rsc_get_ctrl_blk(&rsc->ctrl_blk);
|
||||
break;
|
||||
case SRCIMP:
|
||||
case SUM:
|
||||
case DAIO:
|
||||
break;
|
||||
default:
|
||||
printk(KERN_ERR
|
||||
"ctxfi: Invalid resource type value %d!\n", type);
|
||||
dev_err(((struct hw *)hw)->card->dev,
|
||||
"Invalid resource type value %d!\n", type);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (err) {
|
||||
printk(KERN_ERR
|
||||
"ctxfi: Failed to get resource control block!\n");
|
||||
dev_err(((struct hw *)hw)->card->dev,
|
||||
"Failed to get resource control block!\n");
|
||||
return err;
|
||||
}
|
||||
|
||||
@ -181,19 +181,18 @@ int rsc_uninit(struct rsc *rsc)
|
||||
if ((NULL != rsc->hw) && (NULL != rsc->ctrl_blk)) {
|
||||
switch (rsc->type) {
|
||||
case SRC:
|
||||
((struct hw *)rsc->hw)->
|
||||
src_rsc_put_ctrl_blk(rsc->ctrl_blk);
|
||||
rsc->hw->src_rsc_put_ctrl_blk(rsc->ctrl_blk);
|
||||
break;
|
||||
case AMIXER:
|
||||
((struct hw *)rsc->hw)->
|
||||
amixer_rsc_put_ctrl_blk(rsc->ctrl_blk);
|
||||
rsc->hw->amixer_rsc_put_ctrl_blk(rsc->ctrl_blk);
|
||||
break;
|
||||
case SUM:
|
||||
case DAIO:
|
||||
break;
|
||||
default:
|
||||
printk(KERN_ERR "ctxfi: "
|
||||
"Invalid resource type value %d!\n", rsc->type);
|
||||
dev_err(((struct hw *)rsc->hw)->card->dev,
|
||||
"Invalid resource type value %d!\n",
|
||||
rsc->type);
|
||||
break;
|
||||
}
|
||||
|
||||
@ -208,10 +207,9 @@ int rsc_uninit(struct rsc *rsc)
|
||||
}
|
||||
|
||||
int rsc_mgr_init(struct rsc_mgr *mgr, enum RSCTYP type,
|
||||
unsigned int amount, void *hw_obj)
|
||||
unsigned int amount, struct hw *hw)
|
||||
{
|
||||
int err = 0;
|
||||
struct hw *hw = hw_obj;
|
||||
|
||||
mgr->type = NUM_RSCTYP;
|
||||
|
||||
@ -235,15 +233,15 @@ int rsc_mgr_init(struct rsc_mgr *mgr, enum RSCTYP type,
|
||||
case SUM:
|
||||
break;
|
||||
default:
|
||||
printk(KERN_ERR
|
||||
"ctxfi: Invalid resource type value %d!\n", type);
|
||||
dev_err(hw->card->dev,
|
||||
"Invalid resource type value %d!\n", type);
|
||||
err = -EINVAL;
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (err) {
|
||||
printk(KERN_ERR
|
||||
"ctxfi: Failed to get manager control block!\n");
|
||||
dev_err(hw->card->dev,
|
||||
"Failed to get manager control block!\n");
|
||||
goto error;
|
||||
}
|
||||
|
||||
@ -268,26 +266,23 @@ int rsc_mgr_uninit(struct rsc_mgr *mgr)
|
||||
if ((NULL != mgr->hw) && (NULL != mgr->ctrl_blk)) {
|
||||
switch (mgr->type) {
|
||||
case SRC:
|
||||
((struct hw *)mgr->hw)->
|
||||
src_mgr_put_ctrl_blk(mgr->ctrl_blk);
|
||||
mgr->hw->src_mgr_put_ctrl_blk(mgr->ctrl_blk);
|
||||
break;
|
||||
case SRCIMP:
|
||||
((struct hw *)mgr->hw)->
|
||||
srcimp_mgr_put_ctrl_blk(mgr->ctrl_blk);
|
||||
mgr->hw->srcimp_mgr_put_ctrl_blk(mgr->ctrl_blk);
|
||||
break;
|
||||
case AMIXER:
|
||||
((struct hw *)mgr->hw)->
|
||||
amixer_mgr_put_ctrl_blk(mgr->ctrl_blk);
|
||||
mgr->hw->amixer_mgr_put_ctrl_blk(mgr->ctrl_blk);
|
||||
break;
|
||||
case DAIO:
|
||||
((struct hw *)mgr->hw)->
|
||||
daio_mgr_put_ctrl_blk(mgr->ctrl_blk);
|
||||
mgr->hw->daio_mgr_put_ctrl_blk(mgr->ctrl_blk);
|
||||
break;
|
||||
case SUM:
|
||||
break;
|
||||
default:
|
||||
printk(KERN_ERR "ctxfi: "
|
||||
"Invalid resource type value %d!\n", mgr->type);
|
||||
dev_err(((struct hw *)mgr->hw)->card->dev,
|
||||
"Invalid resource type value %d!\n",
|
||||
mgr->type);
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -38,7 +38,7 @@ struct rsc {
|
||||
u32 conj:12; /* Current conjugate index */
|
||||
u32 msr:4; /* The Master Sample Rate a resource working on */
|
||||
void *ctrl_blk; /* Chip specific control info block for a resource */
|
||||
void *hw; /* Chip specific object for hardware access means */
|
||||
struct hw *hw; /* Chip specific object for hardware access means */
|
||||
struct rsc_ops *ops; /* Generic resource operations */
|
||||
};
|
||||
|
||||
@ -50,7 +50,8 @@ struct rsc_ops {
|
||||
int (*output_slot)(const struct rsc *rsc);
|
||||
};
|
||||
|
||||
int rsc_init(struct rsc *rsc, u32 idx, enum RSCTYP type, u32 msr, void *hw);
|
||||
int
|
||||
rsc_init(struct rsc *rsc, u32 idx, enum RSCTYP type, u32 msr, struct hw *hw);
|
||||
int rsc_uninit(struct rsc *rsc);
|
||||
|
||||
struct rsc_mgr {
|
||||
@ -59,12 +60,12 @@ struct rsc_mgr {
|
||||
unsigned int avail; /* The amount of currently available resources */
|
||||
unsigned char *rscs; /* The bit-map for resource allocation */
|
||||
void *ctrl_blk; /* Chip specific control info block */
|
||||
void *hw; /* Chip specific object for hardware access */
|
||||
struct hw *hw; /* Chip specific object for hardware access */
|
||||
};
|
||||
|
||||
/* Resource management is based on bit-map mechanism */
|
||||
int rsc_mgr_init(struct rsc_mgr *mgr, enum RSCTYP type,
|
||||
unsigned int amount, void *hw);
|
||||
unsigned int amount, struct hw *hw);
|
||||
int rsc_mgr_uninit(struct rsc_mgr *mgr);
|
||||
int mgr_get_resource(struct rsc_mgr *mgr, unsigned int n, unsigned int *ridx);
|
||||
int mgr_put_resource(struct rsc_mgr *mgr, unsigned int n, unsigned int idx);
|
||||
|
@ -431,7 +431,8 @@ get_src_rsc(struct src_mgr *mgr, const struct src_desc *desc, struct src **rsrc)
|
||||
|
||||
spin_unlock_irqrestore(&mgr->mgr_lock, flags);
|
||||
if (err) {
|
||||
printk(KERN_ERR "ctxfi: Can't meet SRC resource request!\n");
|
||||
dev_err(mgr->card->dev,
|
||||
"Can't meet SRC resource request!\n");
|
||||
return err;
|
||||
}
|
||||
|
||||
@ -543,7 +544,7 @@ static int src_mgr_commit_write(struct src_mgr *mgr)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int src_mgr_create(void *hw, struct src_mgr **rsrc_mgr)
|
||||
int src_mgr_create(struct hw *hw, struct src_mgr **rsrc_mgr)
|
||||
{
|
||||
int err, i;
|
||||
struct src_mgr *src_mgr;
|
||||
@ -558,7 +559,7 @@ int src_mgr_create(void *hw, struct src_mgr **rsrc_mgr)
|
||||
goto error1;
|
||||
|
||||
spin_lock_init(&src_mgr->mgr_lock);
|
||||
conj_mask = ((struct hw *)hw)->src_dirty_conj_mask();
|
||||
conj_mask = hw->src_dirty_conj_mask();
|
||||
|
||||
src_mgr->get_src = get_src_rsc;
|
||||
src_mgr->put_src = put_src_rsc;
|
||||
@ -566,12 +567,13 @@ int src_mgr_create(void *hw, struct src_mgr **rsrc_mgr)
|
||||
src_mgr->src_enable = src_enable;
|
||||
src_mgr->src_disable = src_disable;
|
||||
src_mgr->commit_write = src_mgr_commit_write;
|
||||
src_mgr->card = hw->card;
|
||||
|
||||
/* Disable all SRC resources. */
|
||||
for (i = 0; i < 256; i++)
|
||||
((struct hw *)hw)->src_mgr_dsb_src(src_mgr->mgr.ctrl_blk, i);
|
||||
hw->src_mgr_dsb_src(src_mgr->mgr.ctrl_blk, i);
|
||||
|
||||
((struct hw *)hw)->src_mgr_commit_write(hw, src_mgr->mgr.ctrl_blk);
|
||||
hw->src_mgr_commit_write(hw, src_mgr->mgr.ctrl_blk);
|
||||
|
||||
*rsrc_mgr = src_mgr;
|
||||
|
||||
@ -739,7 +741,8 @@ static int get_srcimp_rsc(struct srcimp_mgr *mgr,
|
||||
}
|
||||
spin_unlock_irqrestore(&mgr->mgr_lock, flags);
|
||||
if (err) {
|
||||
printk(KERN_ERR "ctxfi: Can't meet SRCIMP resource request!\n");
|
||||
dev_err(mgr->card->dev,
|
||||
"Can't meet SRCIMP resource request!\n");
|
||||
goto error1;
|
||||
}
|
||||
|
||||
@ -825,7 +828,7 @@ static int srcimp_imap_delete(struct srcimp_mgr *mgr, struct imapper *entry)
|
||||
return err;
|
||||
}
|
||||
|
||||
int srcimp_mgr_create(void *hw, struct srcimp_mgr **rsrcimp_mgr)
|
||||
int srcimp_mgr_create(struct hw *hw, struct srcimp_mgr **rsrcimp_mgr)
|
||||
{
|
||||
int err;
|
||||
struct srcimp_mgr *srcimp_mgr;
|
||||
@ -857,6 +860,7 @@ int srcimp_mgr_create(void *hw, struct srcimp_mgr **rsrcimp_mgr)
|
||||
srcimp_mgr->put_srcimp = put_srcimp_rsc;
|
||||
srcimp_mgr->imap_add = srcimp_imap_add;
|
||||
srcimp_mgr->imap_delete = srcimp_imap_delete;
|
||||
srcimp_mgr->card = hw->card;
|
||||
|
||||
*rsrcimp_mgr = srcimp_mgr;
|
||||
|
||||
|
@ -23,6 +23,7 @@
|
||||
#include "ctimap.h"
|
||||
#include <linux/spinlock.h>
|
||||
#include <linux/list.h>
|
||||
#include <sound/core.h>
|
||||
|
||||
#define SRC_STATE_OFF 0x0
|
||||
#define SRC_STATE_INIT 0x4
|
||||
@ -85,6 +86,7 @@ struct src_desc {
|
||||
/* Define src manager object */
|
||||
struct src_mgr {
|
||||
struct rsc_mgr mgr; /* Basic resource manager info */
|
||||
struct snd_card *card; /* pointer to this card */
|
||||
spinlock_t mgr_lock;
|
||||
|
||||
/* request src resource */
|
||||
@ -123,6 +125,7 @@ struct srcimp_desc {
|
||||
|
||||
struct srcimp_mgr {
|
||||
struct rsc_mgr mgr; /* Basic resource manager info */
|
||||
struct snd_card *card; /* pointer to this card */
|
||||
spinlock_t mgr_lock;
|
||||
spinlock_t imap_lock;
|
||||
struct list_head imappers;
|
||||
@ -140,10 +143,10 @@ struct srcimp_mgr {
|
||||
};
|
||||
|
||||
/* Constructor and destructor of SRC resource manager */
|
||||
int src_mgr_create(void *hw, struct src_mgr **rsrc_mgr);
|
||||
int src_mgr_create(struct hw *hw, struct src_mgr **rsrc_mgr);
|
||||
int src_mgr_destroy(struct src_mgr *src_mgr);
|
||||
/* Constructor and destructor of SRCIMP resource manager */
|
||||
int srcimp_mgr_create(void *hw, struct srcimp_mgr **rsrc_mgr);
|
||||
int srcimp_mgr_create(struct hw *hw, struct srcimp_mgr **rsrc_mgr);
|
||||
int srcimp_mgr_destroy(struct srcimp_mgr *srcimp_mgr);
|
||||
|
||||
#endif /* CTSRC_H */
|
||||
|
@ -16,6 +16,7 @@
|
||||
*/
|
||||
|
||||
#include "ctvmem.h"
|
||||
#include "ctatc.h"
|
||||
#include <linux/slab.h>
|
||||
#include <linux/mm.h>
|
||||
#include <linux/io.h>
|
||||
@ -29,15 +30,15 @@
|
||||
* @size must be page aligned.
|
||||
* */
|
||||
static struct ct_vm_block *
|
||||
get_vm_block(struct ct_vm *vm, unsigned int size)
|
||||
get_vm_block(struct ct_vm *vm, unsigned int size, struct ct_atc *atc)
|
||||
{
|
||||
struct ct_vm_block *block = NULL, *entry;
|
||||
struct list_head *pos;
|
||||
|
||||
size = CT_PAGE_ALIGN(size);
|
||||
if (size > vm->size) {
|
||||
printk(KERN_ERR "ctxfi: Fail! No sufficient device virtual "
|
||||
"memory space available!\n");
|
||||
dev_err(atc->card->dev,
|
||||
"Fail! No sufficient device virtual memory space available!\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@ -129,11 +130,12 @@ ct_vm_map(struct ct_vm *vm, struct snd_pcm_substream *substream, int size)
|
||||
unsigned int pte_start;
|
||||
unsigned i, pages;
|
||||
unsigned long *ptp;
|
||||
struct ct_atc *atc = snd_pcm_substream_chip(substream);
|
||||
|
||||
block = get_vm_block(vm, size);
|
||||
block = get_vm_block(vm, size, atc);
|
||||
if (block == NULL) {
|
||||
printk(KERN_ERR "ctxfi: No virtual memory block that is big "
|
||||
"enough to allocate!\n");
|
||||
dev_err(atc->card->dev,
|
||||
"No virtual memory block that is big enough to allocate!\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
@ -76,17 +76,18 @@ ct_card_probe(struct pci_dev *pci, const struct pci_device_id *pci_id)
|
||||
if (err)
|
||||
return err;
|
||||
if ((reference_rate != 48000) && (reference_rate != 44100)) {
|
||||
printk(KERN_ERR "ctxfi: Invalid reference_rate value %u!!!\n",
|
||||
reference_rate);
|
||||
printk(KERN_ERR "ctxfi: The valid values for reference_rate "
|
||||
"are 48000 and 44100, Value 48000 is assumed.\n");
|
||||
dev_err(card->dev,
|
||||
"Invalid reference_rate value %u!!!\n",
|
||||
reference_rate);
|
||||
dev_err(card->dev,
|
||||
"The valid values for reference_rate are 48000 and 44100, Value 48000 is assumed.\n");
|
||||
reference_rate = 48000;
|
||||
}
|
||||
if ((multiple != 1) && (multiple != 2) && (multiple != 4)) {
|
||||
printk(KERN_ERR "ctxfi: Invalid multiple value %u!!!\n",
|
||||
multiple);
|
||||
printk(KERN_ERR "ctxfi: The valid values for multiple are "
|
||||
"1, 2 and 4, Value 2 is assumed.\n");
|
||||
dev_err(card->dev, "Invalid multiple value %u!!!\n",
|
||||
multiple);
|
||||
dev_err(card->dev,
|
||||
"The valid values for multiple are 1, 2 and 4, Value 2 is assumed.\n");
|
||||
multiple = 2;
|
||||
}
|
||||
err = ct_atc_create(card, pci, reference_rate, multiple,
|
||||
|
@ -57,12 +57,14 @@ static void sort_pins_by_sequence(hda_nid_t *pins, struct auto_out_pin *list,
|
||||
|
||||
|
||||
/* add the found input-pin to the cfg->inputs[] table */
|
||||
static void add_auto_cfg_input_pin(struct auto_pin_cfg *cfg, hda_nid_t nid,
|
||||
int type)
|
||||
static void add_auto_cfg_input_pin(struct hda_codec *codec, struct auto_pin_cfg *cfg,
|
||||
hda_nid_t nid, int type)
|
||||
{
|
||||
if (cfg->num_inputs < AUTO_CFG_MAX_INS) {
|
||||
cfg->inputs[cfg->num_inputs].pin = nid;
|
||||
cfg->inputs[cfg->num_inputs].type = type;
|
||||
cfg->inputs[cfg->num_inputs].has_boost_on_pin =
|
||||
nid_has_volume(codec, nid, HDA_INPUT);
|
||||
cfg->num_inputs++;
|
||||
}
|
||||
}
|
||||
@ -71,7 +73,12 @@ static int compare_input_type(const void *ap, const void *bp)
|
||||
{
|
||||
const struct auto_pin_cfg_item *a = ap;
|
||||
const struct auto_pin_cfg_item *b = bp;
|
||||
return (int)(a->type - b->type);
|
||||
if (a->type != b->type)
|
||||
return (int)(a->type - b->type);
|
||||
|
||||
/* In case one has boost and the other one has not,
|
||||
pick the one with boost first. */
|
||||
return (int)(b->has_boost_on_pin - a->has_boost_on_pin);
|
||||
}
|
||||
|
||||
/* Reorder the surround channels
|
||||
@ -268,16 +275,16 @@ int snd_hda_parse_pin_defcfg(struct hda_codec *codec,
|
||||
cfg->hp_outs++;
|
||||
break;
|
||||
case AC_JACK_MIC_IN:
|
||||
add_auto_cfg_input_pin(cfg, nid, AUTO_PIN_MIC);
|
||||
add_auto_cfg_input_pin(codec, cfg, nid, AUTO_PIN_MIC);
|
||||
break;
|
||||
case AC_JACK_LINE_IN:
|
||||
add_auto_cfg_input_pin(cfg, nid, AUTO_PIN_LINE_IN);
|
||||
add_auto_cfg_input_pin(codec, cfg, nid, AUTO_PIN_LINE_IN);
|
||||
break;
|
||||
case AC_JACK_CD:
|
||||
add_auto_cfg_input_pin(cfg, nid, AUTO_PIN_CD);
|
||||
add_auto_cfg_input_pin(codec, cfg, nid, AUTO_PIN_CD);
|
||||
break;
|
||||
case AC_JACK_AUX:
|
||||
add_auto_cfg_input_pin(cfg, nid, AUTO_PIN_AUX);
|
||||
add_auto_cfg_input_pin(codec, cfg, nid, AUTO_PIN_AUX);
|
||||
break;
|
||||
case AC_JACK_SPDIF_OUT:
|
||||
case AC_JACK_DIG_OTHER_OUT:
|
||||
|
@ -38,6 +38,7 @@ struct auto_pin_cfg_item {
|
||||
int type;
|
||||
unsigned int is_headset_mic:1;
|
||||
unsigned int is_headphone_mic:1; /* Mic-only in headphone jack */
|
||||
unsigned int has_boost_on_pin:1;
|
||||
};
|
||||
|
||||
struct auto_pin_cfg;
|
||||
|
@ -2001,6 +2001,26 @@ u32 query_amp_caps(struct hda_codec *codec, hda_nid_t nid, int direction)
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(query_amp_caps);
|
||||
|
||||
/**
|
||||
* snd_hda_check_amp_caps - query AMP capabilities
|
||||
* @codec: the HD-audio codec
|
||||
* @nid: the NID to query
|
||||
* @dir: either #HDA_INPUT or #HDA_OUTPUT
|
||||
*
|
||||
* Check whether the widget has the given amp capability for the direction.
|
||||
*/
|
||||
bool snd_hda_check_amp_caps(struct hda_codec *codec, hda_nid_t nid,
|
||||
int dir, unsigned int bits)
|
||||
{
|
||||
if (!nid)
|
||||
return false;
|
||||
if (get_wcaps(codec, nid) & (1 << (dir + 1)))
|
||||
if (query_amp_caps(codec, nid, dir) & bits)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(snd_hda_check_amp_caps);
|
||||
|
||||
/**
|
||||
* snd_hda_override_amp_caps - Override the AMP capabilities
|
||||
* @codec: the CODEC to clean up
|
||||
@ -4816,121 +4836,6 @@ int snd_hda_build_pcms(struct hda_bus *bus)
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(snd_hda_build_pcms);
|
||||
|
||||
/**
|
||||
* snd_hda_check_board_config - compare the current codec with the config table
|
||||
* @codec: the HDA codec
|
||||
* @num_configs: number of config enums
|
||||
* @models: array of model name strings
|
||||
* @tbl: configuration table, terminated by null entries
|
||||
*
|
||||
* Compares the modelname or PCI subsystem id of the current codec with the
|
||||
* given configuration table. If a matching entry is found, returns its
|
||||
* config value (supposed to be 0 or positive).
|
||||
*
|
||||
* If no entries are matching, the function returns a negative value.
|
||||
*/
|
||||
int snd_hda_check_board_config(struct hda_codec *codec,
|
||||
int num_configs, const char * const *models,
|
||||
const struct snd_pci_quirk *tbl)
|
||||
{
|
||||
if (codec->modelname && models) {
|
||||
int i;
|
||||
for (i = 0; i < num_configs; i++) {
|
||||
if (models[i] &&
|
||||
!strcmp(codec->modelname, models[i])) {
|
||||
codec_info(codec, "model '%s' is selected\n",
|
||||
models[i]);
|
||||
return i;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!codec->bus->pci || !tbl)
|
||||
return -1;
|
||||
|
||||
tbl = snd_pci_quirk_lookup(codec->bus->pci, tbl);
|
||||
if (!tbl)
|
||||
return -1;
|
||||
if (tbl->value >= 0 && tbl->value < num_configs) {
|
||||
#ifdef CONFIG_SND_DEBUG_VERBOSE
|
||||
char tmp[10];
|
||||
const char *model = NULL;
|
||||
if (models)
|
||||
model = models[tbl->value];
|
||||
if (!model) {
|
||||
sprintf(tmp, "#%d", tbl->value);
|
||||
model = tmp;
|
||||
}
|
||||
codec_info(codec, "model '%s' is selected for config %x:%x (%s)\n",
|
||||
model, tbl->subvendor, tbl->subdevice,
|
||||
(tbl->name ? tbl->name : "Unknown device"));
|
||||
#endif
|
||||
return tbl->value;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(snd_hda_check_board_config);
|
||||
|
||||
/**
|
||||
* snd_hda_check_board_codec_sid_config - compare the current codec
|
||||
subsystem ID with the
|
||||
config table
|
||||
|
||||
This is important for Gateway notebooks with SB450 HDA Audio
|
||||
where the vendor ID of the PCI device is:
|
||||
ATI Technologies Inc SB450 HDA Audio [1002:437b]
|
||||
and the vendor/subvendor are found only at the codec.
|
||||
|
||||
* @codec: the HDA codec
|
||||
* @num_configs: number of config enums
|
||||
* @models: array of model name strings
|
||||
* @tbl: configuration table, terminated by null entries
|
||||
*
|
||||
* Compares the modelname or PCI subsystem id of the current codec with the
|
||||
* given configuration table. If a matching entry is found, returns its
|
||||
* config value (supposed to be 0 or positive).
|
||||
*
|
||||
* If no entries are matching, the function returns a negative value.
|
||||
*/
|
||||
int snd_hda_check_board_codec_sid_config(struct hda_codec *codec,
|
||||
int num_configs, const char * const *models,
|
||||
const struct snd_pci_quirk *tbl)
|
||||
{
|
||||
const struct snd_pci_quirk *q;
|
||||
|
||||
/* Search for codec ID */
|
||||
for (q = tbl; q->subvendor; q++) {
|
||||
unsigned int mask = 0xffff0000 | q->subdevice_mask;
|
||||
unsigned int id = (q->subdevice | (q->subvendor << 16)) & mask;
|
||||
if ((codec->subsystem_id & mask) == id)
|
||||
break;
|
||||
}
|
||||
|
||||
if (!q->subvendor)
|
||||
return -1;
|
||||
|
||||
tbl = q;
|
||||
|
||||
if (tbl->value >= 0 && tbl->value < num_configs) {
|
||||
#ifdef CONFIG_SND_DEBUG_VERBOSE
|
||||
char tmp[10];
|
||||
const char *model = NULL;
|
||||
if (models)
|
||||
model = models[tbl->value];
|
||||
if (!model) {
|
||||
sprintf(tmp, "#%d", tbl->value);
|
||||
model = tmp;
|
||||
}
|
||||
codec_info(codec, "model '%s' is selected for config %x:%x (%s)\n",
|
||||
model, tbl->subvendor, tbl->subdevice,
|
||||
(tbl->name ? tbl->name : "Unknown device"));
|
||||
#endif
|
||||
return tbl->value;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(snd_hda_check_board_codec_sid_config);
|
||||
|
||||
/**
|
||||
* snd_hda_add_new_ctls - create controls from the array
|
||||
* @codec: the HDA codec
|
||||
|
@ -687,6 +687,4 @@ snd_hda_codec_load_dsp_cleanup(struct hda_codec *codec,
|
||||
struct snd_dma_buffer *dmab) {}
|
||||
#endif
|
||||
|
||||
#define EXPORT_SYMBOL_HDA(sym) EXPORT_SYMBOL_GPL(sym)
|
||||
|
||||
#endif /* __SOUND_HDA_CODEC_H */
|
||||
|
@ -31,6 +31,7 @@
|
||||
#include <linux/module.h>
|
||||
#include <sound/core.h>
|
||||
#include <sound/jack.h>
|
||||
#include <sound/tlv.h>
|
||||
#include "hda_codec.h"
|
||||
#include "hda_local.h"
|
||||
#include "hda_auto_parser.h"
|
||||
@ -518,18 +519,6 @@ static unsigned int amp_val_replace_channels(unsigned int val, unsigned int chs)
|
||||
return val;
|
||||
}
|
||||
|
||||
/* check whether the widget has the given amp capability for the direction */
|
||||
static bool check_amp_caps(struct hda_codec *codec, hda_nid_t nid,
|
||||
int dir, unsigned int bits)
|
||||
{
|
||||
if (!nid)
|
||||
return false;
|
||||
if (get_wcaps(codec, nid) & (1 << (dir + 1)))
|
||||
if (query_amp_caps(codec, nid, dir) & bits)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool same_amp_caps(struct hda_codec *codec, hda_nid_t nid1,
|
||||
hda_nid_t nid2, int dir)
|
||||
{
|
||||
@ -539,11 +528,6 @@ static bool same_amp_caps(struct hda_codec *codec, hda_nid_t nid1,
|
||||
query_amp_caps(codec, nid2, dir));
|
||||
}
|
||||
|
||||
#define nid_has_mute(codec, nid, dir) \
|
||||
check_amp_caps(codec, nid, dir, (AC_AMPCAP_MUTE | AC_AMPCAP_MIN_MUTE))
|
||||
#define nid_has_volume(codec, nid, dir) \
|
||||
check_amp_caps(codec, nid, dir, AC_AMPCAP_NUM_STEPS)
|
||||
|
||||
/* look for a widget suitable for assigning a mute switch in the path */
|
||||
static hda_nid_t look_for_out_mute_nid(struct hda_codec *codec,
|
||||
struct nid_path *path)
|
||||
@ -1105,6 +1089,7 @@ enum {
|
||||
*/
|
||||
static int assign_out_path_ctls(struct hda_codec *codec, struct nid_path *path)
|
||||
{
|
||||
struct hda_gen_spec *spec = codec->spec;
|
||||
hda_nid_t nid;
|
||||
unsigned int val;
|
||||
int badness = 0;
|
||||
@ -1119,6 +1104,8 @@ static int assign_out_path_ctls(struct hda_codec *codec, struct nid_path *path)
|
||||
nid = look_for_out_vol_nid(codec, path);
|
||||
if (nid) {
|
||||
val = HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT);
|
||||
if (spec->dac_min_mute)
|
||||
val |= HDA_AMP_VAL_MIN_MUTE;
|
||||
if (is_ctl_used(codec, val, NID_PATH_VOL_CTL))
|
||||
badness += BAD_SHARED_VOL;
|
||||
else
|
||||
@ -1880,9 +1867,12 @@ static int parse_output_paths(struct hda_codec *codec)
|
||||
path = snd_hda_get_path_from_idx(codec, spec->out_paths[0]);
|
||||
if (path)
|
||||
spec->vmaster_nid = look_for_out_vol_nid(codec, path);
|
||||
if (spec->vmaster_nid)
|
||||
if (spec->vmaster_nid) {
|
||||
snd_hda_set_vmaster_tlv(codec, spec->vmaster_nid,
|
||||
HDA_OUTPUT, spec->vmaster_tlv);
|
||||
if (spec->dac_min_mute)
|
||||
spec->vmaster_tlv[3] |= TLV_DB_SCALE_MUTE;
|
||||
}
|
||||
}
|
||||
|
||||
/* set initial pinctl targets */
|
||||
@ -2025,7 +2015,8 @@ static int create_speaker_out_ctls(struct hda_codec *codec)
|
||||
* independent HP controls
|
||||
*/
|
||||
|
||||
static void call_hp_automute(struct hda_codec *codec, struct hda_jack_tbl *jack);
|
||||
static void call_hp_automute(struct hda_codec *codec,
|
||||
struct hda_jack_callback *jack);
|
||||
static int indep_hp_info(struct snd_kcontrol *kcontrol,
|
||||
struct snd_ctl_elem_info *uinfo)
|
||||
{
|
||||
@ -3941,7 +3932,8 @@ static void call_update_outputs(struct hda_codec *codec)
|
||||
}
|
||||
|
||||
/* standard HP-automute helper */
|
||||
void snd_hda_gen_hp_automute(struct hda_codec *codec, struct hda_jack_tbl *jack)
|
||||
void snd_hda_gen_hp_automute(struct hda_codec *codec,
|
||||
struct hda_jack_callback *jack)
|
||||
{
|
||||
struct hda_gen_spec *spec = codec->spec;
|
||||
hda_nid_t *pins = spec->autocfg.hp_pins;
|
||||
@ -3961,7 +3953,8 @@ void snd_hda_gen_hp_automute(struct hda_codec *codec, struct hda_jack_tbl *jack)
|
||||
EXPORT_SYMBOL_GPL(snd_hda_gen_hp_automute);
|
||||
|
||||
/* standard line-out-automute helper */
|
||||
void snd_hda_gen_line_automute(struct hda_codec *codec, struct hda_jack_tbl *jack)
|
||||
void snd_hda_gen_line_automute(struct hda_codec *codec,
|
||||
struct hda_jack_callback *jack)
|
||||
{
|
||||
struct hda_gen_spec *spec = codec->spec;
|
||||
|
||||
@ -3981,7 +3974,8 @@ void snd_hda_gen_line_automute(struct hda_codec *codec, struct hda_jack_tbl *jac
|
||||
EXPORT_SYMBOL_GPL(snd_hda_gen_line_automute);
|
||||
|
||||
/* standard mic auto-switch helper */
|
||||
void snd_hda_gen_mic_autoswitch(struct hda_codec *codec, struct hda_jack_tbl *jack)
|
||||
void snd_hda_gen_mic_autoswitch(struct hda_codec *codec,
|
||||
struct hda_jack_callback *jack)
|
||||
{
|
||||
struct hda_gen_spec *spec = codec->spec;
|
||||
int i;
|
||||
@ -4004,7 +3998,8 @@ void snd_hda_gen_mic_autoswitch(struct hda_codec *codec, struct hda_jack_tbl *ja
|
||||
EXPORT_SYMBOL_GPL(snd_hda_gen_mic_autoswitch);
|
||||
|
||||
/* call appropriate hooks */
|
||||
static void call_hp_automute(struct hda_codec *codec, struct hda_jack_tbl *jack)
|
||||
static void call_hp_automute(struct hda_codec *codec,
|
||||
struct hda_jack_callback *jack)
|
||||
{
|
||||
struct hda_gen_spec *spec = codec->spec;
|
||||
if (spec->hp_automute_hook)
|
||||
@ -4014,7 +4009,7 @@ static void call_hp_automute(struct hda_codec *codec, struct hda_jack_tbl *jack)
|
||||
}
|
||||
|
||||
static void call_line_automute(struct hda_codec *codec,
|
||||
struct hda_jack_tbl *jack)
|
||||
struct hda_jack_callback *jack)
|
||||
{
|
||||
struct hda_gen_spec *spec = codec->spec;
|
||||
if (spec->line_automute_hook)
|
||||
@ -4024,7 +4019,7 @@ static void call_line_automute(struct hda_codec *codec,
|
||||
}
|
||||
|
||||
static void call_mic_autoswitch(struct hda_codec *codec,
|
||||
struct hda_jack_tbl *jack)
|
||||
struct hda_jack_callback *jack)
|
||||
{
|
||||
struct hda_gen_spec *spec = codec->spec;
|
||||
if (spec->mic_autoswitch_hook)
|
||||
@ -4173,7 +4168,7 @@ static int check_auto_mute_availability(struct hda_codec *codec)
|
||||
if (!is_jack_detectable(codec, nid))
|
||||
continue;
|
||||
codec_dbg(codec, "Enable HP auto-muting on NID 0x%x\n", nid);
|
||||
snd_hda_jack_detect_enable_callback(codec, nid, HDA_GEN_HP_EVENT,
|
||||
snd_hda_jack_detect_enable_callback(codec, nid,
|
||||
call_hp_automute);
|
||||
spec->detect_hp = 1;
|
||||
}
|
||||
@ -4186,7 +4181,6 @@ static int check_auto_mute_availability(struct hda_codec *codec)
|
||||
continue;
|
||||
codec_dbg(codec, "Enable Line-Out auto-muting on NID 0x%x\n", nid);
|
||||
snd_hda_jack_detect_enable_callback(codec, nid,
|
||||
HDA_GEN_FRONT_EVENT,
|
||||
call_line_automute);
|
||||
spec->detect_lo = 1;
|
||||
}
|
||||
@ -4228,7 +4222,6 @@ static bool auto_mic_check_imux(struct hda_codec *codec)
|
||||
for (i = 1; i < spec->am_num_entries; i++)
|
||||
snd_hda_jack_detect_enable_callback(codec,
|
||||
spec->am_entry[i].pin,
|
||||
HDA_GEN_MIC_EVENT,
|
||||
call_mic_autoswitch);
|
||||
return true;
|
||||
}
|
||||
|
@ -12,12 +12,6 @@
|
||||
#ifndef __SOUND_HDA_GENERIC_H
|
||||
#define __SOUND_HDA_GENERIC_H
|
||||
|
||||
/* unsol event tags */
|
||||
enum {
|
||||
HDA_GEN_HP_EVENT = 1, HDA_GEN_FRONT_EVENT, HDA_GEN_MIC_EVENT,
|
||||
HDA_GEN_LAST_EVENT = HDA_GEN_MIC_EVENT
|
||||
};
|
||||
|
||||
/* table entry for multi-io paths */
|
||||
struct hda_multi_io {
|
||||
hda_nid_t pin; /* multi-io widget pin NID */
|
||||
@ -231,6 +225,7 @@ struct hda_gen_spec {
|
||||
unsigned int add_stereo_mix_input:1; /* add aamix as a capture src */
|
||||
unsigned int add_jack_modes:1; /* add i/o jack mode enum ctls */
|
||||
unsigned int power_down_unused:1; /* power down unused widgets */
|
||||
unsigned int dac_min_mute:1; /* minimal = mute for DACs */
|
||||
|
||||
/* other internal flags */
|
||||
unsigned int no_analog:1; /* digital I/O only */
|
||||
@ -289,11 +284,11 @@ struct hda_gen_spec {
|
||||
|
||||
/* automute / autoswitch hooks */
|
||||
void (*hp_automute_hook)(struct hda_codec *codec,
|
||||
struct hda_jack_tbl *tbl);
|
||||
struct hda_jack_callback *cb);
|
||||
void (*line_automute_hook)(struct hda_codec *codec,
|
||||
struct hda_jack_tbl *tbl);
|
||||
struct hda_jack_callback *cb);
|
||||
void (*mic_autoswitch_hook)(struct hda_codec *codec,
|
||||
struct hda_jack_tbl *tbl);
|
||||
struct hda_jack_callback *cb);
|
||||
};
|
||||
|
||||
int snd_hda_gen_spec_init(struct hda_gen_spec *spec);
|
||||
@ -325,11 +320,11 @@ int snd_hda_gen_build_pcms(struct hda_codec *codec);
|
||||
|
||||
/* standard jack event callbacks */
|
||||
void snd_hda_gen_hp_automute(struct hda_codec *codec,
|
||||
struct hda_jack_tbl *jack);
|
||||
struct hda_jack_callback *jack);
|
||||
void snd_hda_gen_line_automute(struct hda_codec *codec,
|
||||
struct hda_jack_tbl *jack);
|
||||
struct hda_jack_callback *jack);
|
||||
void snd_hda_gen_mic_autoswitch(struct hda_codec *codec,
|
||||
struct hda_jack_tbl *jack);
|
||||
struct hda_jack_callback *jack);
|
||||
void snd_hda_gen_update_outputs(struct hda_codec *codec);
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
|
@ -94,7 +94,7 @@ EXPORT_SYMBOL_GPL(snd_hda_jack_tbl_get_from_tag);
|
||||
/**
|
||||
* snd_hda_jack_tbl_new - create a jack-table entry for the given NID
|
||||
*/
|
||||
struct hda_jack_tbl *
|
||||
static struct hda_jack_tbl *
|
||||
snd_hda_jack_tbl_new(struct hda_codec *codec, hda_nid_t nid)
|
||||
{
|
||||
struct hda_jack_tbl *jack = snd_hda_jack_tbl_get(codec, nid);
|
||||
@ -108,21 +108,24 @@ snd_hda_jack_tbl_new(struct hda_codec *codec, hda_nid_t nid)
|
||||
jack->tag = codec->jacktbl.used;
|
||||
return jack;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(snd_hda_jack_tbl_new);
|
||||
|
||||
void snd_hda_jack_tbl_clear(struct hda_codec *codec)
|
||||
{
|
||||
struct hda_jack_tbl *jack = codec->jacktbl.list;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < codec->jacktbl.used; i++, jack++) {
|
||||
struct hda_jack_callback *cb, *next;
|
||||
#ifdef CONFIG_SND_HDA_INPUT_JACK
|
||||
/* free jack instances manually when clearing/reconfiguring */
|
||||
if (!codec->bus->shutdown && codec->jacktbl.list) {
|
||||
struct hda_jack_tbl *jack = codec->jacktbl.list;
|
||||
int i;
|
||||
for (i = 0; i < codec->jacktbl.used; i++, jack++) {
|
||||
if (jack->jack)
|
||||
snd_device_free(codec->bus->card, jack->jack);
|
||||
/* free jack instances manually when clearing/reconfiguring */
|
||||
if (!codec->bus->shutdown && jack->jack)
|
||||
snd_device_free(codec->bus->card, jack->jack);
|
||||
#endif
|
||||
for (cb = jack->callback; cb; cb = next) {
|
||||
next = cb->next;
|
||||
kfree(cb);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
snd_array_free(&codec->jacktbl);
|
||||
}
|
||||
|
||||
@ -215,33 +218,49 @@ EXPORT_SYMBOL_GPL(snd_hda_jack_detect_state);
|
||||
|
||||
/**
|
||||
* snd_hda_jack_detect_enable - enable the jack-detection
|
||||
*
|
||||
* In the case of error, the return value will be a pointer embedded with
|
||||
* errno. Check and handle the return value appropriately with standard
|
||||
* macros such as @IS_ERR() and @PTR_ERR().
|
||||
*/
|
||||
int snd_hda_jack_detect_enable_callback(struct hda_codec *codec, hda_nid_t nid,
|
||||
unsigned char action,
|
||||
hda_jack_callback cb)
|
||||
struct hda_jack_callback *
|
||||
snd_hda_jack_detect_enable_callback(struct hda_codec *codec, hda_nid_t nid,
|
||||
hda_jack_callback_fn func)
|
||||
{
|
||||
struct hda_jack_tbl *jack = snd_hda_jack_tbl_new(codec, nid);
|
||||
struct hda_jack_tbl *jack;
|
||||
struct hda_jack_callback *callback = NULL;
|
||||
int err;
|
||||
|
||||
jack = snd_hda_jack_tbl_new(codec, nid);
|
||||
if (!jack)
|
||||
return -ENOMEM;
|
||||
return ERR_PTR(-ENOMEM);
|
||||
if (func) {
|
||||
callback = kzalloc(sizeof(*callback), GFP_KERNEL);
|
||||
if (!callback)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
callback->func = func;
|
||||
callback->tbl = jack;
|
||||
callback->next = jack->callback;
|
||||
jack->callback = callback;
|
||||
}
|
||||
|
||||
if (jack->jack_detect)
|
||||
return 0; /* already registered */
|
||||
return callback; /* already registered */
|
||||
jack->jack_detect = 1;
|
||||
if (action)
|
||||
jack->action = action;
|
||||
if (cb)
|
||||
jack->callback = cb;
|
||||
if (codec->jackpoll_interval > 0)
|
||||
return 0; /* No unsol if we're polling instead */
|
||||
return snd_hda_codec_write_cache(codec, nid, 0,
|
||||
return callback; /* No unsol if we're polling instead */
|
||||
err = snd_hda_codec_write_cache(codec, nid, 0,
|
||||
AC_VERB_SET_UNSOLICITED_ENABLE,
|
||||
AC_USRSP_EN | jack->tag);
|
||||
if (err < 0)
|
||||
return ERR_PTR(err);
|
||||
return callback;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(snd_hda_jack_detect_enable_callback);
|
||||
|
||||
int snd_hda_jack_detect_enable(struct hda_codec *codec, hda_nid_t nid,
|
||||
unsigned char action)
|
||||
int snd_hda_jack_detect_enable(struct hda_codec *codec, hda_nid_t nid)
|
||||
{
|
||||
return snd_hda_jack_detect_enable_callback(codec, nid, action, NULL);
|
||||
return PTR_ERR_OR_ZERO(snd_hda_jack_detect_enable_callback(codec, nid, NULL));
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(snd_hda_jack_detect_enable);
|
||||
|
||||
@ -431,7 +450,7 @@ static int add_jack_kctl(struct hda_codec *codec, hda_nid_t nid,
|
||||
return err;
|
||||
|
||||
if (!phantom_jack)
|
||||
return snd_hda_jack_detect_enable(codec, nid, 0);
|
||||
return snd_hda_jack_detect_enable(codec, nid);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -498,13 +517,17 @@ EXPORT_SYMBOL_GPL(snd_hda_jack_add_kctls);
|
||||
static void call_jack_callback(struct hda_codec *codec,
|
||||
struct hda_jack_tbl *jack)
|
||||
{
|
||||
if (jack->callback)
|
||||
jack->callback(codec, jack);
|
||||
struct hda_jack_callback *cb;
|
||||
|
||||
for (cb = jack->callback; cb; cb = cb->next)
|
||||
cb->func(codec, cb);
|
||||
if (jack->gated_jack) {
|
||||
struct hda_jack_tbl *gated =
|
||||
snd_hda_jack_tbl_get(codec, jack->gated_jack);
|
||||
if (gated && gated->callback)
|
||||
gated->callback(codec, gated);
|
||||
if (gated) {
|
||||
for (cb = gated->callback; cb; cb = cb->next)
|
||||
cb->func(codec, cb);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -12,17 +12,25 @@
|
||||
#ifndef __SOUND_HDA_JACK_H
|
||||
#define __SOUND_HDA_JACK_H
|
||||
|
||||
#include <linux/err.h>
|
||||
|
||||
struct auto_pin_cfg;
|
||||
struct hda_jack_tbl;
|
||||
struct hda_jack_callback;
|
||||
|
||||
typedef void (*hda_jack_callback) (struct hda_codec *, struct hda_jack_tbl *);
|
||||
typedef void (*hda_jack_callback_fn) (struct hda_codec *, struct hda_jack_callback *);
|
||||
|
||||
struct hda_jack_callback {
|
||||
struct hda_jack_tbl *tbl;
|
||||
hda_jack_callback_fn func;
|
||||
unsigned int private_data; /* arbitrary data */
|
||||
struct hda_jack_callback *next;
|
||||
};
|
||||
|
||||
struct hda_jack_tbl {
|
||||
hda_nid_t nid;
|
||||
unsigned char action; /* event action (0 = none) */
|
||||
unsigned char tag; /* unsol event tag */
|
||||
unsigned int private_data; /* arbitrary data */
|
||||
hda_jack_callback callback;
|
||||
struct hda_jack_callback *callback;
|
||||
/* jack-detection stuff */
|
||||
unsigned int pin_sense; /* cached pin-sense value */
|
||||
unsigned int jack_detect:1; /* capable of jack-detection? */
|
||||
@ -43,34 +51,14 @@ snd_hda_jack_tbl_get(struct hda_codec *codec, hda_nid_t nid);
|
||||
struct hda_jack_tbl *
|
||||
snd_hda_jack_tbl_get_from_tag(struct hda_codec *codec, unsigned char tag);
|
||||
|
||||
struct hda_jack_tbl *
|
||||
snd_hda_jack_tbl_new(struct hda_codec *codec, hda_nid_t nid);
|
||||
void snd_hda_jack_tbl_clear(struct hda_codec *codec);
|
||||
|
||||
/**
|
||||
* snd_hda_jack_get_action - get jack-tbl entry for the tag
|
||||
*
|
||||
* Call this from the unsol event handler to get the assigned action for the
|
||||
* event. This will mark the dirty flag for the later reporting, too.
|
||||
*/
|
||||
static inline unsigned char
|
||||
snd_hda_jack_get_action(struct hda_codec *codec, unsigned int tag)
|
||||
{
|
||||
struct hda_jack_tbl *jack = snd_hda_jack_tbl_get_from_tag(codec, tag);
|
||||
if (jack) {
|
||||
jack->jack_dirty = 1;
|
||||
return jack->action;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void snd_hda_jack_set_dirty_all(struct hda_codec *codec);
|
||||
|
||||
int snd_hda_jack_detect_enable(struct hda_codec *codec, hda_nid_t nid,
|
||||
unsigned char action);
|
||||
int snd_hda_jack_detect_enable_callback(struct hda_codec *codec, hda_nid_t nid,
|
||||
unsigned char action,
|
||||
hda_jack_callback cb);
|
||||
int snd_hda_jack_detect_enable(struct hda_codec *codec, hda_nid_t nid);
|
||||
struct hda_jack_callback *
|
||||
snd_hda_jack_detect_enable_callback(struct hda_codec *codec, hda_nid_t nid,
|
||||
hda_jack_callback_fn cb);
|
||||
|
||||
int snd_hda_jack_set_gating_jack(struct hda_codec *codec, hda_nid_t gated_nid,
|
||||
hda_nid_t gating_nid);
|
||||
|
@ -371,12 +371,6 @@ void snd_print_pcm_bits(int pcm, char *buf, int buflen);
|
||||
/*
|
||||
* Misc
|
||||
*/
|
||||
int snd_hda_check_board_config(struct hda_codec *codec, int num_configs,
|
||||
const char * const *modelnames,
|
||||
const struct snd_pci_quirk *pci_list);
|
||||
int snd_hda_check_board_codec_sid_config(struct hda_codec *codec,
|
||||
int num_configs, const char * const *models,
|
||||
const struct snd_pci_quirk *tbl);
|
||||
int snd_hda_add_new_ctls(struct hda_codec *codec,
|
||||
const struct snd_kcontrol_new *knew);
|
||||
|
||||
@ -609,6 +603,14 @@ int snd_hda_override_amp_caps(struct hda_codec *codec, hda_nid_t nid, int dir,
|
||||
u32 snd_hda_query_pin_caps(struct hda_codec *codec, hda_nid_t nid);
|
||||
int snd_hda_override_pin_caps(struct hda_codec *codec, hda_nid_t nid,
|
||||
unsigned int caps);
|
||||
bool snd_hda_check_amp_caps(struct hda_codec *codec, hda_nid_t nid,
|
||||
int dir, unsigned int bits);
|
||||
|
||||
#define nid_has_mute(codec, nid, dir) \
|
||||
snd_hda_check_amp_caps(codec, nid, dir, (AC_AMPCAP_MUTE | AC_AMPCAP_MIN_MUTE))
|
||||
#define nid_has_volume(codec, nid, dir) \
|
||||
snd_hda_check_amp_caps(codec, nid, dir, AC_AMPCAP_NUM_STEPS)
|
||||
|
||||
|
||||
/* flags for hda_nid_item */
|
||||
#define HDA_NID_ITEM_AMP (1<<0)
|
||||
|
@ -514,7 +514,7 @@ enum {
|
||||
|
||||
static inline int strmatch(const char *a, const char *b)
|
||||
{
|
||||
return strnicmp(a, b, strlen(b)) == 0;
|
||||
return strncasecmp(a, b, strlen(b)) == 0;
|
||||
}
|
||||
|
||||
/* parse the contents after the line "[codec]"
|
||||
|
@ -3224,8 +3224,14 @@ static void ca0132_unsol_hp_delayed(struct work_struct *work)
|
||||
{
|
||||
struct ca0132_spec *spec = container_of(
|
||||
to_delayed_work(work), struct ca0132_spec, unsol_hp_work);
|
||||
struct hda_jack_tbl *jack;
|
||||
|
||||
ca0132_select_out(spec->codec);
|
||||
snd_hda_jack_report_sync(spec->codec);
|
||||
jack = snd_hda_jack_tbl_get(spec->codec, UNSOL_TAG_HP);
|
||||
if (jack) {
|
||||
jack->block_report = 0;
|
||||
snd_hda_jack_report_sync(spec->codec);
|
||||
}
|
||||
}
|
||||
|
||||
static void ca0132_set_dmic(struct hda_codec *codec, int enable);
|
||||
@ -4114,12 +4120,6 @@ static void init_input(struct hda_codec *codec, hda_nid_t pin, hda_nid_t adc)
|
||||
}
|
||||
}
|
||||
|
||||
static void ca0132_init_unsol(struct hda_codec *codec)
|
||||
{
|
||||
snd_hda_jack_detect_enable(codec, UNSOL_TAG_HP, UNSOL_TAG_HP);
|
||||
snd_hda_jack_detect_enable(codec, UNSOL_TAG_AMIC1, UNSOL_TAG_AMIC1);
|
||||
}
|
||||
|
||||
static void refresh_amp_caps(struct hda_codec *codec, hda_nid_t nid, int dir)
|
||||
{
|
||||
unsigned int caps;
|
||||
@ -4390,7 +4390,8 @@ static void ca0132_download_dsp(struct hda_codec *codec)
|
||||
ca0132_set_dsp_msr(codec, true);
|
||||
}
|
||||
|
||||
static void ca0132_process_dsp_response(struct hda_codec *codec)
|
||||
static void ca0132_process_dsp_response(struct hda_codec *codec,
|
||||
struct hda_jack_callback *callback)
|
||||
{
|
||||
struct ca0132_spec *spec = codec->spec;
|
||||
|
||||
@ -4403,36 +4404,31 @@ static void ca0132_process_dsp_response(struct hda_codec *codec)
|
||||
dspio_clear_response_queue(codec);
|
||||
}
|
||||
|
||||
static void ca0132_unsol_event(struct hda_codec *codec, unsigned int res)
|
||||
static void hp_callback(struct hda_codec *codec, struct hda_jack_callback *cb)
|
||||
{
|
||||
struct ca0132_spec *spec = codec->spec;
|
||||
|
||||
if (((res >> AC_UNSOL_RES_TAG_SHIFT) & 0x3f) == UNSOL_TAG_DSP) {
|
||||
ca0132_process_dsp_response(codec);
|
||||
} else {
|
||||
res = snd_hda_jack_get_action(codec,
|
||||
(res >> AC_UNSOL_RES_TAG_SHIFT) & 0x3f);
|
||||
/* Delay enabling the HP amp, to let the mic-detection
|
||||
* state machine run.
|
||||
*/
|
||||
cancel_delayed_work_sync(&spec->unsol_hp_work);
|
||||
queue_delayed_work(codec->bus->workq, &spec->unsol_hp_work,
|
||||
msecs_to_jiffies(500));
|
||||
cb->tbl->block_report = 1;
|
||||
}
|
||||
|
||||
codec_dbg(codec, "snd_hda_jack_get_action: 0x%x\n", res);
|
||||
static void amic_callback(struct hda_codec *codec, struct hda_jack_callback *cb)
|
||||
{
|
||||
ca0132_select_mic(codec);
|
||||
}
|
||||
|
||||
switch (res) {
|
||||
case UNSOL_TAG_HP:
|
||||
/* Delay enabling the HP amp, to let the mic-detection
|
||||
* state machine run.
|
||||
*/
|
||||
cancel_delayed_work_sync(&spec->unsol_hp_work);
|
||||
queue_delayed_work(codec->bus->workq,
|
||||
&spec->unsol_hp_work,
|
||||
msecs_to_jiffies(500));
|
||||
break;
|
||||
case UNSOL_TAG_AMIC1:
|
||||
ca0132_select_mic(codec);
|
||||
snd_hda_jack_report_sync(codec);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
static void ca0132_init_unsol(struct hda_codec *codec)
|
||||
{
|
||||
snd_hda_jack_detect_enable_callback(codec, UNSOL_TAG_HP, hp_callback);
|
||||
snd_hda_jack_detect_enable_callback(codec, UNSOL_TAG_AMIC1,
|
||||
amic_callback);
|
||||
snd_hda_jack_detect_enable_callback(codec, UNSOL_TAG_DSP,
|
||||
ca0132_process_dsp_response);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -4443,8 +4439,6 @@ static void ca0132_unsol_event(struct hda_codec *codec, unsigned int res)
|
||||
static struct hda_verb ca0132_base_init_verbs[] = {
|
||||
/*enable ct extension*/
|
||||
{0x15, VENDOR_CHIPIO_CT_EXTENSIONS_ENABLE, 0x1},
|
||||
/*enable DSP node unsol, needed for DSP download*/
|
||||
{0x16, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | UNSOL_TAG_DSP},
|
||||
{}
|
||||
};
|
||||
|
||||
@ -4561,6 +4555,8 @@ static int ca0132_init(struct hda_codec *codec)
|
||||
|
||||
snd_hda_power_up(codec);
|
||||
|
||||
ca0132_init_unsol(codec);
|
||||
|
||||
ca0132_init_params(codec);
|
||||
ca0132_init_flags(codec);
|
||||
snd_hda_sequence_write(codec, spec->base_init_verbs);
|
||||
@ -4583,8 +4579,6 @@ static int ca0132_init(struct hda_codec *codec)
|
||||
for (i = 0; i < spec->num_init_verbs; i++)
|
||||
snd_hda_sequence_write(codec, spec->init_verbs[i]);
|
||||
|
||||
ca0132_init_unsol(codec);
|
||||
|
||||
ca0132_select_out(codec);
|
||||
ca0132_select_mic(codec);
|
||||
|
||||
@ -4612,7 +4606,7 @@ static struct hda_codec_ops ca0132_patch_ops = {
|
||||
.build_pcms = ca0132_build_pcms,
|
||||
.init = ca0132_init,
|
||||
.free = ca0132_free,
|
||||
.unsol_event = ca0132_unsol_event,
|
||||
.unsol_event = snd_hda_jack_unsol_event,
|
||||
};
|
||||
|
||||
static void ca0132_config(struct hda_codec *codec)
|
||||
|
@ -135,8 +135,6 @@ enum {
|
||||
#define CS421X_IDX_DAC_CFG 0x03
|
||||
#define CS421X_IDX_SPK_CTL 0x04
|
||||
|
||||
#define SPDIF_EVENT 0x04
|
||||
|
||||
/* Cirrus Logic CS4213 is like CS4210 but does not have SPDIF input/output */
|
||||
#define CS4213_VENDOR_NID 0x09
|
||||
|
||||
@ -984,7 +982,7 @@ static void cs4210_pinmux_init(struct hda_codec *codec)
|
||||
}
|
||||
|
||||
static void cs4210_spdif_automute(struct hda_codec *codec,
|
||||
struct hda_jack_tbl *tbl)
|
||||
struct hda_jack_callback *tbl)
|
||||
{
|
||||
struct cs_spec *spec = codec->spec;
|
||||
bool spdif_present = false;
|
||||
@ -1019,7 +1017,6 @@ static void parse_cs421x_digital(struct hda_codec *codec)
|
||||
if (get_wcaps(codec, nid) & AC_WCAP_UNSOL_CAP) {
|
||||
spec->spdif_detect = 1;
|
||||
snd_hda_jack_detect_enable_callback(codec, nid,
|
||||
SPDIF_EVENT,
|
||||
cs4210_spdif_automute);
|
||||
}
|
||||
}
|
||||
|
@ -26,7 +26,6 @@
|
||||
#include <linux/module.h>
|
||||
#include <sound/core.h>
|
||||
#include <sound/jack.h>
|
||||
#include <sound/tlv.h>
|
||||
|
||||
#include "hda_codec.h"
|
||||
#include "hda_local.h"
|
||||
@ -394,7 +393,8 @@ static void olpc_xo_update_mic_pins(struct hda_codec *codec)
|
||||
}
|
||||
|
||||
/* mic_autoswitch hook */
|
||||
static void olpc_xo_automic(struct hda_codec *codec, struct hda_jack_tbl *jack)
|
||||
static void olpc_xo_automic(struct hda_codec *codec,
|
||||
struct hda_jack_callback *jack)
|
||||
{
|
||||
struct conexant_spec *spec = codec->spec;
|
||||
int saved_cached_write = codec->cached_write;
|
||||
@ -752,6 +752,7 @@ static const struct hda_model_fixup cxt5051_fixup_models[] = {
|
||||
static const struct snd_pci_quirk cxt5066_fixups[] = {
|
||||
SND_PCI_QUIRK(0x1025, 0x0543, "Acer Aspire One 522", CXT_FIXUP_STEREO_DMIC),
|
||||
SND_PCI_QUIRK(0x1025, 0x054c, "Acer Aspire 3830TG", CXT_FIXUP_ASPIRE_DMIC),
|
||||
SND_PCI_QUIRK(0x1025, 0x054f, "Acer Aspire 4830T", CXT_FIXUP_ASPIRE_DMIC),
|
||||
SND_PCI_QUIRK(0x1043, 0x138d, "Asus", CXT_FIXUP_HEADPHONE_MIC_PIN),
|
||||
SND_PCI_QUIRK(0x152d, 0x0833, "OLPC XO-1.5", CXT_FIXUP_OLPC_XO),
|
||||
SND_PCI_QUIRK(0x17aa, 0x20f2, "Lenovo T400", CXT_PINCFG_LENOVO_TP410),
|
||||
@ -787,6 +788,7 @@ static const struct hda_model_fixup cxt5066_fixup_models[] = {
|
||||
*/
|
||||
static void add_cx5051_fake_mutes(struct hda_codec *codec)
|
||||
{
|
||||
struct conexant_spec *spec = codec->spec;
|
||||
static hda_nid_t out_nids[] = {
|
||||
0x10, 0x11, 0
|
||||
};
|
||||
@ -796,6 +798,7 @@ static void add_cx5051_fake_mutes(struct hda_codec *codec)
|
||||
snd_hda_override_amp_caps(codec, *p, HDA_OUTPUT,
|
||||
AC_AMPCAP_MIN_MUTE |
|
||||
query_amp_caps(codec, *p, HDA_OUTPUT));
|
||||
spec->gen.dac_min_mute = true;
|
||||
}
|
||||
|
||||
static int patch_conexant_auto(struct hda_codec *codec)
|
||||
@ -868,11 +871,6 @@ static int patch_conexant_auto(struct hda_codec *codec)
|
||||
if (err < 0)
|
||||
goto error;
|
||||
|
||||
if (codec->vendor_id == 0x14f15051) {
|
||||
/* minimum value is actually mute */
|
||||
spec->gen.vmaster_tlv[3] |= TLV_DB_SCALE_MUTE;
|
||||
}
|
||||
|
||||
codec->patch_ops = cx_auto_patch_ops;
|
||||
|
||||
/* Some laptops with Conexant chips show stalls in S3 resume,
|
||||
|
@ -1163,17 +1163,23 @@ static void hdmi_setup_audio_infoframe(struct hda_codec *codec,
|
||||
|
||||
static bool hdmi_present_sense(struct hdmi_spec_per_pin *per_pin, int repoll);
|
||||
|
||||
static void jack_callback(struct hda_codec *codec, struct hda_jack_tbl *jack)
|
||||
static void check_presence_and_report(struct hda_codec *codec, hda_nid_t nid)
|
||||
{
|
||||
struct hdmi_spec *spec = codec->spec;
|
||||
int pin_idx = pin_nid_to_pin_index(codec, jack->nid);
|
||||
int pin_idx = pin_nid_to_pin_index(codec, nid);
|
||||
|
||||
if (pin_idx < 0)
|
||||
return;
|
||||
|
||||
if (hdmi_present_sense(get_pin(spec, pin_idx), 1))
|
||||
snd_hda_jack_report_sync(codec);
|
||||
}
|
||||
|
||||
static void jack_callback(struct hda_codec *codec,
|
||||
struct hda_jack_callback *jack)
|
||||
{
|
||||
check_presence_and_report(codec, jack->tbl->nid);
|
||||
}
|
||||
|
||||
static void hdmi_intrinsic_event(struct hda_codec *codec, unsigned int res)
|
||||
{
|
||||
int tag = res >> AC_UNSOL_RES_TAG_SHIFT;
|
||||
@ -1190,7 +1196,7 @@ static void hdmi_intrinsic_event(struct hda_codec *codec, unsigned int res)
|
||||
codec->addr, jack->nid, dev_entry, !!(res & AC_UNSOL_RES_IA),
|
||||
!!(res & AC_UNSOL_RES_PD), !!(res & AC_UNSOL_RES_ELDV));
|
||||
|
||||
jack_callback(codec, jack);
|
||||
check_presence_and_report(codec, jack->nid);
|
||||
}
|
||||
|
||||
static void hdmi_non_intrinsic_event(struct hda_codec *codec, unsigned int res)
|
||||
@ -2165,7 +2171,7 @@ static int generic_hdmi_init(struct hda_codec *codec)
|
||||
hda_nid_t pin_nid = per_pin->pin_nid;
|
||||
|
||||
hdmi_init_pin(codec, pin_nid);
|
||||
snd_hda_jack_detect_enable_callback(codec, pin_nid, pin_nid,
|
||||
snd_hda_jack_detect_enable_callback(codec, pin_nid,
|
||||
codec->jackpoll_interval > 0 ? jack_callback : NULL);
|
||||
}
|
||||
return 0;
|
||||
@ -2428,7 +2434,7 @@ static int simple_playback_init(struct hda_codec *codec)
|
||||
if (get_wcaps(codec, pin) & AC_WCAP_OUT_AMP)
|
||||
snd_hda_codec_write(codec, pin, 0, AC_VERB_SET_AMP_GAIN_MUTE,
|
||||
AMP_OUT_UNMUTE);
|
||||
snd_hda_jack_detect_enable(codec, pin, pin);
|
||||
snd_hda_jack_detect_enable(codec, pin);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -32,7 +32,6 @@
|
||||
#include <linux/module.h>
|
||||
#include <sound/core.h>
|
||||
#include <sound/jack.h>
|
||||
#include <sound/tlv.h>
|
||||
#include "hda_codec.h"
|
||||
#include "hda_local.h"
|
||||
#include "hda_auto_parser.h"
|
||||
@ -40,11 +39,6 @@
|
||||
#include "hda_jack.h"
|
||||
#include "hda_generic.h"
|
||||
|
||||
enum {
|
||||
STAC_VREF_EVENT = 8,
|
||||
STAC_PWR_EVENT,
|
||||
};
|
||||
|
||||
enum {
|
||||
STAC_REF,
|
||||
STAC_9200_OQO,
|
||||
@ -487,7 +481,7 @@ static void stac_toggle_power_map(struct hda_codec *codec, hda_nid_t nid,
|
||||
|
||||
/* update power bit per jack plug/unplug */
|
||||
static void jack_update_power(struct hda_codec *codec,
|
||||
struct hda_jack_tbl *jack)
|
||||
struct hda_jack_callback *jack)
|
||||
{
|
||||
struct sigmatel_spec *spec = codec->spec;
|
||||
int i;
|
||||
@ -495,9 +489,9 @@ static void jack_update_power(struct hda_codec *codec,
|
||||
if (!spec->num_pwrs)
|
||||
return;
|
||||
|
||||
if (jack && jack->nid) {
|
||||
stac_toggle_power_map(codec, jack->nid,
|
||||
snd_hda_jack_detect(codec, jack->nid),
|
||||
if (jack && jack->tbl->nid) {
|
||||
stac_toggle_power_map(codec, jack->tbl->nid,
|
||||
snd_hda_jack_detect(codec, jack->tbl->nid),
|
||||
true);
|
||||
return;
|
||||
}
|
||||
@ -505,42 +499,19 @@ static void jack_update_power(struct hda_codec *codec,
|
||||
/* update all jacks */
|
||||
for (i = 0; i < spec->num_pwrs; i++) {
|
||||
hda_nid_t nid = spec->pwr_nids[i];
|
||||
jack = snd_hda_jack_tbl_get(codec, nid);
|
||||
if (!jack || !jack->action)
|
||||
if (!snd_hda_jack_tbl_get(codec, nid))
|
||||
continue;
|
||||
if (jack->action == STAC_PWR_EVENT ||
|
||||
jack->action <= HDA_GEN_LAST_EVENT)
|
||||
stac_toggle_power_map(codec, nid,
|
||||
snd_hda_jack_detect(codec, nid),
|
||||
false);
|
||||
stac_toggle_power_map(codec, nid,
|
||||
snd_hda_jack_detect(codec, nid),
|
||||
false);
|
||||
}
|
||||
|
||||
snd_hda_codec_write(codec, codec->afg, 0, AC_VERB_IDT_SET_POWER_MAP,
|
||||
spec->power_map_bits);
|
||||
}
|
||||
|
||||
static void stac_hp_automute(struct hda_codec *codec,
|
||||
struct hda_jack_tbl *jack)
|
||||
{
|
||||
snd_hda_gen_hp_automute(codec, jack);
|
||||
jack_update_power(codec, jack);
|
||||
}
|
||||
|
||||
static void stac_line_automute(struct hda_codec *codec,
|
||||
struct hda_jack_tbl *jack)
|
||||
{
|
||||
snd_hda_gen_line_automute(codec, jack);
|
||||
jack_update_power(codec, jack);
|
||||
}
|
||||
|
||||
static void stac_mic_autoswitch(struct hda_codec *codec,
|
||||
struct hda_jack_tbl *jack)
|
||||
{
|
||||
snd_hda_gen_mic_autoswitch(codec, jack);
|
||||
jack_update_power(codec, jack);
|
||||
}
|
||||
|
||||
static void stac_vref_event(struct hda_codec *codec, struct hda_jack_tbl *event)
|
||||
static void stac_vref_event(struct hda_codec *codec,
|
||||
struct hda_jack_callback *event)
|
||||
{
|
||||
unsigned int data;
|
||||
|
||||
@ -563,13 +534,10 @@ static void stac_init_power_map(struct hda_codec *codec)
|
||||
hda_nid_t nid = spec->pwr_nids[i];
|
||||
unsigned int def_conf = snd_hda_codec_get_pincfg(codec, nid);
|
||||
def_conf = get_defcfg_connect(def_conf);
|
||||
if (snd_hda_jack_tbl_get(codec, nid))
|
||||
continue;
|
||||
if (def_conf == AC_JACK_PORT_COMPLEX &&
|
||||
spec->vref_mute_led_nid != nid &&
|
||||
is_jack_detectable(codec, nid)) {
|
||||
snd_hda_jack_detect_enable_callback(codec, nid,
|
||||
STAC_PWR_EVENT,
|
||||
jack_update_power);
|
||||
} else {
|
||||
if (def_conf == AC_JACK_PORT_NONE)
|
||||
@ -3020,7 +2988,7 @@ static void stac92hd71bxx_fixup_hp_m4(struct hda_codec *codec,
|
||||
const struct hda_fixup *fix, int action)
|
||||
{
|
||||
struct sigmatel_spec *spec = codec->spec;
|
||||
struct hda_jack_tbl *jack;
|
||||
struct hda_jack_callback *jack;
|
||||
|
||||
if (action != HDA_FIXUP_ACT_PRE_PROBE)
|
||||
return;
|
||||
@ -3028,11 +2996,9 @@ static void stac92hd71bxx_fixup_hp_m4(struct hda_codec *codec,
|
||||
/* Enable VREF power saving on GPIO1 detect */
|
||||
snd_hda_codec_write_cache(codec, codec->afg, 0,
|
||||
AC_VERB_SET_GPIO_UNSOLICITED_RSP_MASK, 0x02);
|
||||
snd_hda_jack_detect_enable_callback(codec, codec->afg,
|
||||
STAC_VREF_EVENT,
|
||||
stac_vref_event);
|
||||
jack = snd_hda_jack_tbl_get(codec, codec->afg);
|
||||
if (jack)
|
||||
jack = snd_hda_jack_detect_enable_callback(codec, codec->afg,
|
||||
stac_vref_event);
|
||||
if (!IS_ERR(jack))
|
||||
jack->private_data = 0x02;
|
||||
|
||||
spec->gpio_mask |= 0x02;
|
||||
@ -4044,7 +4010,7 @@ static void stac9205_fixup_dell_m43(struct hda_codec *codec,
|
||||
const struct hda_fixup *fix, int action)
|
||||
{
|
||||
struct sigmatel_spec *spec = codec->spec;
|
||||
struct hda_jack_tbl *jack;
|
||||
struct hda_jack_callback *jack;
|
||||
|
||||
if (action == HDA_FIXUP_ACT_PRE_PROBE) {
|
||||
snd_hda_apply_pincfgs(codec, dell_9205_m43_pin_configs);
|
||||
@ -4052,11 +4018,9 @@ static void stac9205_fixup_dell_m43(struct hda_codec *codec,
|
||||
/* Enable unsol response for GPIO4/Dock HP connection */
|
||||
snd_hda_codec_write_cache(codec, codec->afg, 0,
|
||||
AC_VERB_SET_GPIO_UNSOLICITED_RSP_MASK, 0x10);
|
||||
snd_hda_jack_detect_enable_callback(codec, codec->afg,
|
||||
STAC_VREF_EVENT,
|
||||
stac_vref_event);
|
||||
jack = snd_hda_jack_tbl_get(codec, codec->afg);
|
||||
if (jack)
|
||||
jack = snd_hda_jack_detect_enable_callback(codec, codec->afg,
|
||||
stac_vref_event);
|
||||
if (!IS_ERR(jack))
|
||||
jack->private_data = 0x01;
|
||||
|
||||
spec->gpio_dir = 0x0b;
|
||||
@ -4219,17 +4183,11 @@ static int stac_parse_auto_config(struct hda_codec *codec)
|
||||
spec->gen.pcm_capture_hook = stac_capture_pcm_hook;
|
||||
|
||||
spec->gen.automute_hook = stac_update_outputs;
|
||||
spec->gen.hp_automute_hook = stac_hp_automute;
|
||||
spec->gen.line_automute_hook = stac_line_automute;
|
||||
spec->gen.mic_autoswitch_hook = stac_mic_autoswitch;
|
||||
|
||||
err = snd_hda_gen_parse_auto_config(codec, &spec->gen.autocfg);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
/* minimum value is actually mute */
|
||||
spec->gen.vmaster_tlv[3] |= TLV_DB_SCALE_MUTE;
|
||||
|
||||
/* setup analog beep controls */
|
||||
if (spec->anabeep_nid > 0) {
|
||||
err = stac_auto_create_beep_ctls(codec,
|
||||
@ -4276,16 +4234,8 @@ static int stac_parse_auto_config(struct hda_codec *codec)
|
||||
return err;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int stac_build_controls(struct hda_codec *codec)
|
||||
{
|
||||
int err = snd_hda_gen_build_controls(codec);
|
||||
|
||||
if (err < 0)
|
||||
return err;
|
||||
stac_init_power_map(codec);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -4399,7 +4349,7 @@ static int stac_suspend(struct hda_codec *codec)
|
||||
#endif /* CONFIG_PM */
|
||||
|
||||
static const struct hda_codec_ops stac_patch_ops = {
|
||||
.build_controls = stac_build_controls,
|
||||
.build_controls = snd_hda_gen_build_controls,
|
||||
.build_pcms = snd_hda_gen_build_pcms,
|
||||
.init = stac_init,
|
||||
.free = stac_free,
|
||||
@ -4420,6 +4370,7 @@ static int alloc_stac_spec(struct hda_codec *codec)
|
||||
snd_hda_gen_spec_init(&spec->gen);
|
||||
codec->spec = spec;
|
||||
codec->no_trigger_sense = 1; /* seems common with STAC/IDT codecs */
|
||||
spec->gen.dac_min_mute = true;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -118,7 +118,6 @@ static void via_playback_pcm_hook(struct hda_pcm_stream *hinfo,
|
||||
struct hda_codec *codec,
|
||||
struct snd_pcm_substream *substream,
|
||||
int action);
|
||||
static void via_hp_automute(struct hda_codec *codec, struct hda_jack_tbl *tbl);
|
||||
|
||||
static struct via_spec *via_new_spec(struct hda_codec *codec)
|
||||
{
|
||||
@ -575,25 +574,12 @@ static const struct snd_kcontrol_new vt1708_jack_detect_ctl[] = {
|
||||
{} /* terminator */
|
||||
};
|
||||
|
||||
static void via_hp_automute(struct hda_codec *codec, struct hda_jack_tbl *tbl)
|
||||
{
|
||||
set_widgets_power_state(codec);
|
||||
snd_hda_gen_hp_automute(codec, tbl);
|
||||
}
|
||||
|
||||
static void via_line_automute(struct hda_codec *codec, struct hda_jack_tbl *tbl)
|
||||
{
|
||||
set_widgets_power_state(codec);
|
||||
snd_hda_gen_line_automute(codec, tbl);
|
||||
}
|
||||
|
||||
static void via_jack_powerstate_event(struct hda_codec *codec, struct hda_jack_tbl *tbl)
|
||||
static void via_jack_powerstate_event(struct hda_codec *codec,
|
||||
struct hda_jack_callback *tbl)
|
||||
{
|
||||
set_widgets_power_state(codec);
|
||||
}
|
||||
|
||||
#define VIA_JACK_EVENT (HDA_GEN_LAST_EVENT + 1)
|
||||
|
||||
static void via_set_jack_unsol_events(struct hda_codec *codec)
|
||||
{
|
||||
struct via_spec *spec = codec->spec;
|
||||
@ -601,25 +587,17 @@ static void via_set_jack_unsol_events(struct hda_codec *codec)
|
||||
hda_nid_t pin;
|
||||
int i;
|
||||
|
||||
spec->gen.hp_automute_hook = via_hp_automute;
|
||||
if (cfg->speaker_pins[0])
|
||||
spec->gen.line_automute_hook = via_line_automute;
|
||||
|
||||
for (i = 0; i < cfg->line_outs; i++) {
|
||||
pin = cfg->line_out_pins[i];
|
||||
if (pin && !snd_hda_jack_tbl_get(codec, pin) &&
|
||||
is_jack_detectable(codec, pin))
|
||||
if (pin && is_jack_detectable(codec, pin))
|
||||
snd_hda_jack_detect_enable_callback(codec, pin,
|
||||
VIA_JACK_EVENT,
|
||||
via_jack_powerstate_event);
|
||||
}
|
||||
|
||||
for (i = 0; i < cfg->num_inputs; i++) {
|
||||
pin = cfg->line_out_pins[i];
|
||||
if (pin && !snd_hda_jack_tbl_get(codec, pin) &&
|
||||
is_jack_detectable(codec, pin))
|
||||
if (pin && is_jack_detectable(codec, pin))
|
||||
snd_hda_jack_detect_enable_callback(codec, pin,
|
||||
VIA_JACK_EVENT,
|
||||
via_jack_powerstate_event);
|
||||
}
|
||||
}
|
||||
|
@ -2528,7 +2528,7 @@ static int snd_ice1712_free(struct snd_ice1712 *ice)
|
||||
if (!ice->port)
|
||||
goto __hw_end;
|
||||
/* mask all interrupts */
|
||||
outb(0xc0, ICEMT(ice, IRQ));
|
||||
outb(ICE1712_MULTI_CAPTURE | ICE1712_MULTI_PLAYBACK, ICEMT(ice, IRQ));
|
||||
outb(0xff, ICEREG(ice, IRQMASK));
|
||||
/* --- */
|
||||
__hw_end:
|
||||
|
@ -279,7 +279,6 @@ static snd_pcm_uframes_t lx_pcm_stream_pointer(struct snd_pcm_substream
|
||||
{
|
||||
struct lx6464es *chip = snd_pcm_substream_chip(substream);
|
||||
snd_pcm_uframes_t pos;
|
||||
unsigned long flags;
|
||||
int is_capture = (substream->stream == SNDRV_PCM_STREAM_CAPTURE);
|
||||
|
||||
struct lx_stream *lx_stream = is_capture ? &chip->capture_stream :
|
||||
@ -287,9 +286,9 @@ static snd_pcm_uframes_t lx_pcm_stream_pointer(struct snd_pcm_substream
|
||||
|
||||
dev_dbg(chip->card->dev, "->lx_pcm_stream_pointer\n");
|
||||
|
||||
spin_lock_irqsave(&chip->lock, flags);
|
||||
mutex_lock(&chip->lock);
|
||||
pos = lx_stream->frame_pos * substream->runtime->period_size;
|
||||
spin_unlock_irqrestore(&chip->lock, flags);
|
||||
mutex_unlock(&chip->lock);
|
||||
|
||||
dev_dbg(chip->card->dev, "stream_pointer at %ld\n", pos);
|
||||
return pos;
|
||||
@ -485,8 +484,8 @@ static void lx_trigger_stop(struct lx6464es *chip, struct lx_stream *lx_stream)
|
||||
|
||||
}
|
||||
|
||||
static void lx_trigger_tasklet_dispatch_stream(struct lx6464es *chip,
|
||||
struct lx_stream *lx_stream)
|
||||
static void lx_trigger_dispatch_stream(struct lx6464es *chip,
|
||||
struct lx_stream *lx_stream)
|
||||
{
|
||||
switch (lx_stream->status) {
|
||||
case LX_STREAM_STATUS_SCHEDULE_RUN:
|
||||
@ -502,24 +501,12 @@ static void lx_trigger_tasklet_dispatch_stream(struct lx6464es *chip,
|
||||
}
|
||||
}
|
||||
|
||||
static void lx_trigger_tasklet(unsigned long data)
|
||||
{
|
||||
struct lx6464es *chip = (struct lx6464es *)data;
|
||||
unsigned long flags;
|
||||
|
||||
dev_dbg(chip->card->dev, "->lx_trigger_tasklet\n");
|
||||
|
||||
spin_lock_irqsave(&chip->lock, flags);
|
||||
lx_trigger_tasklet_dispatch_stream(chip, &chip->capture_stream);
|
||||
lx_trigger_tasklet_dispatch_stream(chip, &chip->playback_stream);
|
||||
spin_unlock_irqrestore(&chip->lock, flags);
|
||||
}
|
||||
|
||||
static int lx_pcm_trigger_dispatch(struct lx6464es *chip,
|
||||
struct lx_stream *lx_stream, int cmd)
|
||||
{
|
||||
int err = 0;
|
||||
|
||||
mutex_lock(&chip->lock);
|
||||
switch (cmd) {
|
||||
case SNDRV_PCM_TRIGGER_START:
|
||||
lx_stream->status = LX_STREAM_STATUS_SCHEDULE_RUN;
|
||||
@ -533,9 +520,12 @@ static int lx_pcm_trigger_dispatch(struct lx6464es *chip,
|
||||
err = -EINVAL;
|
||||
goto exit;
|
||||
}
|
||||
tasklet_schedule(&chip->trigger_tasklet);
|
||||
|
||||
lx_trigger_dispatch_stream(chip, &chip->capture_stream);
|
||||
lx_trigger_dispatch_stream(chip, &chip->playback_stream);
|
||||
|
||||
exit:
|
||||
mutex_unlock(&chip->lock);
|
||||
return err;
|
||||
}
|
||||
|
||||
@ -861,6 +851,7 @@ static int lx_pcm_create(struct lx6464es *chip)
|
||||
snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &lx_ops_capture);
|
||||
|
||||
pcm->info_flags = 0;
|
||||
pcm->nonatomic = true;
|
||||
strcpy(pcm->name, card_name);
|
||||
|
||||
err = snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV,
|
||||
@ -1009,15 +1000,9 @@ static int snd_lx6464es_create(struct snd_card *card,
|
||||
chip->irq = -1;
|
||||
|
||||
/* initialize synchronization structs */
|
||||
spin_lock_init(&chip->lock);
|
||||
spin_lock_init(&chip->msg_lock);
|
||||
mutex_init(&chip->lock);
|
||||
mutex_init(&chip->msg_lock);
|
||||
mutex_init(&chip->setup_mutex);
|
||||
tasklet_init(&chip->trigger_tasklet, lx_trigger_tasklet,
|
||||
(unsigned long)chip);
|
||||
tasklet_init(&chip->tasklet_capture, lx_tasklet_capture,
|
||||
(unsigned long)chip);
|
||||
tasklet_init(&chip->tasklet_playback, lx_tasklet_playback,
|
||||
(unsigned long)chip);
|
||||
|
||||
/* request resources */
|
||||
err = pci_request_regions(pci, card_name);
|
||||
@ -1032,8 +1017,8 @@ static int snd_lx6464es_create(struct snd_card *card,
|
||||
/* dsp port */
|
||||
chip->port_dsp_bar = pci_ioremap_bar(pci, 2);
|
||||
|
||||
err = request_irq(pci->irq, lx_interrupt, IRQF_SHARED,
|
||||
KBUILD_MODNAME, chip);
|
||||
err = request_threaded_irq(pci->irq, lx_interrupt, lx_threaded_irq,
|
||||
IRQF_SHARED, KBUILD_MODNAME, chip);
|
||||
if (err) {
|
||||
dev_err(card->dev, "unable to grab IRQ %d\n", pci->irq);
|
||||
goto request_irq_failed;
|
||||
|
@ -71,14 +71,10 @@ struct lx6464es {
|
||||
|
||||
u8 mac_address[6];
|
||||
|
||||
spinlock_t lock; /* interrupt spinlock */
|
||||
struct mutex lock; /* interrupt lock */
|
||||
struct mutex setup_mutex; /* mutex used in hw_params, open
|
||||
* and close */
|
||||
|
||||
struct tasklet_struct trigger_tasklet; /* trigger tasklet */
|
||||
struct tasklet_struct tasklet_capture;
|
||||
struct tasklet_struct tasklet_playback;
|
||||
|
||||
/* ports */
|
||||
unsigned long port_plx; /* io port (size=256) */
|
||||
void __iomem *port_plx_remapped; /* remapped plx port */
|
||||
@ -87,8 +83,9 @@ struct lx6464es {
|
||||
* size=8K) */
|
||||
|
||||
/* messaging */
|
||||
spinlock_t msg_lock; /* message spinlock */
|
||||
struct mutex msg_lock; /* message lock */
|
||||
struct lx_rmh rmh;
|
||||
u32 irqsrc;
|
||||
|
||||
/* configuration */
|
||||
uint freq_ratio : 2;
|
||||
|
@ -332,27 +332,25 @@ polling_successful:
|
||||
int lx_dsp_get_version(struct lx6464es *chip, u32 *rdsp_version)
|
||||
{
|
||||
u16 ret;
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&chip->msg_lock, flags);
|
||||
mutex_lock(&chip->msg_lock);
|
||||
|
||||
lx_message_init(&chip->rmh, CMD_01_GET_SYS_CFG);
|
||||
ret = lx_message_send_atomic(chip, &chip->rmh);
|
||||
|
||||
*rdsp_version = chip->rmh.stat[1];
|
||||
spin_unlock_irqrestore(&chip->msg_lock, flags);
|
||||
mutex_unlock(&chip->msg_lock);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int lx_dsp_get_clock_frequency(struct lx6464es *chip, u32 *rfreq)
|
||||
{
|
||||
u16 ret = 0;
|
||||
unsigned long flags;
|
||||
u32 freq_raw = 0;
|
||||
u32 freq = 0;
|
||||
u32 frequency = 0;
|
||||
|
||||
spin_lock_irqsave(&chip->msg_lock, flags);
|
||||
mutex_lock(&chip->msg_lock);
|
||||
|
||||
lx_message_init(&chip->rmh, CMD_01_GET_SYS_CFG);
|
||||
ret = lx_message_send_atomic(chip, &chip->rmh);
|
||||
@ -370,7 +368,7 @@ int lx_dsp_get_clock_frequency(struct lx6464es *chip, u32 *rfreq)
|
||||
frequency = 48000;
|
||||
}
|
||||
|
||||
spin_unlock_irqrestore(&chip->msg_lock, flags);
|
||||
mutex_unlock(&chip->msg_lock);
|
||||
|
||||
*rfreq = frequency * chip->freq_ratio;
|
||||
|
||||
@ -398,25 +396,23 @@ int lx_dsp_get_mac(struct lx6464es *chip)
|
||||
|
||||
int lx_dsp_set_granularity(struct lx6464es *chip, u32 gran)
|
||||
{
|
||||
unsigned long flags;
|
||||
int ret;
|
||||
|
||||
spin_lock_irqsave(&chip->msg_lock, flags);
|
||||
mutex_lock(&chip->msg_lock);
|
||||
|
||||
lx_message_init(&chip->rmh, CMD_02_SET_GRANULARITY);
|
||||
chip->rmh.cmd[0] |= gran;
|
||||
|
||||
ret = lx_message_send_atomic(chip, &chip->rmh);
|
||||
spin_unlock_irqrestore(&chip->msg_lock, flags);
|
||||
mutex_unlock(&chip->msg_lock);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int lx_dsp_read_async_events(struct lx6464es *chip, u32 *data)
|
||||
{
|
||||
unsigned long flags;
|
||||
int ret;
|
||||
|
||||
spin_lock_irqsave(&chip->msg_lock, flags);
|
||||
mutex_lock(&chip->msg_lock);
|
||||
|
||||
lx_message_init(&chip->rmh, CMD_04_GET_EVENT);
|
||||
chip->rmh.stat_len = 9; /* we don't necessarily need the full length */
|
||||
@ -426,7 +422,7 @@ int lx_dsp_read_async_events(struct lx6464es *chip, u32 *data)
|
||||
if (!ret)
|
||||
memcpy(data, chip->rmh.stat, chip->rmh.stat_len * sizeof(u32));
|
||||
|
||||
spin_unlock_irqrestore(&chip->msg_lock, flags);
|
||||
mutex_unlock(&chip->msg_lock);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -440,18 +436,16 @@ int lx_pipe_allocate(struct lx6464es *chip, u32 pipe, int is_capture,
|
||||
int channels)
|
||||
{
|
||||
int err;
|
||||
unsigned long flags;
|
||||
|
||||
u32 pipe_cmd = PIPE_INFO_TO_CMD(is_capture, pipe);
|
||||
|
||||
spin_lock_irqsave(&chip->msg_lock, flags);
|
||||
mutex_lock(&chip->msg_lock);
|
||||
lx_message_init(&chip->rmh, CMD_06_ALLOCATE_PIPE);
|
||||
|
||||
chip->rmh.cmd[0] |= pipe_cmd;
|
||||
chip->rmh.cmd[0] |= channels;
|
||||
|
||||
err = lx_message_send_atomic(chip, &chip->rmh);
|
||||
spin_unlock_irqrestore(&chip->msg_lock, flags);
|
||||
mutex_unlock(&chip->msg_lock);
|
||||
|
||||
if (err != 0)
|
||||
dev_err(chip->card->dev, "could not allocate pipe\n");
|
||||
@ -462,17 +456,15 @@ int lx_pipe_allocate(struct lx6464es *chip, u32 pipe, int is_capture,
|
||||
int lx_pipe_release(struct lx6464es *chip, u32 pipe, int is_capture)
|
||||
{
|
||||
int err;
|
||||
unsigned long flags;
|
||||
|
||||
u32 pipe_cmd = PIPE_INFO_TO_CMD(is_capture, pipe);
|
||||
|
||||
spin_lock_irqsave(&chip->msg_lock, flags);
|
||||
mutex_lock(&chip->msg_lock);
|
||||
lx_message_init(&chip->rmh, CMD_07_RELEASE_PIPE);
|
||||
|
||||
chip->rmh.cmd[0] |= pipe_cmd;
|
||||
|
||||
err = lx_message_send_atomic(chip, &chip->rmh);
|
||||
spin_unlock_irqrestore(&chip->msg_lock, flags);
|
||||
mutex_unlock(&chip->msg_lock);
|
||||
|
||||
return err;
|
||||
}
|
||||
@ -481,8 +473,6 @@ int lx_buffer_ask(struct lx6464es *chip, u32 pipe, int is_capture,
|
||||
u32 *r_needed, u32 *r_freed, u32 *size_array)
|
||||
{
|
||||
int err;
|
||||
unsigned long flags;
|
||||
|
||||
u32 pipe_cmd = PIPE_INFO_TO_CMD(is_capture, pipe);
|
||||
|
||||
#ifdef CONFIG_SND_DEBUG
|
||||
@ -493,7 +483,7 @@ int lx_buffer_ask(struct lx6464es *chip, u32 pipe, int is_capture,
|
||||
*r_needed = 0;
|
||||
*r_freed = 0;
|
||||
|
||||
spin_lock_irqsave(&chip->msg_lock, flags);
|
||||
mutex_lock(&chip->msg_lock);
|
||||
lx_message_init(&chip->rmh, CMD_08_ASK_BUFFERS);
|
||||
|
||||
chip->rmh.cmd[0] |= pipe_cmd;
|
||||
@ -527,7 +517,7 @@ int lx_buffer_ask(struct lx6464es *chip, u32 pipe, int is_capture,
|
||||
}
|
||||
}
|
||||
|
||||
spin_unlock_irqrestore(&chip->msg_lock, flags);
|
||||
mutex_unlock(&chip->msg_lock);
|
||||
return err;
|
||||
}
|
||||
|
||||
@ -535,36 +525,32 @@ int lx_buffer_ask(struct lx6464es *chip, u32 pipe, int is_capture,
|
||||
int lx_pipe_stop(struct lx6464es *chip, u32 pipe, int is_capture)
|
||||
{
|
||||
int err;
|
||||
unsigned long flags;
|
||||
|
||||
u32 pipe_cmd = PIPE_INFO_TO_CMD(is_capture, pipe);
|
||||
|
||||
spin_lock_irqsave(&chip->msg_lock, flags);
|
||||
mutex_lock(&chip->msg_lock);
|
||||
lx_message_init(&chip->rmh, CMD_09_STOP_PIPE);
|
||||
|
||||
chip->rmh.cmd[0] |= pipe_cmd;
|
||||
|
||||
err = lx_message_send_atomic(chip, &chip->rmh);
|
||||
|
||||
spin_unlock_irqrestore(&chip->msg_lock, flags);
|
||||
mutex_unlock(&chip->msg_lock);
|
||||
return err;
|
||||
}
|
||||
|
||||
static int lx_pipe_toggle_state(struct lx6464es *chip, u32 pipe, int is_capture)
|
||||
{
|
||||
int err;
|
||||
unsigned long flags;
|
||||
|
||||
u32 pipe_cmd = PIPE_INFO_TO_CMD(is_capture, pipe);
|
||||
|
||||
spin_lock_irqsave(&chip->msg_lock, flags);
|
||||
mutex_lock(&chip->msg_lock);
|
||||
lx_message_init(&chip->rmh, CMD_0B_TOGGLE_PIPE_STATE);
|
||||
|
||||
chip->rmh.cmd[0] |= pipe_cmd;
|
||||
|
||||
err = lx_message_send_atomic(chip, &chip->rmh);
|
||||
|
||||
spin_unlock_irqrestore(&chip->msg_lock, flags);
|
||||
mutex_unlock(&chip->msg_lock);
|
||||
return err;
|
||||
}
|
||||
|
||||
@ -600,11 +586,9 @@ int lx_pipe_sample_count(struct lx6464es *chip, u32 pipe, int is_capture,
|
||||
u64 *rsample_count)
|
||||
{
|
||||
int err;
|
||||
unsigned long flags;
|
||||
|
||||
u32 pipe_cmd = PIPE_INFO_TO_CMD(is_capture, pipe);
|
||||
|
||||
spin_lock_irqsave(&chip->msg_lock, flags);
|
||||
mutex_lock(&chip->msg_lock);
|
||||
lx_message_init(&chip->rmh, CMD_0A_GET_PIPE_SPL_COUNT);
|
||||
|
||||
chip->rmh.cmd[0] |= pipe_cmd;
|
||||
@ -621,18 +605,16 @@ int lx_pipe_sample_count(struct lx6464es *chip, u32 pipe, int is_capture,
|
||||
+ chip->rmh.stat[1]; /* lo part */
|
||||
}
|
||||
|
||||
spin_unlock_irqrestore(&chip->msg_lock, flags);
|
||||
mutex_unlock(&chip->msg_lock);
|
||||
return err;
|
||||
}
|
||||
|
||||
int lx_pipe_state(struct lx6464es *chip, u32 pipe, int is_capture, u16 *rstate)
|
||||
{
|
||||
int err;
|
||||
unsigned long flags;
|
||||
|
||||
u32 pipe_cmd = PIPE_INFO_TO_CMD(is_capture, pipe);
|
||||
|
||||
spin_lock_irqsave(&chip->msg_lock, flags);
|
||||
mutex_lock(&chip->msg_lock);
|
||||
lx_message_init(&chip->rmh, CMD_0A_GET_PIPE_SPL_COUNT);
|
||||
|
||||
chip->rmh.cmd[0] |= pipe_cmd;
|
||||
@ -644,7 +626,7 @@ int lx_pipe_state(struct lx6464es *chip, u32 pipe, int is_capture, u16 *rstate)
|
||||
else
|
||||
*rstate = (chip->rmh.stat[0] >> PSTATE_OFFSET) & 0x0F;
|
||||
|
||||
spin_unlock_irqrestore(&chip->msg_lock, flags);
|
||||
mutex_unlock(&chip->msg_lock);
|
||||
return err;
|
||||
}
|
||||
|
||||
@ -686,18 +668,16 @@ int lx_stream_set_state(struct lx6464es *chip, u32 pipe,
|
||||
int is_capture, enum stream_state_t state)
|
||||
{
|
||||
int err;
|
||||
unsigned long flags;
|
||||
|
||||
u32 pipe_cmd = PIPE_INFO_TO_CMD(is_capture, pipe);
|
||||
|
||||
spin_lock_irqsave(&chip->msg_lock, flags);
|
||||
mutex_lock(&chip->msg_lock);
|
||||
lx_message_init(&chip->rmh, CMD_13_SET_STREAM_STATE);
|
||||
|
||||
chip->rmh.cmd[0] |= pipe_cmd;
|
||||
chip->rmh.cmd[0] |= state;
|
||||
|
||||
err = lx_message_send_atomic(chip, &chip->rmh);
|
||||
spin_unlock_irqrestore(&chip->msg_lock, flags);
|
||||
mutex_unlock(&chip->msg_lock);
|
||||
|
||||
return err;
|
||||
}
|
||||
@ -706,17 +686,14 @@ int lx_stream_set_format(struct lx6464es *chip, struct snd_pcm_runtime *runtime,
|
||||
u32 pipe, int is_capture)
|
||||
{
|
||||
int err;
|
||||
unsigned long flags;
|
||||
|
||||
u32 pipe_cmd = PIPE_INFO_TO_CMD(is_capture, pipe);
|
||||
|
||||
u32 channels = runtime->channels;
|
||||
|
||||
if (runtime->channels != channels)
|
||||
dev_err(chip->card->dev, "channel count mismatch: %d vs %d",
|
||||
runtime->channels, channels);
|
||||
|
||||
spin_lock_irqsave(&chip->msg_lock, flags);
|
||||
mutex_lock(&chip->msg_lock);
|
||||
lx_message_init(&chip->rmh, CMD_0C_DEF_STREAM);
|
||||
|
||||
chip->rmh.cmd[0] |= pipe_cmd;
|
||||
@ -732,7 +709,7 @@ int lx_stream_set_format(struct lx6464es *chip, struct snd_pcm_runtime *runtime,
|
||||
chip->rmh.cmd[0] |= channels-1;
|
||||
|
||||
err = lx_message_send_atomic(chip, &chip->rmh);
|
||||
spin_unlock_irqrestore(&chip->msg_lock, flags);
|
||||
mutex_unlock(&chip->msg_lock);
|
||||
|
||||
return err;
|
||||
}
|
||||
@ -741,11 +718,9 @@ int lx_stream_state(struct lx6464es *chip, u32 pipe, int is_capture,
|
||||
int *rstate)
|
||||
{
|
||||
int err;
|
||||
unsigned long flags;
|
||||
|
||||
u32 pipe_cmd = PIPE_INFO_TO_CMD(is_capture, pipe);
|
||||
|
||||
spin_lock_irqsave(&chip->msg_lock, flags);
|
||||
mutex_lock(&chip->msg_lock);
|
||||
lx_message_init(&chip->rmh, CMD_0E_GET_STREAM_SPL_COUNT);
|
||||
|
||||
chip->rmh.cmd[0] |= pipe_cmd;
|
||||
@ -754,7 +729,7 @@ int lx_stream_state(struct lx6464es *chip, u32 pipe, int is_capture,
|
||||
|
||||
*rstate = (chip->rmh.stat[0] & SF_START) ? START_STATE : PAUSE_STATE;
|
||||
|
||||
spin_unlock_irqrestore(&chip->msg_lock, flags);
|
||||
mutex_unlock(&chip->msg_lock);
|
||||
return err;
|
||||
}
|
||||
|
||||
@ -762,11 +737,9 @@ int lx_stream_sample_position(struct lx6464es *chip, u32 pipe, int is_capture,
|
||||
u64 *r_bytepos)
|
||||
{
|
||||
int err;
|
||||
unsigned long flags;
|
||||
|
||||
u32 pipe_cmd = PIPE_INFO_TO_CMD(is_capture, pipe);
|
||||
|
||||
spin_lock_irqsave(&chip->msg_lock, flags);
|
||||
mutex_lock(&chip->msg_lock);
|
||||
lx_message_init(&chip->rmh, CMD_0E_GET_STREAM_SPL_COUNT);
|
||||
|
||||
chip->rmh.cmd[0] |= pipe_cmd;
|
||||
@ -777,7 +750,7 @@ int lx_stream_sample_position(struct lx6464es *chip, u32 pipe, int is_capture,
|
||||
<< 32) /* hi part */
|
||||
+ chip->rmh.stat[1]; /* lo part */
|
||||
|
||||
spin_unlock_irqrestore(&chip->msg_lock, flags);
|
||||
mutex_unlock(&chip->msg_lock);
|
||||
return err;
|
||||
}
|
||||
|
||||
@ -787,11 +760,9 @@ int lx_buffer_give(struct lx6464es *chip, u32 pipe, int is_capture,
|
||||
u32 *r_buffer_index)
|
||||
{
|
||||
int err;
|
||||
unsigned long flags;
|
||||
|
||||
u32 pipe_cmd = PIPE_INFO_TO_CMD(is_capture, pipe);
|
||||
|
||||
spin_lock_irqsave(&chip->msg_lock, flags);
|
||||
mutex_lock(&chip->msg_lock);
|
||||
lx_message_init(&chip->rmh, CMD_0F_UPDATE_BUFFER);
|
||||
|
||||
chip->rmh.cmd[0] |= pipe_cmd;
|
||||
@ -828,7 +799,7 @@ int lx_buffer_give(struct lx6464es *chip, u32 pipe, int is_capture,
|
||||
"lx_buffer_give EB_CMD_REFUSED\n");
|
||||
|
||||
done:
|
||||
spin_unlock_irqrestore(&chip->msg_lock, flags);
|
||||
mutex_unlock(&chip->msg_lock);
|
||||
return err;
|
||||
}
|
||||
|
||||
@ -836,11 +807,9 @@ int lx_buffer_free(struct lx6464es *chip, u32 pipe, int is_capture,
|
||||
u32 *r_buffer_size)
|
||||
{
|
||||
int err;
|
||||
unsigned long flags;
|
||||
|
||||
u32 pipe_cmd = PIPE_INFO_TO_CMD(is_capture, pipe);
|
||||
|
||||
spin_lock_irqsave(&chip->msg_lock, flags);
|
||||
mutex_lock(&chip->msg_lock);
|
||||
lx_message_init(&chip->rmh, CMD_11_CANCEL_BUFFER);
|
||||
|
||||
chip->rmh.cmd[0] |= pipe_cmd;
|
||||
@ -852,7 +821,7 @@ int lx_buffer_free(struct lx6464es *chip, u32 pipe, int is_capture,
|
||||
if (err == 0)
|
||||
*r_buffer_size = chip->rmh.stat[0] & MASK_DATA_SIZE;
|
||||
|
||||
spin_unlock_irqrestore(&chip->msg_lock, flags);
|
||||
mutex_unlock(&chip->msg_lock);
|
||||
return err;
|
||||
}
|
||||
|
||||
@ -860,11 +829,9 @@ int lx_buffer_cancel(struct lx6464es *chip, u32 pipe, int is_capture,
|
||||
u32 buffer_index)
|
||||
{
|
||||
int err;
|
||||
unsigned long flags;
|
||||
|
||||
u32 pipe_cmd = PIPE_INFO_TO_CMD(is_capture, pipe);
|
||||
|
||||
spin_lock_irqsave(&chip->msg_lock, flags);
|
||||
mutex_lock(&chip->msg_lock);
|
||||
lx_message_init(&chip->rmh, CMD_11_CANCEL_BUFFER);
|
||||
|
||||
chip->rmh.cmd[0] |= pipe_cmd;
|
||||
@ -872,7 +839,7 @@ int lx_buffer_cancel(struct lx6464es *chip, u32 pipe, int is_capture,
|
||||
|
||||
err = lx_message_send_atomic(chip, &chip->rmh);
|
||||
|
||||
spin_unlock_irqrestore(&chip->msg_lock, flags);
|
||||
mutex_unlock(&chip->msg_lock);
|
||||
return err;
|
||||
}
|
||||
|
||||
@ -885,12 +852,10 @@ int lx_buffer_cancel(struct lx6464es *chip, u32 pipe, int is_capture,
|
||||
int lx_level_unmute(struct lx6464es *chip, int is_capture, int unmute)
|
||||
{
|
||||
int err;
|
||||
unsigned long flags;
|
||||
|
||||
/* bit set to 1: channel muted */
|
||||
u64 mute_mask = unmute ? 0 : 0xFFFFFFFFFFFFFFFFLLU;
|
||||
|
||||
spin_lock_irqsave(&chip->msg_lock, flags);
|
||||
mutex_lock(&chip->msg_lock);
|
||||
lx_message_init(&chip->rmh, CMD_0D_SET_MUTE);
|
||||
|
||||
chip->rmh.cmd[0] |= PIPE_INFO_TO_CMD(is_capture, 0);
|
||||
@ -904,7 +869,7 @@ int lx_level_unmute(struct lx6464es *chip, int is_capture, int unmute)
|
||||
|
||||
err = lx_message_send_atomic(chip, &chip->rmh);
|
||||
|
||||
spin_unlock_irqrestore(&chip->msg_lock, flags);
|
||||
mutex_unlock(&chip->msg_lock);
|
||||
return err;
|
||||
}
|
||||
|
||||
@ -931,10 +896,9 @@ int lx_level_peaks(struct lx6464es *chip, int is_capture, int channels,
|
||||
u32 *r_levels)
|
||||
{
|
||||
int err = 0;
|
||||
unsigned long flags;
|
||||
int i;
|
||||
spin_lock_irqsave(&chip->msg_lock, flags);
|
||||
|
||||
mutex_lock(&chip->msg_lock);
|
||||
for (i = 0; i < channels; i += 4) {
|
||||
u32 s0, s1, s2, s3;
|
||||
|
||||
@ -959,7 +923,7 @@ int lx_level_peaks(struct lx6464es *chip, int is_capture, int channels,
|
||||
r_levels += 4;
|
||||
}
|
||||
|
||||
spin_unlock_irqrestore(&chip->msg_lock, flags);
|
||||
mutex_unlock(&chip->msg_lock);
|
||||
return err;
|
||||
}
|
||||
|
||||
@ -1075,7 +1039,6 @@ static int lx_interrupt_request_new_buffer(struct lx6464es *chip,
|
||||
struct snd_pcm_substream *substream = lx_stream->stream;
|
||||
const unsigned int is_capture = lx_stream->is_capture;
|
||||
int err;
|
||||
unsigned long flags;
|
||||
|
||||
const u32 channels = substream->runtime->channels;
|
||||
const u32 bytes_per_frame = channels * 3;
|
||||
@ -1095,7 +1058,7 @@ static int lx_interrupt_request_new_buffer(struct lx6464es *chip,
|
||||
|
||||
dev_dbg(chip->card->dev, "->lx_interrupt_request_new_buffer\n");
|
||||
|
||||
spin_lock_irqsave(&chip->lock, flags);
|
||||
mutex_lock(&chip->lock);
|
||||
|
||||
err = lx_buffer_ask(chip, 0, is_capture, &needed, &freed, size_array);
|
||||
dev_dbg(chip->card->dev,
|
||||
@ -1109,85 +1072,28 @@ static int lx_interrupt_request_new_buffer(struct lx6464es *chip,
|
||||
buffer_index, (unsigned long)buf, period_bytes);
|
||||
|
||||
lx_stream->frame_pos = next_pos;
|
||||
spin_unlock_irqrestore(&chip->lock, flags);
|
||||
mutex_unlock(&chip->lock);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
void lx_tasklet_playback(unsigned long data)
|
||||
{
|
||||
struct lx6464es *chip = (struct lx6464es *)data;
|
||||
struct lx_stream *lx_stream = &chip->playback_stream;
|
||||
int err;
|
||||
|
||||
dev_dbg(chip->card->dev, "->lx_tasklet_playback\n");
|
||||
|
||||
err = lx_interrupt_request_new_buffer(chip, lx_stream);
|
||||
if (err < 0)
|
||||
dev_err(chip->card->dev,
|
||||
"cannot request new buffer for playback\n");
|
||||
|
||||
snd_pcm_period_elapsed(lx_stream->stream);
|
||||
}
|
||||
|
||||
void lx_tasklet_capture(unsigned long data)
|
||||
{
|
||||
struct lx6464es *chip = (struct lx6464es *)data;
|
||||
struct lx_stream *lx_stream = &chip->capture_stream;
|
||||
int err;
|
||||
|
||||
dev_dbg(chip->card->dev, "->lx_tasklet_capture\n");
|
||||
err = lx_interrupt_request_new_buffer(chip, lx_stream);
|
||||
if (err < 0)
|
||||
dev_err(chip->card->dev,
|
||||
"cannot request new buffer for capture\n");
|
||||
|
||||
snd_pcm_period_elapsed(lx_stream->stream);
|
||||
}
|
||||
|
||||
|
||||
|
||||
static int lx_interrupt_handle_audio_transfer(struct lx6464es *chip,
|
||||
u64 notified_in_pipe_mask,
|
||||
u64 notified_out_pipe_mask)
|
||||
{
|
||||
int err = 0;
|
||||
|
||||
if (notified_in_pipe_mask) {
|
||||
dev_dbg(chip->card->dev,
|
||||
"requesting audio transfer for capture\n");
|
||||
tasklet_hi_schedule(&chip->tasklet_capture);
|
||||
}
|
||||
|
||||
if (notified_out_pipe_mask) {
|
||||
dev_dbg(chip->card->dev,
|
||||
"requesting audio transfer for playback\n");
|
||||
tasklet_hi_schedule(&chip->tasklet_playback);
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
irqreturn_t lx_interrupt(int irq, void *dev_id)
|
||||
{
|
||||
struct lx6464es *chip = dev_id;
|
||||
int async_pending, async_escmd;
|
||||
u32 irqsrc;
|
||||
|
||||
spin_lock(&chip->lock);
|
||||
bool wake_thread = false;
|
||||
|
||||
dev_dbg(chip->card->dev,
|
||||
"**************************************************\n");
|
||||
|
||||
if (!lx_interrupt_ack(chip, &irqsrc, &async_pending, &async_escmd)) {
|
||||
spin_unlock(&chip->lock);
|
||||
dev_dbg(chip->card->dev, "IRQ_NONE\n");
|
||||
return IRQ_NONE; /* this device did not cause the interrupt */
|
||||
}
|
||||
|
||||
if (irqsrc & MASK_SYS_STATUS_CMD_DONE)
|
||||
goto exit;
|
||||
return IRQ_HANDLED;
|
||||
|
||||
if (irqsrc & MASK_SYS_STATUS_EOBI)
|
||||
dev_dbg(chip->card->dev, "interrupt: EOBI\n");
|
||||
@ -1202,27 +1108,8 @@ irqreturn_t lx_interrupt(int irq, void *dev_id)
|
||||
dev_dbg(chip->card->dev, "interrupt: ORUN\n");
|
||||
|
||||
if (async_pending) {
|
||||
u64 notified_in_pipe_mask = 0;
|
||||
u64 notified_out_pipe_mask = 0;
|
||||
int freq_changed;
|
||||
int err;
|
||||
|
||||
/* handle async events */
|
||||
err = lx_interrupt_handle_async_events(chip, irqsrc,
|
||||
&freq_changed,
|
||||
¬ified_in_pipe_mask,
|
||||
¬ified_out_pipe_mask);
|
||||
if (err)
|
||||
dev_err(chip->card->dev,
|
||||
"error handling async events\n");
|
||||
|
||||
err = lx_interrupt_handle_audio_transfer(chip,
|
||||
notified_in_pipe_mask,
|
||||
notified_out_pipe_mask
|
||||
);
|
||||
if (err)
|
||||
dev_err(chip->card->dev,
|
||||
"error during audio transfer\n");
|
||||
wake_thread = true;
|
||||
chip->irqsrc = irqsrc;
|
||||
}
|
||||
|
||||
if (async_escmd) {
|
||||
@ -1235,9 +1122,50 @@ irqreturn_t lx_interrupt(int irq, void *dev_id)
|
||||
dev_dbg(chip->card->dev, "interrupt requests escmd handling\n");
|
||||
}
|
||||
|
||||
exit:
|
||||
spin_unlock(&chip->lock);
|
||||
return IRQ_HANDLED; /* this device caused the interrupt */
|
||||
return wake_thread ? IRQ_WAKE_THREAD : IRQ_HANDLED;
|
||||
}
|
||||
|
||||
irqreturn_t lx_threaded_irq(int irq, void *dev_id)
|
||||
{
|
||||
struct lx6464es *chip = dev_id;
|
||||
u64 notified_in_pipe_mask = 0;
|
||||
u64 notified_out_pipe_mask = 0;
|
||||
int freq_changed;
|
||||
int err;
|
||||
|
||||
/* handle async events */
|
||||
err = lx_interrupt_handle_async_events(chip, chip->irqsrc,
|
||||
&freq_changed,
|
||||
¬ified_in_pipe_mask,
|
||||
¬ified_out_pipe_mask);
|
||||
if (err)
|
||||
dev_err(chip->card->dev, "error handling async events\n");
|
||||
|
||||
if (notified_in_pipe_mask) {
|
||||
struct lx_stream *lx_stream = &chip->capture_stream;
|
||||
|
||||
dev_dbg(chip->card->dev,
|
||||
"requesting audio transfer for capture\n");
|
||||
err = lx_interrupt_request_new_buffer(chip, lx_stream);
|
||||
if (err < 0)
|
||||
dev_err(chip->card->dev,
|
||||
"cannot request new buffer for capture\n");
|
||||
snd_pcm_period_elapsed(lx_stream->stream);
|
||||
}
|
||||
|
||||
if (notified_out_pipe_mask) {
|
||||
struct lx_stream *lx_stream = &chip->playback_stream;
|
||||
|
||||
dev_dbg(chip->card->dev,
|
||||
"requesting audio transfer for playback\n");
|
||||
err = lx_interrupt_request_new_buffer(chip, lx_stream);
|
||||
if (err < 0)
|
||||
dev_err(chip->card->dev,
|
||||
"cannot request new buffer for playback\n");
|
||||
snd_pcm_period_elapsed(lx_stream->stream);
|
||||
}
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
|
||||
|
@ -181,12 +181,10 @@ int lx_level_peaks(struct lx6464es *chip, int is_capture, int channels,
|
||||
|
||||
/* interrupt handling */
|
||||
irqreturn_t lx_interrupt(int irq, void *dev_id);
|
||||
irqreturn_t lx_threaded_irq(int irq, void *dev_id);
|
||||
void lx_irq_enable(struct lx6464es *chip);
|
||||
void lx_irq_disable(struct lx6464es *chip);
|
||||
|
||||
void lx_tasklet_capture(unsigned long data);
|
||||
void lx_tasklet_playback(unsigned long data);
|
||||
|
||||
|
||||
/* Stream Format Header Defines (for LIN and IEEE754) */
|
||||
#define HEADER_FMT_BASE HEADER_FMT_BASE_LIN
|
||||
|
@ -986,6 +986,7 @@ static int snd_mixart_pcm_analog(struct snd_mixart *chip)
|
||||
snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_mixart_capture_ops);
|
||||
|
||||
pcm->info_flags = 0;
|
||||
pcm->nonatomic = true;
|
||||
strcpy(pcm->name, name);
|
||||
|
||||
preallocate_buffers(chip, pcm);
|
||||
@ -1018,6 +1019,7 @@ static int snd_mixart_pcm_digital(struct snd_mixart *chip)
|
||||
snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_mixart_capture_ops);
|
||||
|
||||
pcm->info_flags = 0;
|
||||
pcm->nonatomic = true;
|
||||
strcpy(pcm->name, name);
|
||||
|
||||
preallocate_buffers(chip, pcm);
|
||||
@ -1303,8 +1305,9 @@ static int snd_mixart_probe(struct pci_dev *pci,
|
||||
}
|
||||
}
|
||||
|
||||
if (request_irq(pci->irq, snd_mixart_interrupt, IRQF_SHARED,
|
||||
KBUILD_MODNAME, mgr)) {
|
||||
if (request_threaded_irq(pci->irq, snd_mixart_interrupt,
|
||||
snd_mixart_threaded_irq, IRQF_SHARED,
|
||||
KBUILD_MODNAME, mgr)) {
|
||||
dev_err(&pci->dev, "unable to grab IRQ %d\n", pci->irq);
|
||||
snd_mixart_free(mgr);
|
||||
return -EBUSY;
|
||||
@ -1314,24 +1317,18 @@ static int snd_mixart_probe(struct pci_dev *pci,
|
||||
sprintf(mgr->shortname, "Digigram miXart");
|
||||
sprintf(mgr->longname, "%s at 0x%lx & 0x%lx, irq %i", mgr->shortname, mgr->mem[0].phys, mgr->mem[1].phys, mgr->irq);
|
||||
|
||||
/* ISR spinlock */
|
||||
spin_lock_init(&mgr->lock);
|
||||
|
||||
/* init mailbox */
|
||||
mgr->msg_fifo_readptr = 0;
|
||||
mgr->msg_fifo_writeptr = 0;
|
||||
|
||||
spin_lock_init(&mgr->msg_lock);
|
||||
mutex_init(&mgr->msg_mutex);
|
||||
mutex_init(&mgr->lock);
|
||||
mutex_init(&mgr->msg_lock);
|
||||
init_waitqueue_head(&mgr->msg_sleep);
|
||||
atomic_set(&mgr->msg_processed, 0);
|
||||
|
||||
/* init setup mutex*/
|
||||
mutex_init(&mgr->setup_mutex);
|
||||
|
||||
/* init message taslket */
|
||||
tasklet_init(&mgr->msg_taskq, snd_mixart_msg_tasklet, (unsigned long) mgr);
|
||||
|
||||
/* card assignment */
|
||||
mgr->num_cards = MIXART_MAX_CARDS; /* 4 FIXME: configurable? */
|
||||
for (i = 0; i < mgr->num_cards; i++) {
|
||||
|
@ -78,22 +78,18 @@ struct mixart_mgr {
|
||||
char shortname[32]; /* short name of this soundcard */
|
||||
char longname[80]; /* name of this soundcard */
|
||||
|
||||
/* message tasklet */
|
||||
struct tasklet_struct msg_taskq;
|
||||
|
||||
/* one and only blocking message or notification may be pending */
|
||||
u32 pending_event;
|
||||
wait_queue_head_t msg_sleep;
|
||||
|
||||
/* messages stored for tasklet */
|
||||
/* messages fifo */
|
||||
u32 msg_fifo[MSG_FIFO_SIZE];
|
||||
int msg_fifo_readptr;
|
||||
int msg_fifo_writeptr;
|
||||
atomic_t msg_processed; /* number of messages to be processed in takslet */
|
||||
|
||||
spinlock_t lock; /* interrupt spinlock */
|
||||
spinlock_t msg_lock; /* mailbox spinlock */
|
||||
struct mutex msg_mutex; /* mutex for blocking_requests */
|
||||
struct mutex lock; /* interrupt lock */
|
||||
struct mutex msg_lock; /* mailbox lock */
|
||||
|
||||
struct mutex setup_mutex; /* mutex used in hw_params, open and close */
|
||||
|
||||
|
@ -76,7 +76,6 @@ static int retrieve_msg_frame(struct mixart_mgr *mgr, u32 *msg_frame)
|
||||
static int get_msg(struct mixart_mgr *mgr, struct mixart_msg *resp,
|
||||
u32 msg_frame_address )
|
||||
{
|
||||
unsigned long flags;
|
||||
u32 headptr;
|
||||
u32 size;
|
||||
int err;
|
||||
@ -84,7 +83,7 @@ static int get_msg(struct mixart_mgr *mgr, struct mixart_msg *resp,
|
||||
unsigned int i;
|
||||
#endif
|
||||
|
||||
spin_lock_irqsave(&mgr->msg_lock, flags);
|
||||
mutex_lock(&mgr->msg_lock);
|
||||
err = 0;
|
||||
|
||||
/* copy message descriptor from miXart to driver */
|
||||
@ -133,7 +132,7 @@ static int get_msg(struct mixart_mgr *mgr, struct mixart_msg *resp,
|
||||
writel_be(headptr, MIXART_MEM(mgr, MSG_OUTBOUND_FREE_HEAD));
|
||||
|
||||
_clean_exit:
|
||||
spin_unlock_irqrestore(&mgr->msg_lock, flags);
|
||||
mutex_unlock(&mgr->msg_lock);
|
||||
|
||||
return err;
|
||||
}
|
||||
@ -243,28 +242,24 @@ int snd_mixart_send_msg(struct mixart_mgr *mgr, struct mixart_msg *request, int
|
||||
wait_queue_t wait;
|
||||
long timeout;
|
||||
|
||||
mutex_lock(&mgr->msg_mutex);
|
||||
|
||||
init_waitqueue_entry(&wait, current);
|
||||
|
||||
spin_lock_irq(&mgr->msg_lock);
|
||||
mutex_lock(&mgr->msg_lock);
|
||||
/* send the message */
|
||||
err = send_msg(mgr, request, max_resp_size, 1, &msg_frame); /* send and mark the answer pending */
|
||||
if (err) {
|
||||
spin_unlock_irq(&mgr->msg_lock);
|
||||
mutex_unlock(&mgr->msg_mutex);
|
||||
mutex_unlock(&mgr->msg_lock);
|
||||
return err;
|
||||
}
|
||||
|
||||
set_current_state(TASK_UNINTERRUPTIBLE);
|
||||
add_wait_queue(&mgr->msg_sleep, &wait);
|
||||
spin_unlock_irq(&mgr->msg_lock);
|
||||
mutex_unlock(&mgr->msg_lock);
|
||||
timeout = schedule_timeout(MSG_TIMEOUT_JIFFIES);
|
||||
remove_wait_queue(&mgr->msg_sleep, &wait);
|
||||
|
||||
if (! timeout) {
|
||||
/* error - no ack */
|
||||
mutex_unlock(&mgr->msg_mutex);
|
||||
dev_err(&mgr->pci->dev,
|
||||
"error: no response on msg %x\n", msg_frame);
|
||||
return -EIO;
|
||||
@ -281,7 +276,6 @@ int snd_mixart_send_msg(struct mixart_mgr *mgr, struct mixart_msg *request, int
|
||||
if( request->message_id != resp.message_id )
|
||||
dev_err(&mgr->pci->dev, "RESPONSE ERROR!\n");
|
||||
|
||||
mutex_unlock(&mgr->msg_mutex);
|
||||
return err;
|
||||
}
|
||||
|
||||
@ -300,34 +294,29 @@ int snd_mixart_send_msg_wait_notif(struct mixart_mgr *mgr,
|
||||
if (snd_BUG_ON(notif_event & MSG_CANCEL_NOTIFY_MASK))
|
||||
return -EINVAL;
|
||||
|
||||
mutex_lock(&mgr->msg_mutex);
|
||||
|
||||
init_waitqueue_entry(&wait, current);
|
||||
|
||||
spin_lock_irq(&mgr->msg_lock);
|
||||
mutex_lock(&mgr->msg_lock);
|
||||
/* send the message */
|
||||
err = send_msg(mgr, request, MSG_DEFAULT_SIZE, 1, ¬if_event); /* send and mark the notification event pending */
|
||||
if(err) {
|
||||
spin_unlock_irq(&mgr->msg_lock);
|
||||
mutex_unlock(&mgr->msg_mutex);
|
||||
mutex_unlock(&mgr->msg_lock);
|
||||
return err;
|
||||
}
|
||||
|
||||
set_current_state(TASK_UNINTERRUPTIBLE);
|
||||
add_wait_queue(&mgr->msg_sleep, &wait);
|
||||
spin_unlock_irq(&mgr->msg_lock);
|
||||
mutex_unlock(&mgr->msg_lock);
|
||||
timeout = schedule_timeout(MSG_TIMEOUT_JIFFIES);
|
||||
remove_wait_queue(&mgr->msg_sleep, &wait);
|
||||
|
||||
if (! timeout) {
|
||||
/* error - no ack */
|
||||
mutex_unlock(&mgr->msg_mutex);
|
||||
dev_err(&mgr->pci->dev,
|
||||
"error: notification %x not received\n", notif_event);
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
mutex_unlock(&mgr->msg_mutex);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -335,13 +324,12 @@ int snd_mixart_send_msg_wait_notif(struct mixart_mgr *mgr,
|
||||
int snd_mixart_send_msg_nonblock(struct mixart_mgr *mgr, struct mixart_msg *request)
|
||||
{
|
||||
u32 message_frame;
|
||||
unsigned long flags;
|
||||
int err;
|
||||
|
||||
/* just send the message (do not mark it as a pending one) */
|
||||
spin_lock_irqsave(&mgr->msg_lock, flags);
|
||||
mutex_lock(&mgr->msg_lock);
|
||||
err = send_msg(mgr, request, MSG_DEFAULT_SIZE, 0, &message_frame);
|
||||
spin_unlock_irqrestore(&mgr->msg_lock, flags);
|
||||
mutex_unlock(&mgr->msg_lock);
|
||||
|
||||
/* the answer will be handled by snd_struct mixart_msgasklet() */
|
||||
atomic_inc(&mgr->msg_processed);
|
||||
@ -350,19 +338,16 @@ int snd_mixart_send_msg_nonblock(struct mixart_mgr *mgr, struct mixart_msg *requ
|
||||
}
|
||||
|
||||
|
||||
/* common buffer of tasklet and interrupt to send/receive messages */
|
||||
/* common buffer of interrupt to send/receive messages */
|
||||
static u32 mixart_msg_data[MSG_DEFAULT_SIZE / 4];
|
||||
|
||||
|
||||
void snd_mixart_msg_tasklet(unsigned long arg)
|
||||
static void snd_mixart_process_msg(struct mixart_mgr *mgr)
|
||||
{
|
||||
struct mixart_mgr *mgr = ( struct mixart_mgr*)(arg);
|
||||
struct mixart_msg resp;
|
||||
u32 msg, addr, type;
|
||||
int err;
|
||||
|
||||
spin_lock(&mgr->lock);
|
||||
|
||||
while (mgr->msg_fifo_readptr != mgr->msg_fifo_writeptr) {
|
||||
msg = mgr->msg_fifo[mgr->msg_fifo_readptr];
|
||||
mgr->msg_fifo_readptr++;
|
||||
@ -381,7 +366,7 @@ void snd_mixart_msg_tasklet(unsigned long arg)
|
||||
err = get_msg(mgr, &resp, addr);
|
||||
if( err < 0 ) {
|
||||
dev_err(&mgr->pci->dev,
|
||||
"tasklet: error(%d) reading mf %x\n",
|
||||
"error(%d) reading mf %x\n",
|
||||
err, msg);
|
||||
break;
|
||||
}
|
||||
@ -393,12 +378,12 @@ void snd_mixart_msg_tasklet(unsigned long arg)
|
||||
case MSG_STREAM_STOP_OUTPUT_STAGE_PACKET:
|
||||
if(mixart_msg_data[0])
|
||||
dev_err(&mgr->pci->dev,
|
||||
"tasklet : error MSG_STREAM_ST***_***PUT_STAGE_PACKET status=%x\n",
|
||||
"error MSG_STREAM_ST***_***PUT_STAGE_PACKET status=%x\n",
|
||||
mixart_msg_data[0]);
|
||||
break;
|
||||
default:
|
||||
dev_dbg(&mgr->pci->dev,
|
||||
"tasklet received mf(%x) : msg_id(%x) uid(%x, %x) size(%zd)\n",
|
||||
"received mf(%x) : msg_id(%x) uid(%x, %x) size(%zd)\n",
|
||||
msg, resp.message_id, resp.uid.object_id, resp.uid.desc, resp.size);
|
||||
break;
|
||||
}
|
||||
@ -409,7 +394,7 @@ void snd_mixart_msg_tasklet(unsigned long arg)
|
||||
/* get_msg() necessary */
|
||||
default:
|
||||
dev_err(&mgr->pci->dev,
|
||||
"tasklet doesn't know what to do with message %x\n",
|
||||
"doesn't know what to do with message %x\n",
|
||||
msg);
|
||||
} /* switch type */
|
||||
|
||||
@ -417,26 +402,17 @@ void snd_mixart_msg_tasklet(unsigned long arg)
|
||||
atomic_dec(&mgr->msg_processed);
|
||||
|
||||
} /* while there is a msg in fifo */
|
||||
|
||||
spin_unlock(&mgr->lock);
|
||||
}
|
||||
|
||||
|
||||
irqreturn_t snd_mixart_interrupt(int irq, void *dev_id)
|
||||
{
|
||||
struct mixart_mgr *mgr = dev_id;
|
||||
int err;
|
||||
struct mixart_msg resp;
|
||||
|
||||
u32 msg;
|
||||
u32 it_reg;
|
||||
|
||||
spin_lock(&mgr->lock);
|
||||
|
||||
it_reg = readl_le(MIXART_REG(mgr, MIXART_PCI_OMISR_OFFSET));
|
||||
if( !(it_reg & MIXART_OIDI) ) {
|
||||
/* this device did not cause the interrupt */
|
||||
spin_unlock(&mgr->lock);
|
||||
return IRQ_NONE;
|
||||
}
|
||||
|
||||
@ -450,6 +426,17 @@ irqreturn_t snd_mixart_interrupt(int irq, void *dev_id)
|
||||
/* clear interrupt */
|
||||
writel_le( MIXART_OIDI, MIXART_REG(mgr, MIXART_PCI_OMISR_OFFSET) );
|
||||
|
||||
return IRQ_WAKE_THREAD;
|
||||
}
|
||||
|
||||
irqreturn_t snd_mixart_threaded_irq(int irq, void *dev_id)
|
||||
{
|
||||
struct mixart_mgr *mgr = dev_id;
|
||||
int err;
|
||||
struct mixart_msg resp;
|
||||
u32 msg;
|
||||
|
||||
mutex_lock(&mgr->lock);
|
||||
/* process interrupt */
|
||||
while (retrieve_msg_frame(mgr, &msg)) {
|
||||
|
||||
@ -518,9 +505,9 @@ irqreturn_t snd_mixart_interrupt(int irq, void *dev_id)
|
||||
stream->buf_period_frag = (u32)( sample_count - stream->abs_period_elapsed );
|
||||
|
||||
if(elapsed) {
|
||||
spin_unlock(&mgr->lock);
|
||||
mutex_unlock(&mgr->lock);
|
||||
snd_pcm_period_elapsed(stream->substream);
|
||||
spin_lock(&mgr->lock);
|
||||
mutex_lock(&mgr->lock);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -556,7 +543,7 @@ irqreturn_t snd_mixart_interrupt(int irq, void *dev_id)
|
||||
/* no break, continue ! */
|
||||
case MSG_TYPE_ANSWER:
|
||||
/* answer or notification to a message we are waiting for*/
|
||||
spin_lock(&mgr->msg_lock);
|
||||
mutex_lock(&mgr->msg_lock);
|
||||
if( (msg & ~MSG_TYPE_MASK) == mgr->pending_event ) {
|
||||
wake_up(&mgr->msg_sleep);
|
||||
mgr->pending_event = 0;
|
||||
@ -566,9 +553,9 @@ irqreturn_t snd_mixart_interrupt(int irq, void *dev_id)
|
||||
mgr->msg_fifo[mgr->msg_fifo_writeptr] = msg;
|
||||
mgr->msg_fifo_writeptr++;
|
||||
mgr->msg_fifo_writeptr %= MSG_FIFO_SIZE;
|
||||
tasklet_schedule(&mgr->msg_taskq);
|
||||
snd_mixart_process_msg(mgr);
|
||||
}
|
||||
spin_unlock(&mgr->msg_lock);
|
||||
mutex_unlock(&mgr->msg_lock);
|
||||
break;
|
||||
case MSG_TYPE_REQUEST:
|
||||
default:
|
||||
@ -582,7 +569,7 @@ irqreturn_t snd_mixart_interrupt(int irq, void *dev_id)
|
||||
/* allow interrupt again */
|
||||
writel_le( MIXART_ALLOW_OUTBOUND_DOORBELL, MIXART_REG( mgr, MIXART_PCI_OMIMR_OFFSET));
|
||||
|
||||
spin_unlock(&mgr->lock);
|
||||
mutex_unlock(&mgr->lock);
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
@ -564,7 +564,7 @@ int snd_mixart_send_msg_wait_notif(struct mixart_mgr *mgr, struct mixart_msg *r
|
||||
int snd_mixart_send_msg_nonblock(struct mixart_mgr *mgr, struct mixart_msg *request);
|
||||
|
||||
irqreturn_t snd_mixart_interrupt(int irq, void *dev_id);
|
||||
void snd_mixart_msg_tasklet(unsigned long arg);
|
||||
irqreturn_t snd_mixart_threaded_irq(int irq, void *dev_id);
|
||||
|
||||
void snd_mixart_reset_board(struct mixart_mgr *mgr);
|
||||
|
||||
|
@ -29,6 +29,9 @@
|
||||
/* the multichannel DMA channel has a 24-bit counter */
|
||||
#define BUFFER_BYTES_MAX_MULTICH ((1 << 24) * 4)
|
||||
|
||||
#define FIFO_BYTES 256
|
||||
#define FIFO_BYTES_MULTICH 1024
|
||||
|
||||
#define PERIOD_BYTES_MIN 64
|
||||
|
||||
#define DEFAULT_BUFFER_BYTES (BUFFER_BYTES_MAX / 2)
|
||||
@ -60,6 +63,7 @@ static const struct snd_pcm_hardware oxygen_stereo_hardware = {
|
||||
.period_bytes_max = BUFFER_BYTES_MAX,
|
||||
.periods_min = 1,
|
||||
.periods_max = BUFFER_BYTES_MAX / PERIOD_BYTES_MIN,
|
||||
.fifo_size = FIFO_BYTES,
|
||||
};
|
||||
static const struct snd_pcm_hardware oxygen_multichannel_hardware = {
|
||||
.info = SNDRV_PCM_INFO_MMAP |
|
||||
@ -87,6 +91,7 @@ static const struct snd_pcm_hardware oxygen_multichannel_hardware = {
|
||||
.period_bytes_max = BUFFER_BYTES_MAX_MULTICH,
|
||||
.periods_min = 1,
|
||||
.periods_max = BUFFER_BYTES_MAX_MULTICH / PERIOD_BYTES_MIN,
|
||||
.fifo_size = FIFO_BYTES_MULTICH,
|
||||
};
|
||||
static const struct snd_pcm_hardware oxygen_ac97_hardware = {
|
||||
.info = SNDRV_PCM_INFO_MMAP |
|
||||
@ -106,6 +111,7 @@ static const struct snd_pcm_hardware oxygen_ac97_hardware = {
|
||||
.period_bytes_max = BUFFER_BYTES_MAX,
|
||||
.periods_min = 1,
|
||||
.periods_max = BUFFER_BYTES_MAX / PERIOD_BYTES_MIN,
|
||||
.fifo_size = FIFO_BYTES,
|
||||
};
|
||||
|
||||
static const struct snd_pcm_hardware *const oxygen_hardware[PCM_COUNT] = {
|
||||
@ -141,6 +147,10 @@ static int oxygen_open(struct snd_pcm_substream *substream,
|
||||
runtime->hw.rates &= ~(SNDRV_PCM_RATE_32000 |
|
||||
SNDRV_PCM_RATE_64000);
|
||||
runtime->hw.rate_min = 44100;
|
||||
/* fall through */
|
||||
case PCM_A:
|
||||
case PCM_B:
|
||||
runtime->hw.fifo_size = 0;
|
||||
break;
|
||||
case PCM_MULTICH:
|
||||
runtime->hw.channels_max = chip->model.dac_channels_pcm;
|
||||
|
@ -52,6 +52,7 @@ static const struct pci_device_id xonar_ids[] = {
|
||||
{ OXYGEN_PCI_SUBID(0x1043, 0x835d) },
|
||||
{ OXYGEN_PCI_SUBID(0x1043, 0x835e) },
|
||||
{ OXYGEN_PCI_SUBID(0x1043, 0x838e) },
|
||||
{ OXYGEN_PCI_SUBID(0x1043, 0x8428) },
|
||||
{ OXYGEN_PCI_SUBID(0x1043, 0x8522) },
|
||||
{ OXYGEN_PCI_SUBID(0x1043, 0x85f4) },
|
||||
{ OXYGEN_PCI_SUBID_BROKEN_EEPROM },
|
||||
|
@ -212,6 +212,9 @@
|
||||
#define GPIO_ST_MAGIC 0x0040
|
||||
#define GPIO_ST_HP 0x0080
|
||||
|
||||
#define GPIO_XENSE_OUTPUT_ENABLE (0x0001 | 0x0010 | 0x0020)
|
||||
#define GPIO_XENSE_SPEAKERS 0x0080
|
||||
|
||||
#define I2C_DEVICE_PCM1796(i) (0x98 + ((i) << 1)) /* 10011, ii, /W=0 */
|
||||
#define I2C_DEVICE_CS2000 0x9c /* 100111, 0, /W=0 */
|
||||
|
||||
@ -419,6 +422,7 @@ static void xonar_st_init_common(struct oxygen *chip)
|
||||
|
||||
data->generic.output_enable_bit = GPIO_ST_OUTPUT_ENABLE;
|
||||
data->dacs = chip->model.dac_channels_mixer / 2;
|
||||
data->h6 = chip->model.dac_channels_mixer > 2;
|
||||
data->hp_gain_offset = 2*-18;
|
||||
|
||||
pcm1796_init(chip);
|
||||
@ -499,6 +503,51 @@ static void xonar_stx_init(struct oxygen *chip)
|
||||
xonar_st_init_common(chip);
|
||||
}
|
||||
|
||||
static void xonar_xense_init(struct oxygen *chip)
|
||||
{
|
||||
struct xonar_pcm179x *data = chip->model_data;
|
||||
|
||||
data->generic.ext_power_reg = OXYGEN_GPI_DATA;
|
||||
data->generic.ext_power_int_reg = OXYGEN_GPI_INTERRUPT_MASK;
|
||||
data->generic.ext_power_bit = GPI_EXT_POWER;
|
||||
xonar_init_ext_power(chip);
|
||||
|
||||
data->generic.anti_pop_delay = 100;
|
||||
data->has_cs2000 = 1;
|
||||
data->cs2000_regs[CS2000_FUN_CFG_1] = CS2000_REF_CLK_DIV_1;
|
||||
|
||||
oxygen_write16(chip, OXYGEN_I2S_A_FORMAT,
|
||||
OXYGEN_RATE_48000 |
|
||||
OXYGEN_I2S_FORMAT_I2S |
|
||||
OXYGEN_I2S_MCLK(MCLK_512) |
|
||||
OXYGEN_I2S_BITS_16 |
|
||||
OXYGEN_I2S_MASTER |
|
||||
OXYGEN_I2S_BCLK_64);
|
||||
|
||||
xonar_st_init_i2c(chip);
|
||||
cs2000_registers_init(chip);
|
||||
|
||||
data->generic.output_enable_bit = GPIO_XENSE_OUTPUT_ENABLE;
|
||||
data->dacs = 1;
|
||||
data->hp_gain_offset = 2*-18;
|
||||
|
||||
pcm1796_init(chip);
|
||||
|
||||
oxygen_set_bits16(chip, OXYGEN_GPIO_CONTROL,
|
||||
GPIO_INPUT_ROUTE | GPIO_ST_HP_REAR |
|
||||
GPIO_ST_MAGIC | GPIO_XENSE_SPEAKERS);
|
||||
oxygen_clear_bits16(chip, OXYGEN_GPIO_DATA,
|
||||
GPIO_INPUT_ROUTE | GPIO_ST_HP_REAR |
|
||||
GPIO_XENSE_SPEAKERS);
|
||||
|
||||
xonar_init_cs53x1(chip);
|
||||
xonar_enable_output(chip);
|
||||
|
||||
snd_component_add(chip->card, "PCM1796");
|
||||
snd_component_add(chip->card, "CS5381");
|
||||
snd_component_add(chip->card, "CS2000");
|
||||
}
|
||||
|
||||
static void xonar_d2_cleanup(struct oxygen *chip)
|
||||
{
|
||||
xonar_disable_output(chip);
|
||||
@ -795,11 +844,11 @@ static int st_output_switch_put(struct snd_kcontrol *ctl,
|
||||
static int st_hp_volume_offset_info(struct snd_kcontrol *ctl,
|
||||
struct snd_ctl_elem_info *info)
|
||||
{
|
||||
static const char *const names[3] = {
|
||||
"< 64 ohms", "64-300 ohms", "300-600 ohms"
|
||||
static const char *const names[4] = {
|
||||
"< 32 ohms", "32-64 ohms", "64-300 ohms", "300-600 ohms"
|
||||
};
|
||||
|
||||
return snd_ctl_enum_info(info, 1, 3, names);
|
||||
return snd_ctl_enum_info(info, 1, 4, names);
|
||||
}
|
||||
|
||||
static int st_hp_volume_offset_get(struct snd_kcontrol *ctl,
|
||||
@ -809,12 +858,14 @@ static int st_hp_volume_offset_get(struct snd_kcontrol *ctl,
|
||||
struct xonar_pcm179x *data = chip->model_data;
|
||||
|
||||
mutex_lock(&chip->mutex);
|
||||
if (data->hp_gain_offset < 2*-6)
|
||||
if (data->hp_gain_offset < 2*-12)
|
||||
value->value.enumerated.item[0] = 0;
|
||||
else if (data->hp_gain_offset < 0)
|
||||
else if (data->hp_gain_offset < 2*-6)
|
||||
value->value.enumerated.item[0] = 1;
|
||||
else
|
||||
else if (data->hp_gain_offset < 0)
|
||||
value->value.enumerated.item[0] = 2;
|
||||
else
|
||||
value->value.enumerated.item[0] = 3;
|
||||
mutex_unlock(&chip->mutex);
|
||||
return 0;
|
||||
}
|
||||
@ -823,13 +874,13 @@ static int st_hp_volume_offset_get(struct snd_kcontrol *ctl,
|
||||
static int st_hp_volume_offset_put(struct snd_kcontrol *ctl,
|
||||
struct snd_ctl_elem_value *value)
|
||||
{
|
||||
static const s8 offsets[] = { 2*-18, 2*-6, 0 };
|
||||
static const s8 offsets[] = { 2*-18, 2*-12, 2*-6, 0 };
|
||||
struct oxygen *chip = ctl->private_data;
|
||||
struct xonar_pcm179x *data = chip->model_data;
|
||||
s8 offset;
|
||||
int changed;
|
||||
|
||||
if (value->value.enumerated.item[0] > 2)
|
||||
if (value->value.enumerated.item[0] > 3)
|
||||
return -EINVAL;
|
||||
offset = offsets[value->value.enumerated.item[0]];
|
||||
mutex_lock(&chip->mutex);
|
||||
@ -859,6 +910,67 @@ static const struct snd_kcontrol_new st_controls[] = {
|
||||
},
|
||||
};
|
||||
|
||||
static int xense_output_switch_get(struct snd_kcontrol *ctl,
|
||||
struct snd_ctl_elem_value *value)
|
||||
{
|
||||
struct oxygen *chip = ctl->private_data;
|
||||
u16 gpio;
|
||||
|
||||
gpio = oxygen_read16(chip, OXYGEN_GPIO_DATA);
|
||||
if (gpio & GPIO_XENSE_SPEAKERS)
|
||||
value->value.enumerated.item[0] = 0;
|
||||
else if (!(gpio & GPIO_XENSE_SPEAKERS) && (gpio & GPIO_ST_HP_REAR))
|
||||
value->value.enumerated.item[0] = 1;
|
||||
else
|
||||
value->value.enumerated.item[0] = 2;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int xense_output_switch_put(struct snd_kcontrol *ctl,
|
||||
struct snd_ctl_elem_value *value)
|
||||
{
|
||||
struct oxygen *chip = ctl->private_data;
|
||||
struct xonar_pcm179x *data = chip->model_data;
|
||||
u16 gpio_old, gpio;
|
||||
|
||||
mutex_lock(&chip->mutex);
|
||||
gpio_old = oxygen_read16(chip, OXYGEN_GPIO_DATA);
|
||||
gpio = gpio_old;
|
||||
switch (value->value.enumerated.item[0]) {
|
||||
case 0:
|
||||
gpio |= GPIO_XENSE_SPEAKERS | GPIO_ST_HP_REAR;
|
||||
break;
|
||||
case 1:
|
||||
gpio = (gpio | GPIO_ST_HP_REAR) & ~GPIO_XENSE_SPEAKERS;
|
||||
break;
|
||||
case 2:
|
||||
gpio &= ~(GPIO_XENSE_SPEAKERS | GPIO_ST_HP_REAR);
|
||||
break;
|
||||
}
|
||||
oxygen_write16(chip, OXYGEN_GPIO_DATA, gpio);
|
||||
data->hp_active = !(gpio & GPIO_XENSE_SPEAKERS);
|
||||
update_pcm1796_volume(chip);
|
||||
mutex_unlock(&chip->mutex);
|
||||
return gpio != gpio_old;
|
||||
}
|
||||
|
||||
static const struct snd_kcontrol_new xense_controls[] = {
|
||||
{
|
||||
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
|
||||
.name = "Analog Output",
|
||||
.info = st_output_switch_info,
|
||||
.get = xense_output_switch_get,
|
||||
.put = xense_output_switch_put,
|
||||
},
|
||||
{
|
||||
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
|
||||
.name = "Headphones Impedance Playback Enum",
|
||||
.info = st_hp_volume_offset_info,
|
||||
.get = st_hp_volume_offset_get,
|
||||
.put = st_hp_volume_offset_put,
|
||||
},
|
||||
};
|
||||
|
||||
static void xonar_line_mic_ac97_switch(struct oxygen *chip,
|
||||
unsigned int reg, unsigned int mute)
|
||||
{
|
||||
@ -946,6 +1058,23 @@ static int xonar_st_mixer_init(struct oxygen *chip)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int xonar_xense_mixer_init(struct oxygen *chip)
|
||||
{
|
||||
unsigned int i;
|
||||
int err;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(xense_controls); ++i) {
|
||||
err = snd_ctl_add(chip->card,
|
||||
snd_ctl_new1(&xense_controls[i], chip));
|
||||
if (err < 0)
|
||||
return err;
|
||||
}
|
||||
err = add_pcm1796_controls(chip);
|
||||
if (err < 0)
|
||||
return err;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void dump_pcm1796_registers(struct oxygen *chip,
|
||||
struct snd_info_buffer *buffer)
|
||||
{
|
||||
@ -1140,12 +1269,29 @@ int get_xonar_pcm179x_model(struct oxygen *chip,
|
||||
break;
|
||||
case 0x85f4:
|
||||
chip->model = model_xonar_st;
|
||||
/* TODO: daughterboard support */
|
||||
chip->model.shortname = "Xonar STX II";
|
||||
oxygen_clear_bits16(chip, OXYGEN_GPIO_CONTROL, GPIO_DB_MASK);
|
||||
switch (oxygen_read16(chip, OXYGEN_GPIO_DATA) & GPIO_DB_MASK) {
|
||||
default:
|
||||
chip->model.shortname = "Xonar STX II";
|
||||
break;
|
||||
case GPIO_DB_H6:
|
||||
chip->model.shortname = "Xonar STX II+H6";
|
||||
chip->model.dac_channels_pcm = 8;
|
||||
chip->model.dac_channels_mixer = 8;
|
||||
chip->model.dac_mclks = OXYGEN_MCLKS(256, 128, 128);
|
||||
break;
|
||||
}
|
||||
chip->model.init = xonar_stx_init;
|
||||
chip->model.resume = xonar_stx_resume;
|
||||
chip->model.set_dac_params = set_pcm1796_params;
|
||||
break;
|
||||
case 0x8428:
|
||||
chip->model = model_xonar_st;
|
||||
chip->model.shortname = "Xonar Xense";
|
||||
chip->model.chip = "AV100";
|
||||
chip->model.init = xonar_xense_init;
|
||||
chip->model.mixer_init = xonar_xense_mixer_init;
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
@ -702,13 +702,11 @@ static inline int pcxhr_stream_scheduled_get_pipe(struct pcxhr_stream *stream,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void pcxhr_trigger_tasklet(unsigned long arg)
|
||||
static void pcxhr_start_linked_stream(struct pcxhr_mgr *mgr)
|
||||
{
|
||||
unsigned long flags;
|
||||
int i, j, err;
|
||||
struct pcxhr_pipe *pipe;
|
||||
struct snd_pcxhr *chip;
|
||||
struct pcxhr_mgr *mgr = (struct pcxhr_mgr*)(arg);
|
||||
int capture_mask = 0;
|
||||
int playback_mask = 0;
|
||||
|
||||
@ -736,11 +734,11 @@ static void pcxhr_trigger_tasklet(unsigned long arg)
|
||||
}
|
||||
if (capture_mask == 0 && playback_mask == 0) {
|
||||
mutex_unlock(&mgr->setup_mutex);
|
||||
dev_err(&mgr->pci->dev, "pcxhr_trigger_tasklet : no pipes\n");
|
||||
dev_err(&mgr->pci->dev, "pcxhr_start_linked_stream : no pipes\n");
|
||||
return;
|
||||
}
|
||||
|
||||
dev_dbg(&mgr->pci->dev, "pcxhr_trigger_tasklet : "
|
||||
dev_dbg(&mgr->pci->dev, "pcxhr_start_linked_stream : "
|
||||
"playback_mask=%x capture_mask=%x\n",
|
||||
playback_mask, capture_mask);
|
||||
|
||||
@ -748,7 +746,7 @@ static void pcxhr_trigger_tasklet(unsigned long arg)
|
||||
err = pcxhr_set_pipe_state(mgr, playback_mask, capture_mask, 0);
|
||||
if (err) {
|
||||
mutex_unlock(&mgr->setup_mutex);
|
||||
dev_err(&mgr->pci->dev, "pcxhr_trigger_tasklet : "
|
||||
dev_err(&mgr->pci->dev, "pcxhr_start_linked_stream : "
|
||||
"error stop pipes (P%x C%x)\n",
|
||||
playback_mask, capture_mask);
|
||||
return;
|
||||
@ -793,7 +791,7 @@ static void pcxhr_trigger_tasklet(unsigned long arg)
|
||||
err = pcxhr_set_pipe_state(mgr, playback_mask, capture_mask, 1);
|
||||
if (err) {
|
||||
mutex_unlock(&mgr->setup_mutex);
|
||||
dev_err(&mgr->pci->dev, "pcxhr_trigger_tasklet : "
|
||||
dev_err(&mgr->pci->dev, "pcxhr_start_linked_stream : "
|
||||
"error start pipes (P%x C%x)\n",
|
||||
playback_mask, capture_mask);
|
||||
return;
|
||||
@ -802,7 +800,7 @@ static void pcxhr_trigger_tasklet(unsigned long arg)
|
||||
/* put the streams into the running state now
|
||||
* (increment pointer by interrupt)
|
||||
*/
|
||||
spin_lock_irqsave(&mgr->lock, flags);
|
||||
mutex_lock(&mgr->lock);
|
||||
for ( i =0; i < mgr->num_cards; i++) {
|
||||
struct pcxhr_stream *stream;
|
||||
chip = mgr->chip[i];
|
||||
@ -820,13 +818,13 @@ static void pcxhr_trigger_tasklet(unsigned long arg)
|
||||
}
|
||||
}
|
||||
}
|
||||
spin_unlock_irqrestore(&mgr->lock, flags);
|
||||
mutex_unlock(&mgr->lock);
|
||||
|
||||
mutex_unlock(&mgr->setup_mutex);
|
||||
|
||||
#ifdef CONFIG_SND_DEBUG_VERBOSE
|
||||
do_gettimeofday(&my_tv2);
|
||||
dev_dbg(&mgr->pci->dev, "***TRIGGER TASKLET*** TIME = %ld (err = %x)\n",
|
||||
dev_dbg(&mgr->pci->dev, "***TRIGGER START*** TIME = %ld (err = %x)\n",
|
||||
(long)(my_tv2.tv_usec - my_tv1.tv_usec), err);
|
||||
#endif
|
||||
}
|
||||
@ -853,7 +851,7 @@ static int pcxhr_trigger(struct snd_pcm_substream *subs, int cmd)
|
||||
PCXHR_STREAM_STATUS_SCHEDULE_RUN;
|
||||
snd_pcm_trigger_done(s, subs);
|
||||
}
|
||||
tasklet_schedule(&chip->mgr->trigger_taskq);
|
||||
pcxhr_start_linked_stream(chip->mgr);
|
||||
} else {
|
||||
stream = subs->runtime->private_data;
|
||||
snd_printdd("Only one Substream %c %d\n",
|
||||
@ -1127,20 +1125,19 @@ static int pcxhr_close(struct snd_pcm_substream *subs)
|
||||
|
||||
static snd_pcm_uframes_t pcxhr_stream_pointer(struct snd_pcm_substream *subs)
|
||||
{
|
||||
unsigned long flags;
|
||||
u_int32_t timer_period_frag;
|
||||
int timer_buf_periods;
|
||||
struct snd_pcxhr *chip = snd_pcm_substream_chip(subs);
|
||||
struct snd_pcm_runtime *runtime = subs->runtime;
|
||||
struct pcxhr_stream *stream = runtime->private_data;
|
||||
|
||||
spin_lock_irqsave(&chip->mgr->lock, flags);
|
||||
mutex_lock(&chip->mgr->lock);
|
||||
|
||||
/* get the period fragment and the nb of periods in the buffer */
|
||||
timer_period_frag = stream->timer_period_frag;
|
||||
timer_buf_periods = stream->timer_buf_periods;
|
||||
|
||||
spin_unlock_irqrestore(&chip->mgr->lock, flags);
|
||||
mutex_unlock(&chip->mgr->lock);
|
||||
|
||||
return (snd_pcm_uframes_t)((timer_buf_periods * runtime->period_size) +
|
||||
timer_period_frag);
|
||||
@ -1181,6 +1178,7 @@ int pcxhr_create_pcm(struct snd_pcxhr *chip)
|
||||
snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &pcxhr_ops);
|
||||
|
||||
pcm->info_flags = 0;
|
||||
pcm->nonatomic = true;
|
||||
strcpy(pcm->name, name);
|
||||
|
||||
snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV,
|
||||
@ -1588,8 +1586,9 @@ static int pcxhr_probe(struct pci_dev *pci,
|
||||
mgr->pci = pci;
|
||||
mgr->irq = -1;
|
||||
|
||||
if (request_irq(pci->irq, pcxhr_interrupt, IRQF_SHARED,
|
||||
KBUILD_MODNAME, mgr)) {
|
||||
if (request_threaded_irq(pci->irq, pcxhr_interrupt,
|
||||
pcxhr_threaded_irq, IRQF_SHARED,
|
||||
KBUILD_MODNAME, mgr)) {
|
||||
dev_err(&pci->dev, "unable to grab IRQ %d\n", pci->irq);
|
||||
pcxhr_free(mgr);
|
||||
return -EBUSY;
|
||||
@ -1601,19 +1600,13 @@ static int pcxhr_probe(struct pci_dev *pci,
|
||||
mgr->shortname,
|
||||
mgr->port[0], mgr->port[1], mgr->port[2], mgr->irq);
|
||||
|
||||
/* ISR spinlock */
|
||||
spin_lock_init(&mgr->lock);
|
||||
spin_lock_init(&mgr->msg_lock);
|
||||
/* ISR lock */
|
||||
mutex_init(&mgr->lock);
|
||||
mutex_init(&mgr->msg_lock);
|
||||
|
||||
/* init setup mutex*/
|
||||
mutex_init(&mgr->setup_mutex);
|
||||
|
||||
/* init taslket */
|
||||
tasklet_init(&mgr->msg_taskq, pcxhr_msg_tasklet,
|
||||
(unsigned long) mgr);
|
||||
tasklet_init(&mgr->trigger_taskq, pcxhr_trigger_tasklet,
|
||||
(unsigned long) mgr);
|
||||
|
||||
mgr->prmh = kmalloc(sizeof(*mgr->prmh) +
|
||||
sizeof(u32) * (PCXHR_SIZE_MAX_LONG_STATUS -
|
||||
PCXHR_SIZE_MAX_STATUS),
|
||||
|
@ -78,14 +78,10 @@ struct pcxhr_mgr {
|
||||
char shortname[32]; /* short name of this soundcard */
|
||||
char longname[96]; /* name of this soundcard */
|
||||
|
||||
/* message tasklet */
|
||||
struct tasklet_struct msg_taskq;
|
||||
struct pcxhr_rmh *prmh;
|
||||
/* trigger tasklet */
|
||||
struct tasklet_struct trigger_taskq;
|
||||
|
||||
spinlock_t lock; /* interrupt spinlock */
|
||||
spinlock_t msg_lock; /* message spinlock */
|
||||
struct mutex lock; /* interrupt lock */
|
||||
struct mutex msg_lock; /* message lock */
|
||||
|
||||
struct mutex setup_mutex; /* mutex used in hw_params, open and close */
|
||||
struct mutex mixer_mutex; /* mutex for mixer */
|
||||
|
@ -767,11 +767,11 @@ void pcxhr_set_pipe_cmd_params(struct pcxhr_rmh *rmh, int capture,
|
||||
*/
|
||||
int pcxhr_send_msg(struct pcxhr_mgr *mgr, struct pcxhr_rmh *rmh)
|
||||
{
|
||||
unsigned long flags;
|
||||
int err;
|
||||
spin_lock_irqsave(&mgr->msg_lock, flags);
|
||||
|
||||
mutex_lock(&mgr->msg_lock);
|
||||
err = pcxhr_send_msg_nolock(mgr, rmh);
|
||||
spin_unlock_irqrestore(&mgr->msg_lock, flags);
|
||||
mutex_unlock(&mgr->msg_lock);
|
||||
return err;
|
||||
}
|
||||
|
||||
@ -971,17 +971,16 @@ int pcxhr_write_io_num_reg_cont(struct pcxhr_mgr *mgr, unsigned int mask,
|
||||
unsigned int value, int *changed)
|
||||
{
|
||||
struct pcxhr_rmh rmh;
|
||||
unsigned long flags;
|
||||
int err;
|
||||
|
||||
spin_lock_irqsave(&mgr->msg_lock, flags);
|
||||
mutex_lock(&mgr->msg_lock);
|
||||
if ((mgr->io_num_reg_cont & mask) == value) {
|
||||
dev_dbg(&mgr->pci->dev,
|
||||
"IO_NUM_REG_CONT mask %x already is set to %x\n",
|
||||
mask, value);
|
||||
if (changed)
|
||||
*changed = 0;
|
||||
spin_unlock_irqrestore(&mgr->msg_lock, flags);
|
||||
mutex_unlock(&mgr->msg_lock);
|
||||
return 0; /* already programmed */
|
||||
}
|
||||
pcxhr_init_rmh(&rmh, CMD_ACCESS_IO_WRITE);
|
||||
@ -996,7 +995,7 @@ int pcxhr_write_io_num_reg_cont(struct pcxhr_mgr *mgr, unsigned int mask,
|
||||
if (changed)
|
||||
*changed = 1;
|
||||
}
|
||||
spin_unlock_irqrestore(&mgr->msg_lock, flags);
|
||||
mutex_unlock(&mgr->msg_lock);
|
||||
return err;
|
||||
}
|
||||
|
||||
@ -1043,22 +1042,21 @@ static int pcxhr_handle_async_err(struct pcxhr_mgr *mgr, u32 err,
|
||||
}
|
||||
|
||||
|
||||
void pcxhr_msg_tasklet(unsigned long arg)
|
||||
static void pcxhr_msg_thread(struct pcxhr_mgr *mgr)
|
||||
{
|
||||
struct pcxhr_mgr *mgr = (struct pcxhr_mgr *)(arg);
|
||||
struct pcxhr_rmh *prmh = mgr->prmh;
|
||||
int err;
|
||||
int i, j;
|
||||
|
||||
if (mgr->src_it_dsp & PCXHR_IRQ_FREQ_CHANGE)
|
||||
dev_dbg(&mgr->pci->dev,
|
||||
"TASKLET : PCXHR_IRQ_FREQ_CHANGE event occurred\n");
|
||||
"PCXHR_IRQ_FREQ_CHANGE event occurred\n");
|
||||
if (mgr->src_it_dsp & PCXHR_IRQ_TIME_CODE)
|
||||
dev_dbg(&mgr->pci->dev,
|
||||
"TASKLET : PCXHR_IRQ_TIME_CODE event occurred\n");
|
||||
"PCXHR_IRQ_TIME_CODE event occurred\n");
|
||||
if (mgr->src_it_dsp & PCXHR_IRQ_NOTIFY)
|
||||
dev_dbg(&mgr->pci->dev,
|
||||
"TASKLET : PCXHR_IRQ_NOTIFY event occurred\n");
|
||||
"PCXHR_IRQ_NOTIFY event occurred\n");
|
||||
if (mgr->src_it_dsp & (PCXHR_IRQ_FREQ_CHANGE | PCXHR_IRQ_TIME_CODE)) {
|
||||
/* clear events FREQ_CHANGE and TIME_CODE */
|
||||
pcxhr_init_rmh(prmh, CMD_TEST_IT);
|
||||
@ -1068,7 +1066,7 @@ void pcxhr_msg_tasklet(unsigned long arg)
|
||||
}
|
||||
if (mgr->src_it_dsp & PCXHR_IRQ_ASYNC) {
|
||||
dev_dbg(&mgr->pci->dev,
|
||||
"TASKLET : PCXHR_IRQ_ASYNC event occurred\n");
|
||||
"PCXHR_IRQ_ASYNC event occurred\n");
|
||||
|
||||
pcxhr_init_rmh(prmh, CMD_ASYNC);
|
||||
prmh->cmd[0] |= 1; /* add SEL_ASYNC_EVENTS */
|
||||
@ -1076,7 +1074,7 @@ void pcxhr_msg_tasklet(unsigned long arg)
|
||||
prmh->stat_len = PCXHR_SIZE_MAX_LONG_STATUS;
|
||||
err = pcxhr_send_msg(mgr, prmh);
|
||||
if (err)
|
||||
dev_err(&mgr->pci->dev, "ERROR pcxhr_msg_tasklet=%x;\n",
|
||||
dev_err(&mgr->pci->dev, "ERROR pcxhr_msg_thread=%x;\n",
|
||||
err);
|
||||
i = 1;
|
||||
while (i < prmh->stat_len) {
|
||||
@ -1220,9 +1218,9 @@ static void pcxhr_update_timer_pos(struct pcxhr_mgr *mgr,
|
||||
}
|
||||
|
||||
if (elapsed) {
|
||||
spin_unlock(&mgr->lock);
|
||||
mutex_unlock(&mgr->lock);
|
||||
snd_pcm_period_elapsed(stream->substream);
|
||||
spin_lock(&mgr->lock);
|
||||
mutex_lock(&mgr->lock);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1231,14 +1229,10 @@ irqreturn_t pcxhr_interrupt(int irq, void *dev_id)
|
||||
{
|
||||
struct pcxhr_mgr *mgr = dev_id;
|
||||
unsigned int reg;
|
||||
int i, j;
|
||||
struct snd_pcxhr *chip;
|
||||
|
||||
spin_lock(&mgr->lock);
|
||||
bool wake_thread = false;
|
||||
|
||||
reg = PCXHR_INPL(mgr, PCXHR_PLX_IRQCS);
|
||||
if (! (reg & PCXHR_IRQCS_ACTIVE_PCIDB)) {
|
||||
spin_unlock(&mgr->lock);
|
||||
/* this device did not cause the interrupt */
|
||||
return IRQ_NONE;
|
||||
}
|
||||
@ -1250,6 +1244,44 @@ irqreturn_t pcxhr_interrupt(int irq, void *dev_id)
|
||||
/* timer irq occurred */
|
||||
if (reg & PCXHR_IRQ_TIMER) {
|
||||
int timer_toggle = reg & PCXHR_IRQ_TIMER;
|
||||
if (timer_toggle == mgr->timer_toggle) {
|
||||
dev_dbg(&mgr->pci->dev, "ERROR TIMER TOGGLE\n");
|
||||
mgr->dsp_time_err++;
|
||||
}
|
||||
|
||||
mgr->timer_toggle = timer_toggle;
|
||||
mgr->src_it_dsp = reg;
|
||||
wake_thread = true;
|
||||
}
|
||||
|
||||
/* other irq's handled in the thread */
|
||||
if (reg & PCXHR_IRQ_MASK) {
|
||||
if (reg & PCXHR_IRQ_ASYNC) {
|
||||
/* as we didn't request any async notifications,
|
||||
* some kind of xrun error will probably occurred
|
||||
*/
|
||||
/* better resynchronize all streams next interrupt : */
|
||||
mgr->dsp_time_last = PCXHR_DSP_TIME_INVALID;
|
||||
}
|
||||
mgr->src_it_dsp = reg;
|
||||
wake_thread = true;
|
||||
}
|
||||
#ifdef CONFIG_SND_DEBUG_VERBOSE
|
||||
if (reg & PCXHR_FATAL_DSP_ERR)
|
||||
dev_dbg(&mgr->pci->dev, "FATAL DSP ERROR : %x\n", reg);
|
||||
#endif
|
||||
|
||||
return wake_thread ? IRQ_WAKE_THREAD : IRQ_HANDLED;
|
||||
}
|
||||
|
||||
irqreturn_t pcxhr_threaded_irq(int irq, void *dev_id)
|
||||
{
|
||||
struct pcxhr_mgr *mgr = dev_id;
|
||||
int i, j;
|
||||
struct snd_pcxhr *chip;
|
||||
|
||||
mutex_lock(&mgr->lock);
|
||||
if (mgr->src_it_dsp & PCXHR_IRQ_TIMER) {
|
||||
/* is a 24 bit counter */
|
||||
int dsp_time_new =
|
||||
PCXHR_INPL(mgr, PCXHR_PLX_MBOX4) & PCXHR_DSP_TIME_MASK;
|
||||
@ -1290,13 +1322,6 @@ irqreturn_t pcxhr_interrupt(int irq, void *dev_id)
|
||||
#endif
|
||||
mgr->dsp_time_last = dsp_time_new;
|
||||
|
||||
if (timer_toggle == mgr->timer_toggle) {
|
||||
dev_dbg(&mgr->pci->dev, "ERROR TIMER TOGGLE\n");
|
||||
mgr->dsp_time_err++;
|
||||
}
|
||||
mgr->timer_toggle = timer_toggle;
|
||||
|
||||
reg &= ~PCXHR_IRQ_TIMER;
|
||||
for (i = 0; i < mgr->num_cards; i++) {
|
||||
chip = mgr->chip[i];
|
||||
for (j = 0; j < chip->nb_streams_capt; j++)
|
||||
@ -1312,22 +1337,7 @@ irqreturn_t pcxhr_interrupt(int irq, void *dev_id)
|
||||
dsp_time_diff);
|
||||
}
|
||||
}
|
||||
/* other irq's handled in the tasklet */
|
||||
if (reg & PCXHR_IRQ_MASK) {
|
||||
if (reg & PCXHR_IRQ_ASYNC) {
|
||||
/* as we didn't request any async notifications,
|
||||
* some kind of xrun error will probably occurred
|
||||
*/
|
||||
/* better resynchronize all streams next interrupt : */
|
||||
mgr->dsp_time_last = PCXHR_DSP_TIME_INVALID;
|
||||
}
|
||||
mgr->src_it_dsp = reg;
|
||||
tasklet_schedule(&mgr->msg_taskq);
|
||||
}
|
||||
#ifdef CONFIG_SND_DEBUG_VERBOSE
|
||||
if (reg & PCXHR_FATAL_DSP_ERR)
|
||||
dev_dbg(&mgr->pci->dev, "FATAL DSP ERROR : %x\n", reg);
|
||||
#endif
|
||||
spin_unlock(&mgr->lock);
|
||||
return IRQ_HANDLED; /* this device caused the interrupt */
|
||||
|
||||
pcxhr_msg_thread(mgr);
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
@ -200,6 +200,6 @@ int pcxhr_write_io_num_reg_cont(struct pcxhr_mgr *mgr, unsigned int mask,
|
||||
|
||||
/* interrupt handling */
|
||||
irqreturn_t pcxhr_interrupt(int irq, void *dev_id);
|
||||
void pcxhr_msg_tasklet(unsigned long arg);
|
||||
irqreturn_t pcxhr_threaded_irq(int irq, void *dev_id);
|
||||
|
||||
#endif /* __SOUND_PCXHR_CORE_H */
|
||||
|
@ -168,8 +168,9 @@ static int snd_vx222_create(struct snd_card *card, struct pci_dev *pci,
|
||||
for (i = 0; i < 2; i++)
|
||||
vx->port[i] = pci_resource_start(pci, i + 1);
|
||||
|
||||
if (request_irq(pci->irq, snd_vx_irq_handler, IRQF_SHARED,
|
||||
KBUILD_MODNAME, chip)) {
|
||||
if (request_threaded_irq(pci->irq, snd_vx_irq_handler,
|
||||
snd_vx_threaded_irq_handler, IRQF_SHARED,
|
||||
KBUILD_MODNAME, chip)) {
|
||||
dev_err(card->dev, "unable to grab IRQ %d\n", pci->irq);
|
||||
snd_vx222_free(chip);
|
||||
return -EBUSY;
|
||||
|
@ -61,6 +61,7 @@ static void snd_pdacf_detach(struct pcmcia_device *p_dev);
|
||||
|
||||
static void pdacf_release(struct pcmcia_device *link)
|
||||
{
|
||||
free_irq(link->irq, link->priv);
|
||||
pcmcia_disable_device(link);
|
||||
}
|
||||
|
||||
@ -220,11 +221,13 @@ static int pdacf_config(struct pcmcia_device *link)
|
||||
|
||||
ret = pcmcia_request_io(link);
|
||||
if (ret)
|
||||
goto failed;
|
||||
goto failed_preirq;
|
||||
|
||||
ret = pcmcia_request_irq(link, pdacf_interrupt);
|
||||
ret = request_threaded_irq(link->irq, pdacf_interrupt,
|
||||
pdacf_threaded_irq,
|
||||
IRQF_SHARED, link->devname, link->priv);
|
||||
if (ret)
|
||||
goto failed;
|
||||
goto failed_preirq;
|
||||
|
||||
ret = pcmcia_enable_device(link);
|
||||
if (ret)
|
||||
@ -236,7 +239,9 @@ static int pdacf_config(struct pcmcia_device *link)
|
||||
|
||||
return 0;
|
||||
|
||||
failed:
|
||||
failed:
|
||||
free_irq(link->irq, link->priv);
|
||||
failed_preirq:
|
||||
pcmcia_disable_device(link);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
@ -88,10 +88,9 @@ struct snd_pdacf {
|
||||
unsigned long port;
|
||||
int irq;
|
||||
|
||||
spinlock_t reg_lock;
|
||||
struct mutex reg_lock;
|
||||
unsigned short regmap[8];
|
||||
unsigned short suspend_reg_scr;
|
||||
struct tasklet_struct tq;
|
||||
|
||||
spinlock_t ak4117_lock;
|
||||
struct ak4117 *ak4117;
|
||||
@ -136,7 +135,7 @@ int snd_pdacf_resume(struct snd_pdacf *chip);
|
||||
#endif
|
||||
int snd_pdacf_pcm_new(struct snd_pdacf *chip);
|
||||
irqreturn_t pdacf_interrupt(int irq, void *dev);
|
||||
void pdacf_tasklet(unsigned long private_data);
|
||||
irqreturn_t pdacf_threaded_irq(int irq, void *dev);
|
||||
void pdacf_reinit(struct snd_pdacf *chip, int resume);
|
||||
|
||||
#endif /* __PDAUDIOCF_H */
|
||||
|
@ -162,9 +162,8 @@ struct snd_pdacf *snd_pdacf_create(struct snd_card *card)
|
||||
if (chip == NULL)
|
||||
return NULL;
|
||||
chip->card = card;
|
||||
spin_lock_init(&chip->reg_lock);
|
||||
mutex_init(&chip->reg_lock);
|
||||
spin_lock_init(&chip->ak4117_lock);
|
||||
tasklet_init(&chip->tq, pdacf_tasklet, (unsigned long)chip);
|
||||
card->private_data = chip;
|
||||
|
||||
pdacf_proc_init(chip);
|
||||
@ -174,19 +173,18 @@ struct snd_pdacf *snd_pdacf_create(struct snd_card *card)
|
||||
static void snd_pdacf_ak4117_change(struct ak4117 *ak4117, unsigned char c0, unsigned char c1)
|
||||
{
|
||||
struct snd_pdacf *chip = ak4117->change_callback_private;
|
||||
unsigned long flags;
|
||||
u16 val;
|
||||
|
||||
if (!(c0 & AK4117_UNLCK))
|
||||
return;
|
||||
spin_lock_irqsave(&chip->reg_lock, flags);
|
||||
mutex_lock(&chip->reg_lock);
|
||||
val = chip->regmap[PDAUDIOCF_REG_SCR>>1];
|
||||
if (ak4117->rcs0 & AK4117_UNLCK)
|
||||
val |= PDAUDIOCF_BLUE_LED_OFF;
|
||||
else
|
||||
val &= ~PDAUDIOCF_BLUE_LED_OFF;
|
||||
pdacf_reg_write(chip, PDAUDIOCF_REG_SCR, val);
|
||||
spin_unlock_irqrestore(&chip->reg_lock, flags);
|
||||
mutex_unlock(&chip->reg_lock);
|
||||
}
|
||||
|
||||
int snd_pdacf_ak4117_create(struct snd_pdacf *chip)
|
||||
|
@ -30,6 +30,7 @@ irqreturn_t pdacf_interrupt(int irq, void *dev)
|
||||
{
|
||||
struct snd_pdacf *chip = dev;
|
||||
unsigned short stat;
|
||||
bool wake_thread = false;
|
||||
|
||||
if ((chip->chip_status & (PDAUDIOCF_STAT_IS_STALE|
|
||||
PDAUDIOCF_STAT_IS_CONFIGURED|
|
||||
@ -41,13 +42,13 @@ irqreturn_t pdacf_interrupt(int irq, void *dev)
|
||||
if (stat & PDAUDIOCF_IRQOVR) /* should never happen */
|
||||
snd_printk(KERN_ERR "PDAUDIOCF SRAM buffer overrun detected!\n");
|
||||
if (chip->pcm_substream)
|
||||
tasklet_schedule(&chip->tq);
|
||||
wake_thread = true;
|
||||
if (!(stat & PDAUDIOCF_IRQAKM))
|
||||
stat |= PDAUDIOCF_IRQAKM; /* check rate */
|
||||
}
|
||||
if (get_irq_regs() != NULL)
|
||||
snd_ak4117_check_rate_and_errors(chip->ak4117, 0);
|
||||
return IRQ_HANDLED;
|
||||
return wake_thread ? IRQ_WAKE_THREAD : IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static inline void pdacf_transfer_mono16(u16 *dst, u16 xor, unsigned int size, unsigned long rdp_port)
|
||||
@ -256,16 +257,16 @@ static void pdacf_transfer(struct snd_pdacf *chip, unsigned int size, unsigned i
|
||||
}
|
||||
}
|
||||
|
||||
void pdacf_tasklet(unsigned long private_data)
|
||||
irqreturn_t pdacf_threaded_irq(int irq, void *dev)
|
||||
{
|
||||
struct snd_pdacf *chip = (struct snd_pdacf *) private_data;
|
||||
struct snd_pdacf *chip = dev;
|
||||
int size, off, cont, rdp, wdp;
|
||||
|
||||
if ((chip->chip_status & (PDAUDIOCF_STAT_IS_STALE|PDAUDIOCF_STAT_IS_CONFIGURED)) != PDAUDIOCF_STAT_IS_CONFIGURED)
|
||||
return;
|
||||
return IRQ_HANDLED;
|
||||
|
||||
if (chip->pcm_substream == NULL || chip->pcm_substream->runtime == NULL || !snd_pcm_running(chip->pcm_substream))
|
||||
return;
|
||||
return IRQ_HANDLED;
|
||||
|
||||
rdp = inw(chip->port + PDAUDIOCF_REG_RDP);
|
||||
wdp = inw(chip->port + PDAUDIOCF_REG_WDP);
|
||||
@ -311,15 +312,15 @@ void pdacf_tasklet(unsigned long private_data)
|
||||
size -= cont;
|
||||
}
|
||||
#endif
|
||||
spin_lock(&chip->reg_lock);
|
||||
mutex_lock(&chip->reg_lock);
|
||||
while (chip->pcm_tdone >= chip->pcm_period) {
|
||||
chip->pcm_hwptr += chip->pcm_period;
|
||||
chip->pcm_hwptr %= chip->pcm_size;
|
||||
chip->pcm_tdone -= chip->pcm_period;
|
||||
spin_unlock(&chip->reg_lock);
|
||||
mutex_unlock(&chip->reg_lock);
|
||||
snd_pcm_period_elapsed(chip->pcm_substream);
|
||||
spin_lock(&chip->reg_lock);
|
||||
mutex_lock(&chip->reg_lock);
|
||||
}
|
||||
spin_unlock(&chip->reg_lock);
|
||||
/* printk(KERN_DEBUG "TASKLET: end\n"); */
|
||||
mutex_unlock(&chip->reg_lock);
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
@ -77,7 +77,7 @@ static int pdacf_pcm_trigger(struct snd_pcm_substream *subs, int cmd)
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
spin_lock(&chip->reg_lock);
|
||||
mutex_lock(&chip->reg_lock);
|
||||
chip->pcm_running += inc;
|
||||
tmp = pdacf_reg_read(chip, PDAUDIOCF_REG_SCR);
|
||||
if (chip->pcm_running) {
|
||||
@ -91,7 +91,7 @@ static int pdacf_pcm_trigger(struct snd_pcm_substream *subs, int cmd)
|
||||
tmp |= val;
|
||||
pdacf_reg_write(chip, PDAUDIOCF_REG_SCR, tmp);
|
||||
__end:
|
||||
spin_unlock(&chip->reg_lock);
|
||||
mutex_unlock(&chip->reg_lock);
|
||||
snd_ak4117_check_rate_and_errors(chip->ak4117, AK4117_CHECK_NO_RATE);
|
||||
return ret;
|
||||
}
|
||||
@ -296,6 +296,7 @@ int snd_pdacf_pcm_new(struct snd_pdacf *chip)
|
||||
|
||||
pcm->private_data = chip;
|
||||
pcm->info_flags = 0;
|
||||
pcm->nonatomic = true;
|
||||
strcpy(pcm->name, chip->card->shortname);
|
||||
chip->pcm = pcm;
|
||||
|
||||
|
@ -468,12 +468,11 @@ static void vxp_write_codec_reg(struct vx_core *chip, int codec, unsigned int da
|
||||
void vx_set_mic_boost(struct vx_core *chip, int boost)
|
||||
{
|
||||
struct snd_vxpocket *pchip = (struct snd_vxpocket *)chip;
|
||||
unsigned long flags;
|
||||
|
||||
if (chip->chip_status & VX_STAT_IS_STALE)
|
||||
return;
|
||||
|
||||
spin_lock_irqsave(&chip->lock, flags);
|
||||
mutex_lock(&chip->lock);
|
||||
if (pchip->regCDSP & P24_CDSP_MICS_SEL_MASK) {
|
||||
if (boost) {
|
||||
/* boost: 38 dB */
|
||||
@ -486,7 +485,7 @@ void vx_set_mic_boost(struct vx_core *chip, int boost)
|
||||
}
|
||||
vx_outb(chip, CDSP, pchip->regCDSP);
|
||||
}
|
||||
spin_unlock_irqrestore(&chip->lock, flags);
|
||||
mutex_unlock(&chip->lock);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -511,17 +510,16 @@ static int vx_compute_mic_level(int level)
|
||||
void vx_set_mic_level(struct vx_core *chip, int level)
|
||||
{
|
||||
struct snd_vxpocket *pchip = (struct snd_vxpocket *)chip;
|
||||
unsigned long flags;
|
||||
|
||||
if (chip->chip_status & VX_STAT_IS_STALE)
|
||||
return;
|
||||
|
||||
spin_lock_irqsave(&chip->lock, flags);
|
||||
mutex_lock(&chip->lock);
|
||||
if (pchip->regCDSP & VXP_CDSP_MIC_SEL_MASK) {
|
||||
level = vx_compute_mic_level(level);
|
||||
vx_outb(chip, MICRO, level);
|
||||
}
|
||||
spin_unlock_irqrestore(&chip->lock, flags);
|
||||
mutex_unlock(&chip->lock);
|
||||
}
|
||||
|
||||
|
||||
|
@ -62,6 +62,7 @@ static unsigned int card_alloc;
|
||||
*/
|
||||
static void vxpocket_release(struct pcmcia_device *link)
|
||||
{
|
||||
free_irq(link->irq, link->priv);
|
||||
pcmcia_disable_device(link);
|
||||
}
|
||||
|
||||
@ -227,11 +228,13 @@ static int vxpocket_config(struct pcmcia_device *link)
|
||||
|
||||
ret = pcmcia_request_io(link);
|
||||
if (ret)
|
||||
goto failed;
|
||||
goto failed_preirq;
|
||||
|
||||
ret = pcmcia_request_irq(link, snd_vx_irq_handler);
|
||||
ret = request_threaded_irq(link->irq, snd_vx_irq_handler,
|
||||
snd_vx_threaded_irq_handler,
|
||||
IRQF_SHARED, link->devname, link->priv);
|
||||
if (ret)
|
||||
goto failed;
|
||||
goto failed_preirq;
|
||||
|
||||
ret = pcmcia_enable_device(link);
|
||||
if (ret)
|
||||
@ -245,7 +248,9 @@ static int vxpocket_config(struct pcmcia_device *link)
|
||||
|
||||
return 0;
|
||||
|
||||
failed:
|
||||
failed:
|
||||
free_irq(link->irq, link->priv);
|
||||
failed_preirq:
|
||||
pcmcia_disable_device(link);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
@ -146,7 +146,7 @@ struct pm860x_priv {
|
||||
struct pm860x_det det;
|
||||
|
||||
int irq[4];
|
||||
unsigned char name[4][MAX_NAME_LEN];
|
||||
unsigned char name[4][MAX_NAME_LEN+1];
|
||||
};
|
||||
|
||||
/* -9450dB to 0dB in 150dB steps ( mute instead of -9450dB) */
|
||||
@ -1337,8 +1337,6 @@ static int pm860x_probe(struct snd_soc_codec *codec)
|
||||
}
|
||||
}
|
||||
|
||||
pm860x_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
|
||||
|
||||
return 0;
|
||||
|
||||
out:
|
||||
@ -1354,7 +1352,6 @@ static int pm860x_remove(struct snd_soc_codec *codec)
|
||||
|
||||
for (i = 3; i >= 0; i--)
|
||||
free_irq(pm860x->irq[i], pm860x);
|
||||
pm860x_set_bias_level(codec, SND_SOC_BIAS_OFF);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -43,6 +43,7 @@ config SND_SOC_ALL_CODECS
|
||||
select SND_SOC_ALC5623 if I2C
|
||||
select SND_SOC_ALC5632 if I2C
|
||||
select SND_SOC_CQ0093VC if MFD_DAVINCI_VOICECODEC
|
||||
select SND_SOC_CS35L32 if I2C
|
||||
select SND_SOC_CS42L51_I2C if I2C
|
||||
select SND_SOC_CS42L52 if I2C && INPUT
|
||||
select SND_SOC_CS42L56 if I2C && INPUT
|
||||
@ -56,7 +57,10 @@ config SND_SOC_ALL_CODECS
|
||||
select SND_SOC_DA7213 if I2C
|
||||
select SND_SOC_DA732X if I2C
|
||||
select SND_SOC_DA9055 if I2C
|
||||
select SND_SOC_DMIC
|
||||
select SND_SOC_BT_SCO
|
||||
select SND_SOC_ES8328_SPI if SPI_MASTER
|
||||
select SND_SOC_ES8328_I2C if I2C
|
||||
select SND_SOC_ISABELLE if I2C
|
||||
select SND_SOC_JZ4740_CODEC
|
||||
select SND_SOC_LM4857 if I2C
|
||||
@ -90,6 +94,7 @@ config SND_SOC_ALL_CODECS
|
||||
select SND_SOC_SSM2518 if I2C
|
||||
select SND_SOC_SSM2602_SPI if SPI_MASTER
|
||||
select SND_SOC_SSM2602_I2C if I2C
|
||||
select SND_SOC_SSM4567 if I2C
|
||||
select SND_SOC_STA32X if I2C
|
||||
select SND_SOC_STA350 if I2C
|
||||
select SND_SOC_STA529 if I2C
|
||||
@ -323,6 +328,10 @@ config SND_SOC_ALC5632
|
||||
config SND_SOC_CQ0093VC
|
||||
tristate
|
||||
|
||||
config SND_SOC_CS35L32
|
||||
tristate "Cirrus Logic CS35L32 CODEC"
|
||||
depends on I2C
|
||||
|
||||
config SND_SOC_CS42L51
|
||||
tristate
|
||||
|
||||
@ -405,6 +414,17 @@ config SND_SOC_DMIC
|
||||
config SND_SOC_HDMI_CODEC
|
||||
tristate "HDMI stub CODEC"
|
||||
|
||||
config SND_SOC_ES8328
|
||||
tristate "Everest Semi ES8328 CODEC"
|
||||
|
||||
config SND_SOC_ES8328_I2C
|
||||
tristate
|
||||
select SND_SOC_ES8328
|
||||
|
||||
config SND_SOC_ES8328_SPI
|
||||
tristate
|
||||
select SND_SOC_ES8328
|
||||
|
||||
config SND_SOC_ISABELLE
|
||||
tristate
|
||||
|
||||
@ -464,6 +484,7 @@ config SND_SOC_RL6231
|
||||
|
||||
config SND_SOC_RT286
|
||||
tristate
|
||||
depends on I2C
|
||||
|
||||
config SND_SOC_RT5631
|
||||
tristate
|
||||
@ -520,12 +541,20 @@ config SND_SOC_SSM2602
|
||||
tristate
|
||||
|
||||
config SND_SOC_SSM2602_SPI
|
||||
tristate "Analog Devices SSM2602 CODEC - SPI"
|
||||
depends on SPI_MASTER
|
||||
select SND_SOC_SSM2602
|
||||
tristate
|
||||
select REGMAP_SPI
|
||||
|
||||
config SND_SOC_SSM2602_I2C
|
||||
tristate "Analog Devices SSM2602 CODEC - I2C"
|
||||
depends on I2C
|
||||
select SND_SOC_SSM2602
|
||||
tristate
|
||||
select REGMAP_I2C
|
||||
|
||||
config SND_SOC_SSM4567
|
||||
tristate "Analog Devices ssm4567 amplifier driver support"
|
||||
depends on I2C
|
||||
|
||||
config SND_SOC_STA32X
|
||||
tristate
|
||||
@ -712,7 +741,8 @@ config SND_SOC_WM8974
|
||||
tristate
|
||||
|
||||
config SND_SOC_WM8978
|
||||
tristate
|
||||
tristate "Wolfson Microelectronics WM8978 codec"
|
||||
depends on I2C
|
||||
|
||||
config SND_SOC_WM8983
|
||||
tristate
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user