diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2014-04-01 15:38:47 -0700 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2014-04-01 15:38:47 -0700 |
commit | c70929147a10fa4538886cb23b934b509c4c0e49 (patch) | |
tree | bd7c25f679b271fc81f2cedc7a70ef059586c353 | |
parent | 4b1779c2cf030c68aefe939d946475e4136c1895 (diff) | |
parent | 69dd89fd2b9406603d218cab8996cfb232d5b8b9 (diff) |
Merge tag 'sound-3.15-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound
Pull sound updates from Takashi Iwai:
"There have been lots of changes in ALSA core, HD-audio and ASoC, also
most of PCI drivers touched by conversions of printks. All these
resulted in a high volume and wide ranged patch sets in this release.
Many changes are fairly trivial, but also lots of nice cleanups and
refactors. There are a few new drivers, most notably, the Intel
Haswell and Baytrail ASoC driver.
Core changes:
- A bit modernization; embed the device struct into snd_card struct,
so that it may be referred from the beginning. A new
snd_card_new() function is introduced for that, and all drivers
have been converted.
- Simplification in the device management code in ALSA core; now
managed by a simple priority list instead
- Converted many kernel messages to use the standard dev_err() & co;
this would be the pretty visible difference, especially for
HD-audio.
HD-audio:
- Conexant codecs use the auto-parser as default now; the old static
code still remains in case of regressions. Some old quirks have
been rewritten with the fixups for auto-parser.
- C-Media codecs also use the auto-parser as default now, too.
- A device struct is assigned to each HD-audio codec, and the
formerly hwdep attributes are accessible over the codec sysfs, too.
hwdep attributes still remain for compatibility.
- Split the PCI-specific stuff for HD-audio controller into a
separate module, ane make a helper module for the generic
controller driver. This is a preliminary change for supporting
Tegra HDMI controller in near future, which slipped from 3.15
merge.
- Device-specific fixes: mute LED support for Lenovo Ideapad, mic LED
fix for HP laptops, more ASUS subwoofer quirks, yet more Dell
laptop headset quirks
- Make the HD-audio codec response a bit more robust
- A few improvements on Realtek ALC282 / 283 about the pop noises
- A couple of Intel HDMI fixes
ASoC:
- Lots of cleanups for enumerations; refactored lots of error prone
original codes to use more modern APIs
- Elimination of the ASoC level wrappers for I2C and SPI moving us
closer to converting to regmap completely and avoiding some
randconfig hassle
- Provide both manually and transparently locked DAPM APIs rather
than a mix of the two fixing some concurrency issues
- Start converting CODEC drivers to use separate bus interface
drivers rather than having them all in one file helping avoid
dependency issues
- DPCM support for Intel Haswell and Bay Trail platforms, lots of
fixes
- Lots of work on improvements for simple-card, DaVinci and the
Renesas rcar drivers.
- New drivers for Analog Devices ADAU1977, TI PCM512x and parts of
the CSR SiRF SoC, TLV320AIC31XXX, Armada 370 DB, Cirrus cs42xx8
- Fixes for the simple-card DAI format DT mess
- DT support for a couple more devices.
- Use of the tdm_slot mapping in a few drivers
Others:
- Support of reset_resume callback for improved S4 in USB-audio
driver; the device with boot quirks have been little tested, which
we need to watch out in this development cycle
- Add PM support for ICE1712 driver (finally!); it's still pretty
partial support, only for M-Audio devices"
* tag 'sound-3.15-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound: (610 commits)
ALSA: ice1712: Add suspend support for M-Audio ICE1712-based cards
ALSA: ice1712: add suspend support for ICE1712 chip
ALSA: hda - Enable beep for ASUS 1015E
ALSA: asihpi: fix some indenting in snd_card_asihpi_pcm_new()
ALSA: hda - add headset mic detect quirks for three Dell laptops
ASoC: tegra: move AC97 clock handling to the machine driver
ASoC: simple-card: Handle many DAI links
ASoC: simple-card: Add DT documentation for multi-DAI links
ASoC: simple-card: dynamically allocate the DAI link and properties
ASoC: imx-ssi: Add .xlate_tdm_slot_mask() support.
ASoC: fsl-esai: Add .xlate_tdm_slot_mask() support.
ASoC: fsl-utils: Add fsl_asoc_xlate_tdm_slot_mask() support.
ASoC: core: remove the 'of_' prefix of of_xlate_tdm_slot_mask.
ASoC: rcar: subnode tidyup for renesas,rsnd.txt
ASoC: Remove name_prefix unset during DAI link init hack
ALSA: hda - Inform the unexpectedly ignored pins by auto-parser
ASoC: rcar: bugfix: it cares about the non-src case
ARM: bockw: fixup SND_SOC_DAIFMT_CBx_CFx flags
ASoC: pcm: Drop incorrect double/extra frees
ASoC: mfld_machine: Fix compile error
...
575 files changed, 29910 insertions, 13255 deletions
diff --git a/Documentation/DocBook/writing-an-alsa-driver.tmpl b/Documentation/DocBook/writing-an-alsa-driver.tmpl index 06741e92598..d0056a4e9c5 100644 --- a/Documentation/DocBook/writing-an-alsa-driver.tmpl +++ b/Documentation/DocBook/writing-an-alsa-driver.tmpl @@ -468,8 +468,6 @@ return err; } - snd_card_set_dev(card, &pci->dev); - *rchip = chip; return 0; } @@ -492,7 +490,8 @@ } /* (2) */ - err = snd_card_create(index[dev], id[dev], THIS_MODULE, 0, &card); + err = snd_card_new(&pci->dev, index[dev], id[dev], THIS_MODULE, + 0, &card); if (err < 0) return err; @@ -591,7 +590,8 @@ struct snd_card *card; int err; .... - err = snd_card_create(index[dev], id[dev], THIS_MODULE, 0, &card); + err = snd_card_new(&pci->dev, index[dev], id[dev], THIS_MODULE, + 0, &card); ]]> </programlisting> </informalexample> @@ -809,28 +809,34 @@ <para> As mentioned above, to create a card instance, call - <function>snd_card_create()</function>. + <function>snd_card_new()</function>. <informalexample> <programlisting> <![CDATA[ struct snd_card *card; int err; - err = snd_card_create(index, id, module, extra_size, &card); + err = snd_card_new(&pci->dev, index, id, module, extra_size, &card); ]]> </programlisting> </informalexample> </para> <para> - The function takes five arguments, the card-index number, the - id string, the module pointer (usually + The function takes six arguments: the parent device pointer, + the card-index number, the id string, the module pointer (usually <constant>THIS_MODULE</constant>), the size of extra-data space, and the pointer to return the card instance. The extra_size argument is used to allocate card->private_data for the chip-specific data. Note that these data - are allocated by <function>snd_card_create()</function>. + are allocated by <function>snd_card_new()</function>. + </para> + + <para> + The first argument, the pointer of struct + <structname>device</structname>, specifies the parent device. + For PCI devices, typically &pci-> is passed there. </para> </section> @@ -916,16 +922,16 @@ </para> <section id="card-management-chip-specific-snd-card-new"> - <title>1. Allocating via <function>snd_card_create()</function>.</title> + <title>1. Allocating via <function>snd_card_new()</function>.</title> <para> As mentioned above, you can pass the extra-data-length - to the 4th argument of <function>snd_card_create()</function>, i.e. + to the 5th argument of <function>snd_card_new()</function>, i.e. <informalexample> <programlisting> <![CDATA[ - err = snd_card_create(index[dev], id[dev], THIS_MODULE, - sizeof(struct mychip), &card); + err = snd_card_new(&pci->dev, index[dev], id[dev], THIS_MODULE, + sizeof(struct mychip), &card); ]]> </programlisting> </informalexample> @@ -954,7 +960,7 @@ <para> After allocating a card instance via - <function>snd_card_create()</function> (with + <function>snd_card_new()</function> (with <constant>0</constant> on the 4th arg), call <function>kzalloc()</function>. @@ -963,7 +969,8 @@ <![CDATA[ struct snd_card *card; struct mychip *chip; - err = snd_card_create(index[dev], id[dev], THIS_MODULE, 0, &card); + err = snd_card_new(&pci->dev, index[dev], id[dev], THIS_MODULE, + 0, &card); ..... chip = kzalloc(sizeof(*chip), GFP_KERNEL); ]]> @@ -1170,8 +1177,6 @@ return err; } - snd_card_set_dev(card, &pci->dev); - *rchip = chip; return 0; } @@ -1526,30 +1531,6 @@ </section> - <section id="pci-resource-device-struct"> - <title>Registration of Device Struct</title> - <para> - At some point, typically after calling <function>snd_device_new()</function>, - you need to register the struct <structname>device</structname> of the chip - you're handling for udev and co. ALSA provides a macro for compatibility with - older kernels. Simply call like the following: - <informalexample> - <programlisting> -<![CDATA[ - snd_card_set_dev(card, &pci->dev); -]]> - </programlisting> - </informalexample> - so that it stores the PCI's device pointer to the card. This will be - referred by ALSA core functions later when the devices are registered. - </para> - <para> - In the case of non-PCI, pass the proper device struct pointer of the BUS - instead. (In the case of legacy ISA without PnP, you don't have to do - anything.) - </para> - </section> - <section id="pci-resource-entries"> <title>PCI Entries</title> <para> @@ -5740,7 +5721,8 @@ struct _snd_pcm_runtime { struct mychip *chip; int err; .... - err = snd_card_create(index[dev], id[dev], THIS_MODULE, 0, &card); + err = snd_card_new(&pci->dev, index[dev], id[dev], THIS_MODULE, + 0, &card); .... chip = kzalloc(sizeof(*chip), GFP_KERNEL); .... @@ -5752,7 +5734,7 @@ struct _snd_pcm_runtime { </informalexample> When you created the chip data with - <function>snd_card_create()</function>, it's anyway accessible + <function>snd_card_new()</function>, it's anyway accessible via <structfield>private_data</structfield> field. <informalexample> @@ -5766,8 +5748,8 @@ struct _snd_pcm_runtime { struct mychip *chip; int err; .... - err = snd_card_create(index[dev], id[dev], THIS_MODULE, - sizeof(struct mychip), &card); + err = snd_card_new(&pci->dev, index[dev], id[dev], THIS_MODULE, + sizeof(struct mychip), &card); .... chip = card->private_data; .... diff --git a/Documentation/devicetree/bindings/i2c/trivial-devices.txt b/Documentation/devicetree/bindings/i2c/trivial-devices.txt index 1a1ac2e560e..f47e56bcf78 100644 --- a/Documentation/devicetree/bindings/i2c/trivial-devices.txt +++ b/Documentation/devicetree/bindings/i2c/trivial-devices.txt @@ -18,6 +18,7 @@ atmel,24c02 i2c serial eeprom (24cxx) atmel,at97sc3204t i2c trusted platform module (TPM) capella,cm32181 CM32181: Ambient Light Sensor catalyst,24c32 i2c serial eeprom +cirrus,cs42l51 Cirrus Logic CS42L51 audio codec dallas,ds1307 64 x 8, Serial, I2C Real-Time Clock dallas,ds1338 I2C RTC with 56-Byte NV RAM dallas,ds1339 I2C Serial Real-Time Clock diff --git a/Documentation/devicetree/bindings/misc/atmel-ssc.txt b/Documentation/devicetree/bindings/misc/atmel-ssc.txt index 60960b2755f..efc98ea1f23 100644 --- a/Documentation/devicetree/bindings/misc/atmel-ssc.txt +++ b/Documentation/devicetree/bindings/misc/atmel-ssc.txt @@ -17,6 +17,14 @@ Required properties for devices compatible with "atmel,at91sam9g45-ssc": See Documentation/devicetree/bindings/dma/atmel-dma.txt for details. - dma-names: Must be "tx", "rx". +Optional properties: + - atmel,clk-from-rk-pin: bool property. + - When SSC works in slave mode, according to the hardware design, the + clock can get from TK pin, and also can get from RK pin. So, add + this parameter to choose where the clock from. + - By default the clock is from TK pin, if the clock from RK pin, this + property is needed. + Examples: - PDC transfer: ssc0: ssc@fffbc000 { diff --git a/Documentation/devicetree/bindings/sound/armada-370db-audio.txt b/Documentation/devicetree/bindings/sound/armada-370db-audio.txt new file mode 100644 index 00000000000..bf984d23862 --- /dev/null +++ b/Documentation/devicetree/bindings/sound/armada-370db-audio.txt @@ -0,0 +1,27 @@ +Device Tree bindings for the Armada 370 DB audio +================================================ + +These Device Tree bindings are used to describe the audio complex +found on the Armada 370 DB platform. + +Mandatory properties: + + * compatible: must be "marvell,a370db-audio" + + * marvell,audio-controller: a phandle that points to the audio + controller of the Armada 370 SoC. + + * marvell,audio-codec: a set of three phandles that points to: + + 1/ the analog audio codec connected to the Armada 370 SoC + 2/ the S/PDIF transceiver + 3/ the S/PDIF receiver + +Example: + + sound { + compatible = "marvell,a370db-audio"; + marvell,audio-controller = <&audio_controller>; + marvell,audio-codec = <&audio_codec &spdif_out &spdif_in>; + status = "okay"; + }; diff --git a/Documentation/devicetree/bindings/sound/cs42xx8.txt b/Documentation/devicetree/bindings/sound/cs42xx8.txt new file mode 100644 index 00000000000..f631fbca628 --- /dev/null +++ b/Documentation/devicetree/bindings/sound/cs42xx8.txt @@ -0,0 +1,28 @@ +CS42448/CS42888 audio CODEC + +Required properties: + + - compatible : must contain one of "cirrus,cs42448" and "cirrus,cs42888" + + - reg : the I2C address of the device for I2C + + - clocks : a list of phandles + clock-specifiers, one for each entry in + clock-names + + - clock-names : must contain "mclk" + + - VA-supply, VD-supply, VLS-supply, VLC-supply: power supplies for the device, + as covered in Documentation/devicetree/bindings/regulator/regulator.txt + +Example: + +codec: cs42888@48 { + compatible = "cirrus,cs42888"; + reg = <0x48>; + clocks = <&codec_mclk 0>; + clock-names = "mclk"; + VA-supply = <®_audio>; + VD-supply = <®_audio>; + VLS-supply = <®_audio>; + VLC-supply = <®_audio>; +}; diff --git a/Documentation/devicetree/bindings/sound/da9055.txt b/Documentation/devicetree/bindings/sound/da9055.txt new file mode 100644 index 00000000000..ed1b7cc6f24 --- /dev/null +++ b/Documentation/devicetree/bindings/sound/da9055.txt @@ -0,0 +1,22 @@ +* Dialog DA9055 Audio CODEC + +DA9055 provides Audio CODEC support (I2C only). + +The Audio CODEC device in DA9055 has it's own I2C address which is configurable, +so the device is instantiated separately from the PMIC (MFD) device. + +For details on accompanying PMIC I2C device, see the following: +Documentation/devicetree/bindings/mfd/da9055.txt + +Required properties: + + - compatible: "dlg,da9055-codec" + - reg: Specifies the I2C slave address + + +Example: + + codec: da9055-codec@1a { + compatible = "dlg,da9055-codec"; + reg = <0x1a>; + }; diff --git a/Documentation/devicetree/bindings/sound/davinci-evm-audio.txt b/Documentation/devicetree/bindings/sound/davinci-evm-audio.txt index 865178d5cdf..963e100514c 100644 --- a/Documentation/devicetree/bindings/sound/davinci-evm-audio.txt +++ b/Documentation/devicetree/bindings/sound/davinci-evm-audio.txt @@ -5,12 +5,19 @@ Required properties: - ti,model : The user-visible name of this sound complex. - ti,audio-codec : The phandle of the TLV320AIC3x audio codec - ti,mcasp-controller : The phandle of the McASP controller -- ti,codec-clock-rate : The Codec Clock rate (in Hz) applied to the Codec - ti,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 for sources and sinks are the codec's pins, and the jacks on the board: +Optional properties: +- ti,codec-clock-rate : The Codec Clock rate (in Hz) applied to the Codec. +- clocks : Reference to the master clock +- clock-names : The clock should be named "mclk" +- Either codec-clock-rate or the codec-clock reference has to be defined. If + the both are defined the driver attempts to set referenced clock to the + defined rate and takes the rate from the clock reference. + Board connectors: * Headphone Jack diff --git a/Documentation/devicetree/bindings/sound/eukrea-tlv320.txt b/Documentation/devicetree/bindings/sound/eukrea-tlv320.txt new file mode 100644 index 00000000000..0d7985c864a --- /dev/null +++ b/Documentation/devicetree/bindings/sound/eukrea-tlv320.txt @@ -0,0 +1,21 @@ +Audio complex for Eukrea boards with tlv320aic23 codec. + +Required properties: +- compatible : "eukrea,asoc-tlv320" +- eukrea,model : The user-visible name of this sound complex. +- ssi-controller : The phandle of the SSI controller. +- fsl,mux-int-port : The internal port of the i.MX audio muxer (AUDMUX). +- fsl,mux-ext-port : The external port of the i.MX audio muxer. + +Note: The AUDMUX port numbering should start at 1, which is consistent with +hardware manual. + +Example: + + sound { + compatible = "eukrea,asoc-tlv320"; + eukrea,model = "imx51-eukrea-tlv320aic23"; + ssi-controller = <&ssi2>; + fsl,mux-int-port = <2>; + fsl,mux-ext-port = <3>; + }; diff --git a/Documentation/devicetree/bindings/sound/fsl,esai.txt b/Documentation/devicetree/bindings/sound/fsl,esai.txt index d7b99fa637b..aeb8c4a0b88 100644 --- a/Documentation/devicetree/bindings/sound/fsl,esai.txt +++ b/Documentation/devicetree/bindings/sound/fsl,esai.txt @@ -34,6 +34,10 @@ Required properties: that ESAI would work in the synchronous mode, which means all the settings for Receiving would be duplicated from Transmition related registers. + - big-endian : If this property is absent, the native endian mode will + be in use as default, or the big endian mode will be in use for all the + device registers. + Example: esai: esai@02024000 { @@ -46,5 +50,6 @@ esai: esai@02024000 { dma-names = "rx", "tx"; fsl,fifo-depth = <128>; fsl,esai-synchronous; + big-endian; status = "disabled"; }; diff --git a/Documentation/devicetree/bindings/sound/fsl,spdif.txt b/Documentation/devicetree/bindings/sound/fsl,spdif.txt index f2ae335670f..3e9e82c8eab 100644 --- a/Documentation/devicetree/bindings/sound/fsl,spdif.txt +++ b/Documentation/devicetree/bindings/sound/fsl,spdif.txt @@ -29,6 +29,10 @@ Required properties: can also be referred to TxClk_Source bit of register SPDIF_STC. + - big-endian : If this property is absent, the native endian mode will + be in use as default, or the big endian mode will be in use for all the + device registers. + Example: spdif: spdif@02004000 { @@ -50,5 +54,6 @@ spdif: spdif@02004000 { "rxtx5", "rxtx6", "rxtx7"; + big-endian; status = "okay"; }; diff --git a/Documentation/devicetree/bindings/sound/mvebu-audio.txt b/Documentation/devicetree/bindings/sound/mvebu-audio.txt index f0062c5871b..cb8c07c81ce 100644 --- a/Documentation/devicetree/bindings/sound/mvebu-audio.txt +++ b/Documentation/devicetree/bindings/sound/mvebu-audio.txt @@ -5,6 +5,7 @@ Required properties: - compatible: "marvell,kirkwood-audio" for Kirkwood platforms "marvell,dove-audio" for Dove platforms + "marvell,armada370-audio" for Armada 370 platforms - reg: physical base address of the controller and length of memory mapped region. diff --git a/Documentation/devicetree/bindings/sound/pcm512x.txt b/Documentation/devicetree/bindings/sound/pcm512x.txt new file mode 100644 index 00000000000..faff75e6457 --- /dev/null +++ b/Documentation/devicetree/bindings/sound/pcm512x.txt @@ -0,0 +1,30 @@ +PCM512x audio CODECs + +These devices support both I2C and SPI (configured with pin strapping +on the board). + +Required properties: + + - compatible : One of "ti,pcm5121" or "ti,pcm5122" + + - reg : the I2C address of the device for I2C, the chip select + number for SPI. + + - AVDD-supply, DVDD-supply, and CPVDD-supply : power supplies for the + device, as covered in bindings/regulator/regulator.txt + +Optional properties: + + - clocks : A clock specifier for the clock connected as SCLK. If this + is absent the device will be configured to clock from BCLK. + +Example: + + pcm5122: pcm5122@4c { + compatible = "ti,pcm5122"; + reg = <0x4c>; + + AVDD-supply = <®_3v3_analog>; + DVDD-supply = <®_1v8>; + CPVDD-supply = <®_3v3>; + }; diff --git a/Documentation/devicetree/bindings/sound/renesas,rsnd.txt b/Documentation/devicetree/bindings/sound/renesas,rsnd.txt new file mode 100644 index 00000000000..a44e9179faf --- /dev/null +++ b/Documentation/devicetree/bindings/sound/renesas,rsnd.txt @@ -0,0 +1,105 @@ +Renesas R-Car sound + +Required properties: +- compatible : "renesas,rcar_sound-gen1" if generation1 + "renesas,rcar_sound-gen2" if generation2 +- reg : Should contain the register physical address. + required register is + SRU/ADG/SSI if generation1 + SRU/ADG/SSIU/SSI if generation2 +- rcar_sound,ssi : Should contain SSI feature. + The number of SSI subnode should be same as HW. + see below for detail. +- rcar_sound,src : Should contain SRC feature. + The number of SRC subnode should be same as HW. + see below for detail. +- rcar_sound,dai : DAI contents. + The number of DAI subnode should be same as HW. + see below for detail. + +SSI subnode properties: +- interrupts : Should contain SSI interrupt for PIO transfer +- shared-pin : if shared clock pin + +SRC subnode properties: +no properties at this point + +DAI subnode properties: +- playback : list of playback modules +- capture : list of capture modules + +Example: + +rcar_sound: rcar_sound@0xffd90000 { + #sound-dai-cells = <1>; + compatible = "renesas,rcar_sound-gen2"; + reg = <0 0xec500000 0 0x1000>, /* SCU */ + <0 0xec5a0000 0 0x100>, /* ADG */ + <0 0xec540000 0 0x1000>, /* SSIU */ + <0 0xec541000 0 0x1280>; /* SSI */ + + rcar_sound,src { + src0: src@0 { }; + src1: src@1 { }; + src2: src@2 { }; + src3: src@3 { }; + src4: src@4 { }; + src5: src@5 { }; + src6: src@6 { }; + src7: src@7 { }; + src8: src@8 { }; + src9: src@9 { }; + }; + + rcar_sound,ssi { + ssi0: ssi@0 { + interrupts = <0 370 IRQ_TYPE_LEVEL_HIGH>; + }; + ssi1: ssi@1 { + interrupts = <0 371 IRQ_TYPE_LEVEL_HIGH>; + }; + ssi2: ssi@2 { + interrupts = <0 372 IRQ_TYPE_LEVEL_HIGH>; + }; + ssi3: ssi@3 { + interrupts = <0 373 IRQ_TYPE_LEVEL_HIGH>; + }; + ssi4: ssi@4 { + interrupts = <0 374 IRQ_TYPE_LEVEL_HIGH>; + }; + ssi5: ssi@5 { + interrupts = <0 375 IRQ_TYPE_LEVEL_HIGH>; + }; + ssi6: ssi@6 { + interrupts = <0 376 IRQ_TYPE_LEVEL_HIGH>; + }; + ssi7: ssi@7 { + interrupts = <0 377 IRQ_TYPE_LEVEL_HIGH>; + }; + ssi8: ssi@8 { + interrupts = <0 378 IRQ_TYPE_LEVEL_HIGH>; + }; + ssi9: ssi@9 { + interrupts = <0 379 IRQ_TYPE_LEVEL_HIGH>; + }; + }; + + rcar_sound,dai { + dai0 { + playback = <&ssi5 &src5>; + capture = <&ssi6>; + }; + dai1 { + playback = <&ssi3>; + }; + dai2 { + capture = <&ssi4>; + }; + dai3 { + playback = <&ssi7>; + }; + dai4 { + capture = <&ssi8>; + }; + }; +}; diff --git a/Documentation/devicetree/bindings/sound/simple-card.txt b/Documentation/devicetree/bindings/sound/simple-card.txt index 19c84df5fff..131aa2ad7f1 100644 --- a/Documentation/devicetree/bindings/sound/simple-card.txt +++ b/Documentation/devicetree/bindings/sound/simple-card.txt @@ -8,16 +8,26 @@ Required properties: Optional properties: +- simple-audio-card,name : User specified audio sound card name, one string + property. - simple-audio-card,format : CPU/CODEC common audio format. "i2s", "right_j", "left_j" , "dsp_a" "dsp_b", "ac97", "pdm", "msb", "lsb" +- simple-audio-card,widgets : Please refer to widgets.txt. - simple-audio-card,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. +- dai-tdm-slot-num : Please refer to tdm-slot.txt. +- dai-tdm-slot-width : Please refer to tdm-slot.txt. Required subnodes: +- simple-audio-card,dai-link : container for the CPU and CODEC sub-nodes + This container may be omitted when the + card has only one DAI link. + See the examples. + - simple-audio-card,cpu : CPU sub-node - simple-audio-card,codec : CODEC sub-node @@ -38,15 +48,29 @@ Optional CPU/CODEC subnodes properties: clock node (= common clock), or "system-clock-frequency" (if system doens't support common clock) -Example: +Note: + * For 'format', 'frame-master', 'bitclock-master', 'bitclock-inversion' and + 'frame-inversion', the simple card will use the settings of CODEC for both + CPU and CODEC sides as we need to keep the settings identical for both ends + of the link. + +Example 1 - single DAI link: sound { compatible = "simple-audio-card"; + simple-audio-card,name = "VF610-Tower-Sound-Card"; simple-audio-card,format = "left_j"; + simple-audio-card,widgets = + "Microphone", "Microphone Jack", + "Headphone", "Headphone Jack", + "Speaker", "External Speaker"; simple-audio-card,routing = - "MIC_IN", "Mic Jack", + "MIC_IN", "Microphone Jack", "Headphone Jack", "HP_OUT", - "Ext Spk", "LINE_OUT"; + "External Speaker", "LINE_OUT"; + + dai-tdm-slot-num = <2>; + dai-tdm-slot-width = <8>; simple-audio-card,cpu { sound-dai = <&sh_fsi2 0>; @@ -75,3 +99,38 @@ sh_fsi2: sh_fsi2@ec230000 { interrupt-parent = <&gic>; interrupts = <0 146 0x4>; }; + +Example 2 - many DAI links: + +sound { + compatible = "simple-audio-card"; + simple-audio-card,name = "Cubox Audio"; + simple-audio-card,format = "i2s"; + + simple-audio-card,dai-link@0 { /* I2S - HDMI */ + simple-audio-card,cpu { + sound-dai = <&audio1 0>; + }; + simple-audio-card,codec { + sound-dai = <&tda998x 0>; + }; + }; + + simple-audio-card,dai-link@1 { /* S/PDIF - HDMI */ + simple-audio-card,cpu { + sound-dai = <&audio1 1>; + }; + simple-audio-card,codec { + sound-dai = <&tda998x 1>; + }; + }; + + simple-audio-card,dai-link@2 { /* S/PDIF - S/PDIF */ + simple-audio-card,cpu { + sound-dai = <&audio1 1>; + }; + simple-audio-card,codec { + sound-dai = <&spdif_codec>; + }; + }; +}; diff --git a/Documentation/devicetree/bindings/sound/sirf-audio-codec.txt b/Documentation/devicetree/bindings/sound/sirf-audio-codec.txt new file mode 100644 index 00000000000..062f5ec36f9 --- /dev/null +++ b/Documentation/devicetree/bindings/sound/sirf-audio-codec.txt @@ -0,0 +1,17 @@ +SiRF internal audio CODEC + +Required properties: + + - compatible : "sirf,atlas6-audio-codec" or "sirf,prima2-audio-codec" + + - reg : the register address of the device. + + - clocks: the clock of SiRF internal audio codec + +Example: + +audiocodec: audiocodec@b0040000 { + compatible = "sirf,atlas6-audio-codec"; + reg = <0xb0040000 0x10000>; + clocks = <&clks 27>; +}; diff --git a/Documentation/devicetree/bindings/sound/sirf-audio-port.txt b/Documentation/devicetree/bindings/sound/sirf-audio-port.txt new file mode 100644 index 00000000000..1f66de3c8f0 --- /dev/null +++ b/Documentation/devicetree/bindings/sound/sirf-audio-port.txt @@ -0,0 +1,20 @@ +* SiRF SoC audio port + +Required properties: +- compatible: "sirf,audio-port" +- reg: Base address and size entries: +- dmas: List of DMA controller phandle and DMA request line ordered pairs. +- dma-names: Identifier string for each DMA request line in the dmas property. + These strings correspond 1:1 with the ordered pairs in dmas. + + One of the DMA channels will be responsible for transmission (should be + named "tx") and one for reception (should be named "rx"). + +Example: + +audioport: audioport@b0040000 { + compatible = "sirf,audio-port"; + reg = <0xb0040000 0x10000>; + dmas = <&dmac1 3>, <&dmac1 8>; + dma-names = "rx", "tx"; +}; diff --git a/Documentation/devicetree/bindings/sound/sirf-audio.txt b/Documentation/devicetree/bindings/sound/sirf-audio.txt new file mode 100644 index 00000000000..c88882ca370 --- /dev/null +++ b/Documentation/devicetree/bindings/sound/sirf-audio.txt @@ -0,0 +1,41 @@ +* SiRF atlas6 and prima2 internal audio codec and port based audio setups + +Required properties: +- compatible: "sirf,sirf-audio-card" +- sirf,audio-platform: phandle for the platform node +- sirf,audio-codec: phandle for the SiRF internal codec node + +Optional properties: +- hp-pa-gpios: Need to be present if the board need control external + headphone amplifier. +- spk-pa-gpios: Need to be present if the board need control external + speaker amplifier. +- hp-switch-gpios: Need to be present if the board capable to detect jack + insertion, removal. + +Available audio endpoints for the audio-routing table: + +Board connectors: + * Headset Stereophone + * Ext Spk + * Line In + * Mic + +SiRF internal audio codec pins: + * HPOUTL + * HPOUTR + * SPKOUT + * Ext Mic + * Mic Bias + +Example: + +sound { + compatible = "sirf,sirf-audio-card"; + sirf,audio-codec = <&audiocodec>; + sirf,audio-platform = <&audioport>; + hp-pa-gpios = <&gpio 44 0>; + spk-pa-gpios = <&gpio 46 0>; + hp-switch-gpios = <&gpio 45 0>; +}; + diff --git a/Documentation/devicetree/bindings/sound/tdm-slot.txt b/Documentation/devicetree/bindings/sound/tdm-slot.txt new file mode 100644 index 00000000000..6a2c84247f9 --- /dev/null +++ b/Documentation/devicetree/bindings/sound/tdm-slot.txt @@ -0,0 +1,20 @@ +TDM slot: + +This specifies audio DAI's TDM slot. + +TDM slot properties: +dai-tdm-slot-num : Number of slots in use. +dai-tdm-slot-width : Width in bits for each slot. + +For instance: + dai-tdm-slot-num = <2>; + dai-tdm-slot-width = <8>; + +And for each spcified driver, there could be one .of_xlate_tdm_slot_mask() +to specify a explicit mapping of the channels and the slots. If it's absent +the default snd_soc_of_xlate_tdm_slot_mask() will be used to generating the +tx and rx masks. + +For snd_soc_of_xlate_tdm_slot_mask(), the tx and rx masks will use a 1 bit +for an active slot as default, and the default active bits are at the LSB of +the masks. diff --git a/Documentation/devicetree/bindings/sound/tlv320aic31xx.txt b/Documentation/devicetree/bindings/sound/tlv320aic31xx.txt new file mode 100644 index 00000000000..74c66dee3e1 --- /dev/null +++ b/Documentation/devicetree/bindings/sound/tlv320aic31xx.txt @@ -0,0 +1,61 @@ +Texas Instruments - tlv320aic31xx Codec module + +The tlv320aic31xx serial control bus communicates through I2C protocols + +Required properties: + +- compatible - "string" - One of: + "ti,tlv320aic310x" - Generic TLV320AIC31xx with mono speaker amp + "ti,tlv320aic311x" - Generic TLV320AIC31xx with stereo speaker amp + "ti,tlv320aic3100" - TLV320AIC3100 (mono speaker amp, no MiniDSP) + "ti,tlv320aic3110" - TLV320AIC3110 (stereo speaker amp, no MiniDSP) + "ti,tlv320aic3120" - TLV320AIC3120 (mono speaker amp, MiniDSP) + "ti,tlv320aic3111" - TLV320AIC3111 (stereo speaker amp, MiniDSP) + +- reg - <int> - I2C slave address + + +Optional properties: + +- gpio-reset - gpio pin number used for codec reset +- ai31xx-micbias-vg - MicBias Voltage setting + 1 or MICBIAS_2_0V - MICBIAS output is powered to 2.0V + 2 or MICBIAS_2_5V - MICBIAS output is powered to 2.5V + 3 or MICBIAS_AVDD - MICBIAS output is connected to AVDD + If this node is not mentioned or if the value is unknown, then + micbias is set to 2.0V. +- HPVDD-supply, SPRVDD-supply, SPLVDD-supply, AVDD-supply, IOVDD-supply, + DVDD-supply : power supplies for the device as covered in + Documentation/devicetree/bindings/regulator/regulator.txt + +CODEC output pins: + * HPL + * HPR + * SPL, devices with stereo speaker amp + * SPR, devices with stereo speaker amp + * SPK, devices with mono speaker amp + * MICBIAS + +CODEC input pins: + * MIC1LP + * MIC1RP + * MIC1LM + +The pins can be used in referring sound node's audio-routing property. + +Example: +#include <dt-bindings/sound/tlv320aic31xx-micbias.h> + +tlv320aic31xx: tlv320aic31xx@18 { + compatible = "ti,tlv320aic311x"; + reg = <0x18>; + + ai31xx-micbias-vg = <MICBIAS_OFF>; + + HPVDD-supply = <®ulator>; + SPRVDD-supply = <®ulator>; + SPLVDD-supply = <®ulator>; + AVDD-supply = <®ulator>; + IOVDD-supply = <®ulator>; + DVDD-supply = <®ulator>; +}; diff --git a/Documentation/devicetree/bindings/sound/tlv320aic32x4.txt b/Documentation/devicetree/bindings/sound/tlv320aic32x4.txt new file mode 100644 index 00000000000..5e2741af27b --- /dev/null +++ b/Documentation/devicetree/bindings/sound/tlv320aic32x4.txt @@ -0,0 +1,30 @@ +Texas Instruments - tlv320aic32x4 Codec module + +The tlv320aic32x4 serial control bus communicates through I2C protocols + +Required properties: + - compatible: Should be "ti,tlv320aic32x4" + - reg: I2C slave address + - supply-*: Required supply regulators are: + "iov" - digital IO power supply + "ldoin" - LDO power supply + "dv" - Digital core power supply + "av" - Analog core power supply + If you supply ldoin, dv and av are optional. Otherwise they are required + See regulator/regulator.txt for more information about the detailed binding + format. + +Optional properties: + - reset-gpios: Reset-GPIO phandle with args as described in gpio/gpio.txt + - clocks/clock-names: Clock named 'mclk' for the master clock of the codec. + See clock/clock-bindings.txt for information about the detailed format. + + +Example: + +codec: tlv320aic32x4@18 { + compatible = "ti,tlv320aic32x4"; + reg = <0x18>; + clocks = <&clks 201>; + clock-names = "mclk"; +}; diff --git a/Documentation/devicetree/bindings/sound/tlv320aic3x.txt b/Documentation/devicetree/bindings/sound/tlv320aic3x.txt index 9d8ea14db49..5e6040c2c2e 100644 --- a/Documentation/devicetree/bindings/sound/tlv320aic3x.txt +++ b/Documentation/devicetree/bindings/sound/tlv320aic3x.txt @@ -6,7 +6,6 @@ Required properties: - compatible - "string" - One of: "ti,tlv320aic3x" - Generic TLV320AIC3x device - "ti,tlv320aic32x4" - TLV320AIC32x4 "ti,tlv320aic33" - TLV320AIC33 "ti,tlv320aic3007" - TLV320AIC3007 "ti,tlv320aic3106" - TLV320AIC3106 diff --git a/Documentation/devicetree/bindings/sound/widgets.txt b/Documentation/devicetree/bindings/sound/widgets.txt new file mode 100644 index 00000000000..b6de5ba3b2d --- /dev/null +++ b/Documentation/devicetree/bindings/sound/widgets.txt @@ -0,0 +1,20 @@ +Widgets: + +This mainly specifies audio off-codec DAPM widgets. + +Each entry is a pair of strings in DT: + + "template-wname", "user-supplied-wname" + +The "template-wname" being the template widget name and currently includes: +"Microphone", "Line", "Headphone" and "Speaker". + +The "user-supplied-wname" being the user specified widget name. + +For instance: + simple-audio-widgets = + "Microphone", "Microphone Jack", + "Line", "Line In Jack", + "Line", "Line Out Jack", + "Headphone", "Headphone Jack", + "Speaker", "Speaker External"; diff --git a/MAINTAINERS b/MAINTAINERS index 5fe2c0d6612..c7ded020e64 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -2204,6 +2204,13 @@ L: alsa-devel@alsa-project.org (moderated for non-subscribers) S: Odd Fixes F: sound/soc/codecs/cs4270* +CIRRUS LOGIC AUDIO CODEC DRIVERS +M: Brian Austin <brian.austin@cirrus.com> +M: Paul Handrigan <Paul.Handrigan@cirrus.com> +L: alsa-devel@alsa-project.org (moderated for non-subscribers) +S: Maintained +F: sound/soc/codecs/cs* + CLEANCACHE API M: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com> L: linux-kernel@vger.kernel.org diff --git a/arch/arm/mach-shmobile/board-armadillo800eva.c b/arch/arm/mach-shmobile/board-armadillo800eva.c index 93533e2710a..9323854242c 100644 --- a/arch/arm/mach-shmobile/board-armadillo800eva.c +++ b/arch/arm/mach-shmobile/board-armadillo800eva.c @@ -988,14 +988,12 @@ static struct asoc_simple_card_info fsi_wm8978_info = { .card = "FSI2A-WM8978", .codec = "wm8978.0-001a", .platform = "sh_fsi2", - .daifmt = SND_SOC_DAIFMT_I2S, + .daifmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_CBM_CFM, .cpu_dai = { .name = "fsia-dai", - .fmt = SND_SOC_DAIFMT_CBS_CFS | SND_SOC_DAIFMT_IB_NF, }, .codec_dai = { .name = "wm8978-hifi", - .fmt = SND_SOC_DAIFMT_CBM_CFM | SND_SOC_DAIFMT_NB_NF, .sysclk = 12288000, }, }; diff --git a/arch/arm/mach-shmobile/board-bockw.c b/arch/arm/mach-shmobile/board-bockw.c index c475220545f..74c27d9d690 100644 --- a/arch/arm/mach-shmobile/board-bockw.c +++ b/arch/arm/mach-shmobile/board-bockw.c @@ -429,14 +429,12 @@ static struct asoc_simple_card_info rsnd_card_info[] = { .card = "SSI56-AK4643", .codec = "ak4642-codec.0-0012", .platform = "rcar_sound", - .daifmt = SND_SOC_DAIFMT_LEFT_J, + .daifmt = SND_SOC_DAIFMT_LEFT_J | SND_SOC_DAIFMT_CBM_CFM, .cpu_dai = { .name = "rsnd-dai.0", - .fmt = SND_SOC_DAIFMT_CBS_CFS, }, .codec_dai = { .name = "ak4642-hifi", - .fmt = SND_SOC_DAIFMT_CBM_CFM, .sysclk = 11289600, }, }, @@ -446,10 +444,9 @@ static struct asoc_simple_card_info rsnd_card_info[] = { .card = "SSI3-AK4554(playback)", .codec = "ak4554-adc-dac.0", .platform = "rcar_sound", + .daifmt = SND_SOC_DAIFMT_CBS_CFS | SND_SOC_DAIFMT_RIGHT_J, .cpu_dai = { .name = "rsnd-dai.1", - .fmt = SND_SOC_DAIFMT_CBM_CFM | - SND_SOC_DAIFMT_RIGHT_J, }, .codec_dai = { .name = "ak4554-hifi", @@ -461,10 +458,9 @@ static struct asoc_simple_card_info rsnd_card_info[] = { .card = "SSI4-AK4554(capture)", .codec = "ak4554-adc-dac.0", .platform = "rcar_sound", + .daifmt = SND_SOC_DAIFMT_CBS_CFS | SND_SOC_DAIFMT_LEFT_J, .cpu_dai = { .name = "rsnd-dai.2", - .fmt = SND_SOC_DAIFMT_CBM_CFM | - SND_SOC_DAIFMT_LEFT_J, }, .codec_dai = { .name = "ak4554-hifi", @@ -476,10 +472,9 @@ static struct asoc_simple_card_info rsnd_card_info[] = { .card = "SSI7-AK4554(playback)", .codec = "ak4554-adc-dac.1", .platform = "rcar_sound", + .daifmt = SND_SOC_DAIFMT_CBS_CFS | SND_SOC_DAIFMT_RIGHT_J, .cpu_dai = { .name = "rsnd-dai.3", - .fmt = SND_SOC_DAIFMT_CBM_CFM | - SND_SOC_DAIFMT_RIGHT_J, }, .codec_dai = { .name = "ak4554-hifi", @@ -491,10 +486,9 @@ static struct asoc_simple_card_info rsnd_card_info[] = { .card = "SSI8-AK4554(capture)", .codec = "ak4554-adc-dac.1", .platform = "rcar_sound", + .daifmt = SND_SOC_DAIFMT_CBS_CFS | SND_SOC_DAIFMT_LEFT_J, .cpu_dai = { .name = "rsnd-dai.4", - .fmt = SND_SOC_DAIFMT_CBM_CFM | - SND_SOC_DAIFMT_LEFT_J, }, .codec_dai = { .name = "ak4554-hifi", diff --git a/arch/arm/mach-shmobile/board-kzm9g.c b/arch/arm/mach-shmobile/board-kzm9g.c index bc40b853ffd..03dc3ac8450 100644 --- a/arch/arm/mach-shmobile/board-kzm9g.c +++ b/arch/arm/mach-shmobile/board-kzm9g.c @@ -589,14 +589,12 @@ static struct asoc_simple_card_info fsi2_ak4648_info = { .card = "FSI2A-AK4648", .codec = "ak4642-codec.0-0012", .platform = "sh_fsi2", - .daifmt = SND_SOC_DAIFMT_LEFT_J, + .daifmt = SND_SOC_DAIFMT_LEFT_J | SND_SOC_DAIFMT_CBM_CFM, .cpu_dai = { .name = "fsia-dai", - .fmt = SND_SOC_DAIFMT_CBS_CFS, }, .codec_dai = { .name = "ak4642-hifi", - .fmt = SND_SOC_DAIFMT_CBM_CFM, .sysclk = 11289600, }, }; diff --git a/arch/arm/mach-shmobile/board-mackerel.c b/arch/arm/mach-shmobile/board-mackerel.c index 3aba0372f63..0ff4d8e45cf 100644 --- a/arch/arm/mach-shmobile/board-mackerel.c +++ b/arch/arm/mach-shmobile/board-mackerel.c @@ -509,9 +509,9 @@ static struct asoc_simple_card_info fsi2_hdmi_info = { .card = "FSI2B-HDMI", .codec = "sh-mobile-hdmi", .platform = "sh_fsi2", + .daifmt = SND_SOC_DAIFMT_CBS_CFS, .cpu_dai = { .name = "fsib-dai", - .fmt = SND_SOC_DAIFMT_CBM_CFM | SND_SOC_DAIFMT_IB_NF, }, .codec_dai = { .name = "sh_mobile_hdmi-hifi", @@ -905,14 +905,12 @@ static struct asoc_simple_card_info fsi2_ak4643_info = { .card = "FSI2A-AK4643", .codec = "ak4642-codec.0-0013", .platform = "sh_fsi2", - .daifmt = SND_SOC_DAIFMT_LEFT_J, + .daifmt = SND_SOC_DAIFMT_LEFT_J | SND_SOC_DAIFMT_CBM_CFM, .cpu_dai = { .name = "fsia-dai", - .fmt = SND_SOC_DAIFMT_CBS_CFS, }, .codec_dai = { .name = "ak4642-hifi", - .fmt = SND_SOC_DAIFMT_CBM_CFM, .sysclk = 11289600, }, }; diff --git a/arch/sh/boards/mach-ecovec24/setup.c b/arch/sh/boards/mach-ecovec24/setup.c index 5bc3a15465c..85d5255d259 100644 --- a/arch/sh/boards/mach-ecovec24/setup.c +++ b/arch/sh/boards/mach-ecovec24/setup.c @@ -861,14 +861,12 @@ static struct asoc_simple_card_info fsi_da7210_info = { .card = "FSIB-DA7210", .codec = "da7210.0-001a", .platform = "sh_fsi.0", - .daifmt = SND_SOC_DAIFMT_I2S, + .daifmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_CBM_CFM, .cpu_dai = { .name = "fsib-dai", - .fmt = SND_SOC_DAIFMT_CBS_CFS | SND_SOC_DAIFMT_IB_NF, }, .codec_dai = { .name = "da7210-hifi", - .fmt = SND_SOC_DAIFMT_CBM_CFM, }, }; diff --git a/arch/sh/boards/mach-se/7724/setup.c b/arch/sh/boards/mach-se/7724/setup.c index 21e4230659a..1162bc6945a 100644 --- a/arch/sh/boards/mach-se/7724/setup.c +++ b/arch/sh/boards/mach-se/7724/setup.c @@ -304,14 +304,12 @@ static struct asoc_simple_card_info fsi_ak4642_info = { .card = "FSIA-AK4642", .codec = "ak4642-codec.0-0012", .platform = "sh_fsi.0", - .daifmt = SND_SOC_DAIFMT_LEFT_J, + .daifmt = SND_SOC_DAIFMT_LEFT_J | SND_SOC_DAIFMT_CBM_CFM, .cpu_dai = { .name = "fsia-dai", - .fmt = SND_SOC_DAIFMT_CBS_CFS | SND_SOC_DAIFMT_IB_NF, }, .codec_dai = { .name = "ak4642-hifi", - .fmt = SND_SOC_DAIFMT_CBM_CFM, .sysclk = 11289600, }, }; diff --git a/drivers/hid/hid-prodikeys.c b/drivers/hid/hid-prodikeys.c index 7ed82805641..91fab975063 100644 --- a/drivers/hid/hid-prodikeys.c +++ b/drivers/hid/hid-prodikeys.c @@ -624,7 +624,8 @@ static int pcmidi_snd_initialise(struct pcmidi_snd *pm) /* Setup sound card */ - err = snd_card_create(index[dev], id[dev], THIS_MODULE, 0, &card); + err = snd_card_new(&pm->pk->hdev->dev, index[dev], id[dev], + THIS_MODULE, 0, &card); if (err < 0) { pk_error("failed to create pc-midi sound card\n"); err = -ENOMEM; @@ -660,8 +661,6 @@ static int pcmidi_snd_initialise(struct pcmidi_snd *pm) snd_rawmidi_set_ops(rwmidi, SNDRV_RAWMIDI_STREAM_INPUT, &pcmidi_in_ops); - snd_card_set_dev(card, &pm->pk->hdev->dev); - /* create sysfs variables */ err = device_create_file(&pm->pk->hdev->dev, sysfs_device_attr_channel); diff --git a/drivers/media/pci/cx18/cx18-alsa-main.c b/drivers/media/pci/cx18/cx18-alsa-main.c index b2c8c3439fe..ea272bcb38d 100644 --- a/drivers/media/pci/cx18/cx18-alsa-main.c +++ b/drivers/media/pci/cx18/cx18-alsa-main.c @@ -145,11 +145,12 @@ static int snd_cx18_init(struct v4l2_device *v4l2_dev) /* This is a no-op for us. We'll use the cx->instance */ /* (2) Create a card instance */ - ret = snd_card_create(SNDRV_DEFAULT_IDX1, /* use first available id */ - SNDRV_DEFAULT_STR1, /* xid from end of shortname*/ - THIS_MODULE, 0, &sc); + ret = snd_card_new(&cx->pci_dev->dev, + SNDRV_DEFAULT_IDX1, /* use first available id */ + SNDRV_DEFAULT_STR1, /* xid from end of shortname*/ + THIS_MODULE, 0, &sc); if (ret) { - CX18_ALSA_ERR("%s: snd_card_create() failed with err %d\n", + CX18_ALSA_ERR("%s: snd_card_new() failed with err %d\n", __func__, ret); goto err_exit; } diff --git a/drivers/media/pci/cx23885/cx23885-alsa.c b/drivers/media/pci/cx23885/cx23885-alsa.c index c6c9bd58f8b..554798dcedd 100644 --- a/drivers/media/pci/cx23885/cx23885-alsa.c +++ b/drivers/media/pci/cx23885/cx23885-alsa.c @@ -489,7 +489,8 @@ struct cx23885_audio_dev *cx23885_audio_register(struct cx23885_dev *dev) return NULL; } - err = snd_card_create(SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1, + err = snd_card_new(&dev->pci->dev, + SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1, THIS_MODULE, sizeof(struct cx23885_audio_dev), &card); if (err < 0) goto error; @@ -500,8 +501,6 @@ struct cx23885_audio_dev *cx23885_audio_register(struct cx23885_dev *dev) chip->card = card; spin_lock_init(&chip->lock); - snd_card_set_dev(card, &dev->pci->dev); - err = snd_cx23885_pcm(chip, 0, "CX23885 Digital"); if (err < 0) goto error; diff --git a/drivers/media/pci/cx25821/cx25821-alsa.c b/drivers/media/pci/cx25821/cx25821-alsa.c index b1e08c3e55c..2dd5bcaa7e5 100644 --- a/drivers/media/pci/cx25821/cx25821-alsa.c +++ b/drivers/media/pci/cx25821/cx25821-alsa.c @@ -645,8 +645,9 @@ static int cx25821_audio_initdev(struct cx25821_dev *dev) return -ENOENT; } - err = snd_card_create(index[devno], id[devno], THIS_MODULE, - sizeof(struct cx25821_audio_dev), &card); + err = snd_card_new(&dev->pci->dev, index[devno], id[devno], + THIS_MODULE, + sizeof(struct cx25821_audio_dev), &card); if (err < 0) { pr_info("DEBUG ERROR: cannot create snd_card_new in %s\n", __func__); @@ -682,8 +683,6 @@ static int cx25821_audio_initdev(struct cx25821_dev *dev) goto error; } - snd_card_set_dev(card, &chip->pci->dev); - strcpy(card->shortname, "cx25821"); sprintf(card->longname, "%s at 0x%lx irq %d", chip->dev->name, chip->iobase, chip->irq); diff --git a/drivers/media/pci/cx88/cx88-alsa.c b/drivers/media/pci/cx88/cx88-alsa.c index d014206e717..a72579a9f67 100644 --- a/drivers/media/pci/cx88/cx88-alsa.c +++ b/drivers/media/pci/cx88/cx88-alsa.c @@ -852,8 +852,6 @@ static int snd_cx88_create(struct snd_card *card, struct pci_dev *pci, chip->irq = pci->irq; synchronize_irq(chip->irq); - snd_card_set_dev(card, &pci->dev); - *rchip = chip; *core_ptr = core; @@ -876,8 +874,8 @@ static int cx88_audio_initdev(struct pci_dev *pci, return (-ENOENT); } - err = snd_card_create(index[devno], id[devno], THIS_MODULE, - sizeof(snd_cx88_card_t), &card); + err = snd_card_new(&pci->dev, index[devno], id[devno], THIS_MODULE, + sizeof(snd_cx88_card_t), &card); if (err < 0) return err; diff --git a/drivers/media/pci/ivtv/ivtv-alsa-main.c b/drivers/media/pci/ivtv/ivtv-alsa-main.c index e970cface70..39b52929755 100644 --- a/drivers/media/pci/ivtv/ivtv-alsa-main.c +++ b/drivers/media/pci/ivtv/ivtv-alsa-main.c @@ -145,11 +145,12 @@ static int snd_ivtv_init(struct v4l2_device *v4l2_dev) /* This is a no-op for us. We'll use the itv->instance */ /* (2) Create a card instance */ - ret = snd_card_create(SNDRV_DEFAULT_IDX1, /* use first available id */ - SNDRV_DEFAULT_STR1, /* xid from end of shortname*/ - THIS_MODULE, 0, &sc); + ret = snd_card_new(&itv->pdev->dev, + SNDRV_DEFAULT_IDX1, /* use first available id */ + SNDRV_DEFAULT_STR1, /* xid from end of shortname*/ + THIS_MODULE, 0, &sc); if (ret) { - IVTV_ALSA_ERR("%s: snd_card_create() failed with err %d\n", + IVTV_ALSA_ERR("%s: snd_card_new() failed with err %d\n", __func__, ret); goto err_exit; } diff --git a/drivers/media/pci/saa7134/saa7134-alsa.c b/drivers/media/pci/saa7134/saa7134-alsa.c index dd67c8a400c..e04a4d5d667 100644 --- a/drivers/media/pci/saa7134/saa7134-alsa.c +++ b/drivers/media/pci/saa7134/saa7134-alsa.c @@ -1072,8 +1072,8 @@ static int alsa_card_saa7134_create(struct saa7134_dev *dev, int devnum) if (!enable[devnum]) return -ENODEV; - err = snd_card_create(index[devnum], id[devnum], THIS_MODULE, - sizeof(snd_card_saa7134_t), &card); + err = snd_card_new(&dev->pci->dev, index[devnum], id[devnum], + THIS_MODULE, sizeof(snd_card_saa7134_t), &card); if (err < 0) return err; @@ -1115,8 +1115,6 @@ static int alsa_card_saa7134_create(struct saa7134_dev *dev, int devnum) if ((err = snd_card_saa7134_pcm(chip, 0)) < 0) goto __nodev; - snd_card_set_dev(card, &chip->pci->dev); - /* End of "creation" */ strcpy(card->shortname, "SAA7134"); diff --git a/drivers/media/usb/cx231xx/cx231xx-audio.c b/drivers/media/usb/cx231xx/cx231xx-audio.c index 81a1d971d79..9b925874d39 100644 --- a/drivers/media/usb/cx231xx/cx231xx-audio.c +++ b/drivers/media/usb/cx231xx/cx231xx-audio.c @@ -665,8 +665,8 @@ static int cx231xx_audio_init(struct cx231xx *dev) cx231xx_info("cx231xx-audio.c: probing for cx231xx " "non standard usbaudio\n"); - err = snd_card_create(index[devnr], "Cx231xx Audio", THIS_MODULE, - 0, &card); + err = snd_card_new(&dev->udev->dev, index[devnr], "Cx231xx Audio", + THIS_MODULE, 0, &card); if (err < 0) return err; @@ -682,7 +682,6 @@ static int cx231xx_audio_init(struct cx231xx *dev) pcm->info_flags = 0; pcm->private_data = dev; strcpy(pcm->name, "Conexant cx231xx Capture"); - snd_card_set_dev(card, &dev->udev->dev); strcpy(card->driver, "Cx231xx-Audio"); strcpy(card->shortname, "Cx231xx Audio"); strcpy(card->longname, "Conexant cx231xx Audio"); diff --git a/drivers/media/usb/em28xx/em28xx-audio.c b/drivers/media/usb/em28xx/em28xx-audio.c index 05e9bd11a3f..1a28897af18 100644 --- a/drivers/media/usb/em28xx/em28xx-audio.c +++ b/drivers/media/usb/em28xx/em28xx-audio.c @@ -900,8 +900,8 @@ static int em28xx_audio_init(struct em28xx *dev) printk(KERN_INFO "em28xx-audio.c: Copyright (C) 2007-2014 Mauro Carvalho Chehab\n"); - err = snd_card_create(index[devnr], "Em28xx Audio", THIS_MODULE, 0, - &card); + err = snd_card_new(&dev->udev->dev, index[devnr], "Em28xx Audio", + THIS_MODULE, 0, &card); if (err < 0) return err; @@ -918,7 +918,6 @@ static int em28xx_audio_init(struct em28xx *dev) pcm->private_data = dev; strcpy(pcm->name, "Empia 28xx Capture"); - snd_card_set_dev(card, &dev->udev->dev); strcpy(card->driver, "Em28xx-Audio"); strcpy(card->shortname, "Em28xx Audio"); strcpy(card->longname, "Empia Em28xx Audio"); diff --git a/drivers/media/usb/stk1160/stk1160-ac97.c b/drivers/media/usb/stk1160/stk1160-ac97.c index c8583c262c3..c46c8be8960 100644 --- a/drivers/media/usb/stk1160/stk1160-ac97.c +++ b/drivers/media/usb/stk1160/stk1160-ac97.c @@ -98,13 +98,11 @@ int stk1160_ac97_register(struct stk1160 *dev) * Just want a card to access ac96 controls, * the actual capture interface will be handled by snd-usb-audio */ - rc = snd_card_create(SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1, - THIS_MODULE, 0, &card); + rc = snd_card_new(dev->dev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1, + THIS_MODULE, 0, &card); if (rc < 0) return rc; - snd_card_set_dev(card, dev->dev); - /* TODO: I'm not sure where should I get these names :-( */ snprintf(card->shortname, sizeof(card->shortname), "stk1160-mixer"); diff --git a/drivers/media/usb/tlg2300/pd-alsa.c b/drivers/media/usb/tlg2300/pd-alsa.c index 3f3e141f70f..dd8fe100590 100644 --- a/drivers/media/usb/tlg2300/pd-alsa.c +++ b/drivers/media/usb/tlg2300/pd-alsa.c @@ -300,7 +300,8 @@ int poseidon_audio_init(struct poseidon *p) struct snd_pcm *pcm; int ret; - ret = snd_card_create(-1, "Telegent", THIS_MODULE, 0, &card); + ret = snd_card_new(&p->interface->dev, -1, "Telegent", + THIS_MODULE, 0, &card); if (ret != 0) return ret; diff --git a/drivers/media/usb/tm6000/tm6000-alsa.c b/drivers/media/usb/tm6000/tm6000-alsa.c index 813c1ec5360..3239cd62e45 100644 --- a/drivers/media/usb/tm6000/tm6000-alsa.c +++ b/drivers/media/usb/tm6000/tm6000-alsa.c @@ -431,7 +431,8 @@ static int tm6000_audio_init(struct tm6000_core *dev) if (!enable[devnr]) return -ENOENT; - rc = snd_card_create(index[devnr], "tm6000", THIS_MODULE, 0, &card); + rc = snd_card_new(&dev->udev->dev, index[devnr], "tm6000", + THIS_MODULE, 0, &card); if (rc < 0) { snd_printk(KERN_ERR "cannot create card instance %d\n", devnr); return rc; @@ -445,7 +446,6 @@ static int tm6000_audio_init(struct tm6000_core *dev) le16_to_cpu(dev->udev->descriptor.idVendor), le16_to_cpu(dev->udev->descriptor.idProduct)); snd_component_add(card, component); - snd_card_set_dev(card, &dev->udev->dev); chip = kzalloc(sizeof(struct snd_tm6000_card), GFP_KERNEL); if (!chip) { diff --git a/drivers/misc/atmel-ssc.c b/drivers/misc/atmel-ssc.c index 5be808406ed..22de1372764 100644 --- a/drivers/misc/atmel-ssc.c +++ b/drivers/misc/atmel-ssc.c @@ -150,6 +150,12 @@ static int ssc_probe(struct platform_device *pdev) return -ENODEV; ssc->pdata = (struct atmel_ssc_platform_data *)plat_dat; + if (pdev->dev.of_node) { + struct device_node *np = pdev->dev.of_node; + ssc->clk_from_rk_pin = + of_property_read_bool(np, "atmel,clk-from-rk-pin"); + } + regs = platform_get_resource(pdev, IORESOURCE_MEM, 0); ssc->regs = devm_ioremap_resource(&pdev->dev, regs); if (IS_ERR(ssc->regs)) diff --git a/drivers/platform/x86/thinkpad_acpi.c b/drivers/platform/x86/thinkpad_acpi.c index defb6afc140..94bb6157c95 100644 --- a/drivers/platform/x86/thinkpad_acpi.c +++ b/drivers/platform/x86/thinkpad_acpi.c @@ -6776,8 +6776,9 @@ static int __init volume_create_alsa_mixer(void) struct snd_kcontrol *ctl_mute; int rc; - rc = snd_card_create(alsa_index, alsa_id, THIS_MODULE, - sizeof(struct tpacpi_alsa_data), &card); + rc = snd_card_new(&tpacpi_pdev->dev, + alsa_index, alsa_id, THIS_MODULE, + sizeof(struct tpacpi_alsa_data), &card); if (rc < 0 || !card) { pr_err("Failed to create ALSA card structures: %d\n", rc); return 1; @@ -6828,7 +6829,6 @@ static int __init volume_create_alsa_mixer(void) } data->ctl_mute_id = &ctl_mute->id; - snd_card_set_dev(card, &tpacpi_pdev->dev); rc = snd_card_register(card); if (rc < 0) { pr_err("Failed to register ALSA card: %d\n", rc); diff --git a/drivers/staging/line6/audio.c b/drivers/staging/line6/audio.c index a92e21f7d55..171d80c1b02 100644 --- a/drivers/staging/line6/audio.c +++ b/drivers/staging/line6/audio.c @@ -24,8 +24,9 @@ int line6_init_audio(struct usb_line6 *line6) struct snd_card *card; int err; - err = snd_card_create(SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1, - THIS_MODULE, 0, &card); + err = snd_card_new(line6->ifcdev, + SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1, + THIS_MODULE, 0, &card); if (err < 0) return err; diff --git a/drivers/staging/line6/midi.c b/drivers/staging/line6/midi.c index 3f6d78c585f..c61cd0515ba 100644 --- a/drivers/staging/line6/midi.c +++ b/drivers/staging/line6/midi.c @@ -307,8 +307,6 @@ int line6_init_midi(struct usb_line6 *line6) if (err < 0) return err; - snd_card_set_dev(line6->card, line6->ifcdev); - err = snd_line6_new_midi(line6midi); if (err < 0) return err; diff --git a/drivers/staging/line6/pcm.c b/drivers/staging/line6/pcm.c index df8331bce17..661080b3c39 100644 --- a/drivers/staging/line6/pcm.c +++ b/drivers/staging/line6/pcm.c @@ -501,8 +501,6 @@ int line6_init_pcm(struct usb_line6 *line6, if (err < 0) return err; - snd_card_set_dev(line6->card, line6->ifcdev); - err = snd_line6_new_pcm(line6pcm); if (err < 0) return err; diff --git a/drivers/staging/media/go7007/snd-go7007.c b/drivers/staging/media/go7007/snd-go7007.c index 16dd6492076..9eb2a20ae40 100644 --- a/drivers/staging/media/go7007/snd-go7007.c +++ b/drivers/staging/media/go7007/snd-go7007.c @@ -245,8 +245,8 @@ int go7007_snd_init(struct go7007 *go) spin_lock_init(&gosnd->lock); gosnd->hw_ptr = gosnd->w_idx = gosnd->avail = 0; gosnd->capturing = 0; - ret = snd_card_create(index[dev], id[dev], THIS_MODULE, 0, - &gosnd->card); + ret = snd_card_new(go->dev, index[dev], id[dev], THIS_MODULE, 0, + &gosnd->card); if (ret < 0) { kfree(gosnd); return ret; @@ -257,7 +257,6 @@ int go7007_snd_init(struct go7007 *go) kfree(gosnd); return ret; } - snd_card_set_dev(gosnd->card, go->dev); ret = snd_pcm_new(gosnd->card, "go7007", 0, 0, 1, &gosnd->pcm); if (ret < 0) { snd_card_free(gosnd->card); diff --git a/drivers/staging/media/solo6x10/solo6x10-g723.c b/drivers/staging/media/solo6x10/solo6x10-g723.c index 1db18c7972a..74f037b6166 100644 --- a/drivers/staging/media/solo6x10/solo6x10-g723.c +++ b/drivers/staging/media/solo6x10/solo6x10-g723.c @@ -366,8 +366,9 @@ int solo_g723_init(struct solo_dev *solo_dev) /* Allows for easier mapping between video and audio */ sprintf(name, "Softlogic%d", solo_dev->vfd->num); - ret = snd_card_create(SNDRV_DEFAULT_IDX1, name, THIS_MODULE, 0, - &solo_dev->snd_card); + ret = snd_card_new(&solo_dev->pdev->dev, + SNDRV_DEFAULT_IDX1, name, THIS_MODULE, 0, + &solo_dev->snd_card); if (ret < 0) return ret; @@ -377,7 +378,6 @@ int solo_g723_init(struct solo_dev *solo_dev) strcpy(card->shortname, "SOLO-6x10 Audio"); sprintf(card->longname, "%s on %s IRQ %d", card->shortname, pci_name(solo_dev->pdev), solo_dev->pdev->irq); - snd_card_set_dev(card, &solo_dev->pdev->dev); ret = snd_device_new(card, SNDRV_DEV_LOWLEVEL, solo_dev, &ops); if (ret < 0) diff --git a/drivers/usb/gadget/f_midi.c b/drivers/usb/gadget/f_midi.c index 36d4bb23087..807b31c0edc 100644 --- a/drivers/usb/gadget/f_midi.c +++ b/drivers/usb/gadget/f_midi.c @@ -664,9 +664,10 @@ static int f_midi_register_card(struct f_midi *midi) .dev_free = f_midi_snd_free, }; - err = snd_card_create(midi->index, midi->id, THIS_MODULE, 0, &card); + err = snd_card_new(&midi->gadget->dev, midi->index, midi->id, + THIS_MODULE, 0, &card); if (err < 0) { - ERROR(midi, "snd_card_create() failed\n"); + ERROR(midi, "snd_card_new() failed\n"); goto fail; } midi->card = card; @@ -703,8 +704,6 @@ static int f_midi_register_card(struct f_midi *midi) snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_OUTPUT, &gmidi_in_ops); snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_INPUT, &gmidi_out_ops); - snd_card_set_dev(card, &midi->gadget->dev); - /* register it - we're ready to go */ err = snd_card_register(card); if (err < 0) { diff --git a/drivers/usb/gadget/f_uac2.c b/drivers/usb/gadget/f_uac2.c index 2f23566e53d..bc23040c779 100644 --- a/drivers/usb/gadget/f_uac2.c +++ b/drivers/usb/gadget/f_uac2.c @@ -394,7 +394,7 @@ static int snd_uac2_probe(struct platform_device *pdev) int err; /* Choose any slot, with no id */ - err = snd_card_create(-1, NULL, THIS_MODULE, 0, &card); + err = snd_card_new(&pdev->dev, -1, NULL, THIS_MODULE, 0, &card); if (err < 0) return err; @@ -421,8 +421,6 @@ static int snd_uac2_probe(struct platform_device *pdev) strcpy(card->shortname, "UAC2_Gadget"); sprintf(card->longname, "UAC2_Gadget %i", pdev->id); - snd_card_set_dev(card, &pdev->dev); - snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_CONTINUOUS, snd_dma_continuous_data(GFP_KERNEL), 0, BUFF_SIZE_MAX); diff --git a/include/dt-bindings/sound/tlv320aic31xx-micbias.h b/include/dt-bindings/sound/tlv320aic31xx-micbias.h new file mode 100644 index 00000000000..f5cb772ab9c --- /dev/null +++ b/include/dt-bindings/sound/tlv320aic31xx-micbias.h @@ -0,0 +1,8 @@ +#ifndef __DT_TLV320AIC31XX_MICBIAS_H +#define __DT_TLV320AIC31XX_MICBIAS_H + +#define MICBIAS_2_0V 1 +#define MICBIAS_2_5V 2 +#define MICBIAS_AVDDV 3 + +#endif /* __DT_TLV320AIC31XX_MICBIAS_H */ diff --git a/include/linux/atmel-ssc.h b/include/linux/atmel-ssc.h index 66a0e5384ed..571a12ebb01 100644 --- a/include/linux/atmel-ssc.h +++ b/include/linux/atmel-ssc.h @@ -18,6 +18,7 @@ struct ssc_device { struct clk *clk; int user; int irq; + bool clk_from_rk_pin; }; struct ssc_device * __must_check ssc_request(unsigned int ssc_num); diff --git a/include/linux/mfd/arizona/registers.h b/include/linux/mfd/arizona/registers.h index fdf3aa376eb..3ddaa634b19 100644 --- a/include/linux/mfd/arizona/registers.h +++ b/include/linux/mfd/arizona/registers.h @@ -1702,9 +1702,9 @@ /* * R373 (0x175) - FLL1 Control 5 */ -#define ARIZONA_FLL1_FRATIO_MASK 0x0700 /* FLL1_FRATIO - [10:8] */ -#define ARIZONA_FLL1_FRATIO_SHIFT 8 /* FLL1_FRATIO - [10:8] */ -#define ARIZONA_FLL1_FRATIO_WIDTH 3 /* FLL1_FRATIO - [10:8] */ +#define ARIZONA_FLL1_FRATIO_MASK 0x0F00 /* FLL1_FRATIO - [11:8] */ +#define ARIZONA_FLL1_FRATIO_SHIFT 8 /* FLL1_FRATIO - [11:8] */ +#define ARIZONA_FLL1_FRATIO_WIDTH 4 /* FLL1_FRATIO - [11:8] */ #define ARIZONA_FLL1_OUTDIV_MASK 0x000E /* FLL1_OUTDIV - [3:1] */ #define ARIZONA_FLL1_OUTDIV_SHIFT 1 /* FLL1_OUTDIV - [3:1] */ #define ARIZONA_FLL1_OUTDIV_WIDTH 3 /* FLL1_OUTDIV - [3:1] */ diff --git a/include/linux/platform_data/adau1977.h b/include/linux/platform_data/adau1977.h new file mode 100644 index 00000000000..bed11d908f9 --- /dev/null +++ b/include/linux/platform_data/adau1977.h @@ -0,0 +1,45 @@ +/* + * ADAU1977/ADAU1978/ADAU1979 driver + * + * Copyright 2014 Analog Devices Inc. + * Author: Lars-Peter Clausen <lars@metafoo.de> + * + * Licensed under the GPL-2. + */ + +#ifndef __LINUX_PLATFORM_DATA_ADAU1977_H__ +#define __LINUX_PLATFORM_DATA_ADAU1977_H__ + +/** + * enum adau1977_micbias - ADAU1977 MICBIAS pin voltage setting + * @ADAU1977_MICBIAS_5V0: MICBIAS is set to 5.0 V + * @ADAU1977_MICBIAS_5V5: MICBIAS is set to 5.5 V + * @ADAU1977_MICBIAS_6V0: MICBIAS is set to 6.0 V + * @ADAU1977_MICBIAS_6V5: MICBIAS is set to 6.5 V + * @ADAU1977_MICBIAS_7V0: MICBIAS is set to 7.0 V + * @ADAU1977_MICBIAS_7V5: MICBIAS is set to 7.5 V + * @ADAU1977_MICBIAS_8V0: MICBIAS is set to 8.0 V + * @ADAU1977_MICBIAS_8V5: MICBIAS is set to 8.5 V + * @ADAU1977_MICBIAS_9V0: MICBIAS is set to 9.0 V + */ +enum adau1977_micbias { + ADAU1977_MICBIAS_5V0 = 0x0, + ADAU1977_MICBIAS_5V5 = 0x1, + ADAU1977_MICBIAS_6V0 = 0x2, + ADAU1977_MICBIAS_6V5 = 0x3, + ADAU1977_MICBIAS_7V0 = 0x4, + ADAU1977_MICBIAS_7V5 = 0x5, + ADAU1977_MICBIAS_8V0 = 0x6, + ADAU1977_MICBIAS_8V5 = 0x7, + ADAU1977_MICBIAS_9V0 = 0x8, +}; + +/** + * struct adau1977_platform_data - Platform configuration data for the ADAU1977 + * @micbias: Specifies the voltage for the MICBIAS pin + */ +struct adau1977_platform_data { + enum adau1977_micbias micbias; +}; + +#endif diff --git a/include/linux/platform_data/asoc-s3c.h b/include/linux/platform_data/asoc-s3c.h index 9efc04dd255..709c6f7e2f8 100644 --- a/include/linux/platform_data/asoc-s3c.h +++ b/include/linux/platform_data/asoc-s3c.h @@ -1,5 +1,4 @@ -/* arch/arm/plat-samsung/include/plat/audio.h - * +/* * Copyright (c) 2009 Samsung Electronics Co. Ltd * Author: Jaswinder Singh <jassi.brar@samsung.com> * diff --git a/include/linux/platform_data/asoc-s3c24xx_simtec.h b/include/linux/platform_data/asoc-s3c24xx_simtec.h index 376af5286a3..d220e54123a 100644 --- a/include/linux/platform_data/asoc-s3c24xx_simtec.h +++ b/include/linux/platform_data/asoc-s3c24xx_simtec.h @@ -1,5 +1,4 @@ -/* arch/arm/plat-samsung/include/plat/audio-simtec.h - * +/* * Copyright 2008 Simtec Electronics * http://armlinux.simtec.co.uk/ * Ben Dooks <ben@simtec.co.uk> diff --git a/include/linux/platform_data/davinci_asp.h b/include/linux/platform_data/davinci_asp.h index 5245992b036..85ad68f9206 100644 --- a/include/linux/platform_data/davinci_asp.h +++ b/include/linux/platform_data/davinci_asp.h @@ -18,7 +18,7 @@ #include <linux/genalloc.h> -struct snd_platform_data { +struct davinci_mcasp_pdata { u32 tx_dma_offset; u32 rx_dma_offset; int asp_chan_q; /* event queue number for ASP channel */ @@ -87,6 +87,8 @@ struct snd_platform_data { int tx_dma_channel; int rx_dma_channel; }; +/* TODO: Fix arch/arm/mach-davinci/ users and remove this define */ +#define snd_platform_data davinci_mcasp_pdata enum { MCASP_VERSION_1 = 0, /* DM646x */ diff --git a/include/sound/core.h b/include/sound/core.h index 2a14f1f02d4..d3f5f818e0b 100644 --- a/include/sound/core.h +++ b/include/sound/core.h @@ -22,6 +22,7 @@ * */ +#include <linux/device.h> #include <linux/sched.h> /* wake_up() */ #include <linux/mutex.h> /* struct mutex */ #include <linux/rwsem.h> /* struct rw_semaphore */ @@ -41,39 +42,33 @@ /* forward declarations */ struct pci_dev; struct module; -struct device; -struct device_attribute; +struct completion; /* device allocation stuff */ -#define SNDRV_DEV_TYPE_RANGE_SIZE 0x1000 - -typedef int __bitwise snd_device_type_t; -#define SNDRV_DEV_TOPLEVEL ((__force snd_device_type_t) 0) -#define SNDRV_DEV_CONTROL ((__force snd_device_type_t) 1) -#define SNDRV_DEV_LOWLEVEL_PRE ((__force snd_device_type_t) 2) -#define SNDRV_DEV_LOWLEVEL_NORMAL ((__force snd_device_type_t) 0x1000) -#define SNDRV_DEV_PCM ((__force snd_device_type_t) 0x1001) -#define SNDRV_DEV_RAWMIDI ((__force snd_device_type_t) 0x1002) -#define SNDRV_DEV_TIMER ((__force snd_device_type_t) 0x1003) -#define SNDRV_DEV_SEQUENCER ((__force snd_device_type_t) 0x1004) -#define SNDRV_DEV_HWDEP ((__force snd_device_type_t) 0x1005) -#define SNDRV_DEV_INFO ((__force snd_device_type_t) 0x1006) -#define SNDRV_DEV_BUS ((__force snd_device_type_t) 0x1007) -#define SNDRV_DEV_CODEC ((__force snd_device_type_t) 0x1008) -#define SNDRV_DEV_JACK ((__force snd_device_type_t) 0x1009) -#define SNDRV_DEV_COMPRESS ((__force snd_device_type_t) 0x100A) -#define SNDRV_DEV_LOWLEVEL ((__force snd_device_type_t) 0x2000) - -typedef int __bitwise snd_device_state_t; -#define SNDRV_DEV_BUILD ((__force snd_device_state_t) 0) -#define SNDRV_DEV_REGISTERED ((__force snd_device_state_t) 1) -#define SNDRV_DEV_DISCONNECTED ((__force snd_device_state_t) 2) - -typedef int __bitwise snd_device_cmd_t; -#define SNDRV_DEV_CMD_PRE ((__force snd_device_cmd_t) 0) -#define SNDRV_DEV_CMD_NORMAL ((__force snd_device_cmd_t) 1) -#define SNDRV_DEV_CMD_POST ((__force snd_device_cmd_t) 2) +/* type of the object used in snd_device_*() + * this also defines the calling order + */ +enum snd_device_type { + SNDRV_DEV_LOWLEVEL, + SNDRV_DEV_CONTROL, + SNDRV_DEV_INFO, + SNDRV_DEV_BUS, + SNDRV_DEV_CODEC, + SNDRV_DEV_PCM, + SNDRV_DEV_COMPRESS, + SNDRV_DEV_RAWMIDI, + SNDRV_DEV_TIMER, + SNDRV_DEV_SEQUENCER, + SNDRV_DEV_HWDEP, + SNDRV_DEV_JACK, +}; + +enum snd_device_state { + SNDRV_DEV_BUILD, + SNDRV_DEV_REGISTERED, + SNDRV_DEV_DISCONNECTED, +}; struct snd_device; @@ -86,8 +81,8 @@ struct snd_device_ops { struct snd_device { struct list_head list; /* list of registered devices */ struct snd_card *card; /* card which holds this device */ - snd_device_state_t state; /* state of the device */ - snd_device_type_t type; /* device type */ + enum snd_device_state state; /* state of the device */ + enum snd_device_type type; /* device type */ void *device_data; /* device structure */ struct snd_device_ops *ops; /* operations */ }; @@ -131,11 +126,10 @@ struct snd_card { state */ spinlock_t files_lock; /* lock the files for this card */ int shutdown; /* this card is going down */ - int free_on_last_close; /* free in context of file_release */ - wait_queue_head_t shutdown_sleep; - atomic_t refcount; /* refcount for disconnection */ + struct completion *release_completion; struct device *dev; /* device assigned to this card */ - struct device *card_dev; /* cardX object for sysfs */ + struct device card_dev; /* cardX object for sysfs */ + bool registered; /* card_dev is registered? */ #ifdef CONFIG_PM unsigned int power_state; /* power state */ @@ -149,6 +143,8 @@ struct snd_card { #endif }; +#define dev_to_snd_card(p) container_of(p, struct snd_card, card_dev) + #ifdef CONFIG_PM static inline void snd_power_lock(struct snd_card *card) { @@ -197,7 +193,7 @@ struct snd_minor { /* return a device pointer linked to each sound device as a parent */ static inline struct device *snd_card_get_device_link(struct snd_card *card) { - return card ? card->card_dev : NULL; + return card ? &card->card_dev : NULL; } /* sound.c */ @@ -244,13 +240,11 @@ static inline int snd_register_device(int type, struct snd_card *card, int dev, int snd_unregister_device(int type, struct snd_card *card, int dev); void *snd_lookup_minor_data(unsigned int minor, int type); -int snd_add_device_sysfs_file(int type, struct snd_card *card, int dev, - struct device_attribute *attr); +struct device *snd_get_device(int type, struct snd_card *card, int dev); #ifdef CONFIG_SND_OSSEMUL int snd_register_oss_device(int type, struct snd_card *card, int dev, - const struct file_operations *f_ops, void *private_data, - const char *name); + const struct file_operations *f_ops, void *private_data); int snd_unregister_oss_device(int type, struct snd_card *card, int dev); void *snd_lookup_oss_minor_data(unsigned int minor, int type); #endif @@ -284,9 +278,16 @@ int snd_card_locked(int card); extern int (*snd_mixer_oss_notify_callback)(struct snd_card *card, int cmd); #endif -int snd_card_create(int idx, const char *id, - struct module *module, int extra_size, - struct snd_card **card_ret); +int snd_card_new(struct device *parent, int idx, const char *xid, + struct module *module, int extra_size, + struct snd_card **card_ret); + +static inline int __deprecated +snd_card_create(int idx, const char *id, struct module *module, int extra_size, + struct snd_card **ret) +{ + return snd_card_new(NULL, idx, id, module, extra_size, ret); +} int snd_card_disconnect(struct snd_card *card); int snd_card_free(struct snd_card *card); @@ -298,20 +299,19 @@ int snd_card_info_done(void); int snd_component_add(struct snd_card *card, const char *component); int snd_card_file_add(struct snd_card *card, struct file *file); int snd_card_file_remove(struct snd_card *card, struct file *file); -void snd_card_unref(struct snd_card *card); +#define snd_card_unref(card) put_device(&(card)->card_dev) #define snd_card_set_dev(card, devptr) ((card)->dev = (devptr)) /* device.c */ -int snd_device_new(struct snd_card *card, snd_device_type_t type, +int snd_device_new(struct snd_card *card, enum snd_device_type type, void *device_data, struct snd_device_ops *ops); int snd_device_register(struct snd_card *card, void *device_data); int snd_device_register_all(struct snd_card *card); -int snd_device_disconnect(struct snd_card *card, void *device_data); int snd_device_disconnect_all(struct snd_card *card); -int snd_device_free(struct snd_card *card, void *device_data); -int snd_device_free_all(struct snd_card *card, snd_device_cmd_t cmd); +void snd_device_free(struct snd_card *card, void *device_data); +void snd_device_free_all(struct snd_card *card); /* isadma.c */ @@ -433,7 +433,6 @@ static inline void snd_printdd(const char *format, ...) {} #define gameport_get_port_data(gp) (gp)->port_data #endif -#ifdef CONFIG_PCI /* PCI quirk list helper */ struct snd_pci_quirk { unsigned short subvendor; /* PCI subvendor ID */ @@ -469,12 +468,26 @@ struct snd_pci_quirk { #define snd_pci_quirk_name(q) "" #endif +#ifdef CONFIG_PCI const struct snd_pci_quirk * snd_pci_quirk_lookup(struct pci_dev *pci, const struct snd_pci_quirk *list); const struct snd_pci_quirk * snd_pci_quirk_lookup_id(u16 vendor, u16 device, const struct snd_pci_quirk *list); +#else +static inline const struct snd_pci_quirk * +snd_pci_quirk_lookup(struct pci_dev *pci, const struct snd_pci_quirk *list) +{ + return NULL; +} + +static inline const struct snd_pci_quirk * +snd_pci_quirk_lookup_id(u16 vendor, u16 device, + const struct snd_pci_quirk *list) +{ + return NULL; +} #endif #endif /* __SOUND_CORE_H */ diff --git a/include/sound/emu10k1.h b/include/sound/emu10k1.h index dfb42ca6d04..c46908c1bb3 100644 --- a/include/sound/emu10k1.h +++ b/include/sound/emu10k1.h @@ -436,8 +436,6 @@ #define CCCA_CURRADDR_MASK 0x00ffffff /* Current address of the selected channel */ #define CCCA_CURRADDR 0x18000008 -/* undefine CCR to avoid conflict with the definition for SH */ -#undef CCR #define CCR 0x09 /* Cache control register */ #define CCR_CACHEINVALIDSIZE 0x07190009 #define CCR_CACHEINVALIDSIZE_MASK 0xfe000000 /* Number of invalid samples cache for this channel */ diff --git a/include/sound/hwdep.h b/include/sound/hwdep.h index 8c05e47a409..ae04a3ec9c7 100644 --- a/include/sound/hwdep.h +++ b/include/sound/hwdep.h @@ -60,7 +60,6 @@ struct snd_hwdep { int iface; #ifdef CONFIG_SND_OSSEMUL - char oss_dev[32]; int oss_type; int ossreg; #endif @@ -69,6 +68,8 @@ struct snd_hwdep { wait_queue_head_t open_wait; void *private_data; void (*private_free) (struct snd_hwdep *hwdep); + struct device *dev; + const struct attribute_group **groups; struct mutex open_mutex; int used; /* reference counter */ diff --git a/include/sound/pcm.h b/include/sound/pcm.h index 4883499ab38..b4d6697085f 100644 --- a/include/sound/pcm.h +++ b/include/sound/pcm.h @@ -1141,4 +1141,12 @@ static inline u64 pcm_format_to_bits(snd_pcm_format_t pcm_format) return 1ULL << (__force int) pcm_format; } +/* printk helpers */ +#define pcm_err(pcm, fmt, args...) \ + dev_err((pcm)->card->dev, fmt, ##args) +#define pcm_warn(pcm, fmt, args...) \ + dev_warn((pcm)->card->dev, fmt, ##args) +#define pcm_dbg(pcm, fmt, args...) \ + dev_dbg((pcm)->card->dev, fmt, ##args) + #endif /* __SOUND_PCM_H */ diff --git a/include/sound/rawmidi.h b/include/sound/rawmidi.h index adf0885153f..311dafe6cc4 100644 --- a/include/sound/rawmidi.h +++ b/include/sound/rawmidi.h @@ -157,10 +157,8 @@ void snd_rawmidi_set_ops(struct snd_rawmidi *rmidi, int stream, /* callbacks */ -void snd_rawmidi_receive_reset(struct snd_rawmidi_substream *substream); int snd_rawmidi_receive(struct snd_rawmidi_substream *substream, const unsigned char *buffer, int count); -void snd_rawmidi_transmit_reset(struct snd_rawmidi_substream *substream); int snd_rawmidi_transmit_empty(struct snd_rawmidi_substream *substream); int snd_rawmidi_transmit_peek(struct snd_rawmidi_substream *substream, unsigned char *buffer, int count); diff --git a/include/sound/rcar_snd.h b/include/sound/rcar_snd.h index 6add6ccc811..34a3c02a457 100644 --- a/include/sound/rcar_snd.h +++ b/include/sound/rcar_snd.h @@ -34,17 +34,17 @@ * B : SSI direction */ #define RSND_SSI_CLK_PIN_SHARE (1 << 31) -#define RSND_SSI_SYNC (1 << 29) /* SSI34_sync etc */ - #define RSND_SSI_PLAY (1 << 24) +#define RSND_SSI(_dma_id, _pio_irq, _flags) \ +{ .dma_id = _dma_id, .pio_irq = _pio_irq, .flags = _flags } #define RSND_SSI_SET(_dai_id, _dma_id, _pio_irq, _flags) \ { .dai_id = _dai_id, .dma_id = _dma_id, .pio_irq = _pio_irq, .flags = _flags } #define RSND_SSI_UNUSED \ { .dai_id = -1, .dma_id = -1, .pio_irq = -1, .flags = 0 } struct rsnd_ssi_platform_info { - int dai_id; + int dai_id; /* will be removed */ int dma_id; int pio_irq; u32 flags; @@ -55,9 +55,31 @@ struct rsnd_ssi_platform_info { */ #define RSND_SCU_USE_HPBIF (1 << 31) /* it needs RSND_SSI_DEPENDENT */ -struct rsnd_scu_platform_info { +#define RSND_SRC(rate, _dma_id) \ +{ .flags = RSND_SCU_USE_HPBIF, .convert_rate = rate, .dma_id = _dma_id, } +#define RSND_SRC_SET(rate, _dma_id) \ + { .flags = RSND_SCU_USE_HPBIF, .convert_rate = rate, .dma_id = _dma_id, } +#define RSND_SRC_UNUSED \ + { .flags = 0, .convert_rate = 0, .dma_id = 0, } + +#define rsnd_scu_platform_info rsnd_src_platform_info +#define src_info scu_info +#define src_info_nr scu_info_nr + +struct rsnd_src_platform_info { u32 flags; u32 convert_rate; /* sampling rate convert */ + int dma_id; /* for Gen2 SCU */ +}; + +struct rsnd_dai_path_info { + struct rsnd_ssi_platform_info *ssi; + struct rsnd_src_platform_info *src; +}; + +struct rsnd_dai_platform_info { + struct rsnd_dai_path_info playback; + struct rsnd_dai_path_info capture; }; /* @@ -75,8 +97,10 @@ struct rcar_snd_info { u32 flags; struct rsnd_ssi_platform_info *ssi_info; int ssi_info_nr; - struct rsnd_scu_platform_info *scu_info; - int scu_info_nr; + struct rsnd_src_platform_info *src_info; + int src_info_nr; + struct rsnd_dai_platform_info *dai_info; + int dai_info_nr; int (*start)(int id); int (*stop)(int id); }; diff --git a/include/sound/simple_card.h b/include/sound/simple_card.h index 6c74527d492..9b0ac77177b 100644 --- a/include/sound/simple_card.h +++ b/include/sound/simple_card.h @@ -18,6 +18,8 @@ struct asoc_simple_dai { const char *name; unsigned int fmt; unsigned int sysclk; + int slots; + int slot_width; }; struct asoc_simple_card_info { @@ -29,10 +31,6 @@ struct asoc_simple_card_info { unsigned int daifmt; struct asoc_simple_dai cpu_dai; struct asoc_simple_dai codec_dai; - - /* used in simple-card.c */ - struct snd_soc_dai_link snd_link; - struct snd_soc_card snd_card; }; #endif /* __SIMPLE_CARD_H */ diff --git a/include/sound/soc-dai.h b/include/sound/soc-dai.h index 71f27c40319..fad76769f15 100644 --- a/include/sound/soc-dai.h +++ b/include/sound/soc-dai.h @@ -142,6 +142,8 @@ struct snd_soc_dai_ops { * Called by soc_card drivers, normally in their hw_params. */ int (*set_fmt)(struct snd_soc_dai *dai, unsigned int fmt); + int (*xlate_tdm_slot_mask)(unsigned int slots, + unsigned int *tx_mask, unsigned int *rx_mask); int (*set_tdm_slot)(struct snd_soc_dai *dai, unsigned int tx_mask, unsigned int rx_mask, int slots, int slot_width); @@ -270,6 +272,7 @@ struct snd_soc_dai { /* parent platform/codec */ struct snd_soc_platform *platform; struct snd_soc_codec *codec; + struct snd_soc_component *component; struct snd_soc_card *card; diff --git a/include/sound/soc-dapm.h b/include/sound/soc-dapm.h index 6e89ef6c11c..ef78f562f4a 100644 --- a/include/sound/soc-dapm.h +++ b/include/sound/soc-dapm.h @@ -108,13 +108,9 @@ struct device; SND_SOC_DAPM_INIT_REG_VAL(wreg, wshift, winvert), \ .kcontrol_news = wcontrols, .num_kcontrols = 1} #define SND_SOC_DAPM_VIRT_MUX(wname, wreg, wshift, winvert, wcontrols) \ -{ .id = snd_soc_dapm_virt_mux, .name = wname, \ - SND_SOC_DAPM_INIT_REG_VAL(wreg, wshift, winvert), \ - .kcontrol_news = wcontrols, .num_kcontrols = 1} + SND_SOC_DAPM_MUX(wname, wreg, wshift, winvert, wcontrols) #define SND_SOC_DAPM_VALUE_MUX(wname, wreg, wshift, winvert, wcontrols) \ -{ .id = snd_soc_dapm_value_mux, .name = wname, \ - SND_SOC_DAPM_INIT_REG_VAL(wreg, wshift, winvert), \ - .kcontrol_news = wcontrols, .num_kcontrols = 1} + SND_SOC_DAPM_MUX(wname, wreg, wshift, winvert, wcontrols) /* Simplified versions of above macros, assuming wncontrols = ARRAY_SIZE(wcontrols) */ #define SOC_PGA_ARRAY(wname, wreg, wshift, winvert,\ @@ -172,10 +168,8 @@ struct device; .event = wevent, .event_flags = wflags} #define SND_SOC_DAPM_VIRT_MUX_E(wname, wreg, wshift, winvert, wcontrols, \ wevent, wflags) \ -{ .id = snd_soc_dapm_virt_mux, .name = wname, \ - SND_SOC_DAPM_INIT_REG_VAL(wreg, wshift, winvert), \ - .kcontrol_news = wcontrols, .num_kcontrols = 1, \ - .event = wevent, .event_flags = wflags} + SND_SOC_DAPM_MUX_E(wname, wreg, wshift, winvert, wcontrols, wevent, \ + wflags) /* additional sequencing control within an event type */ #define SND_SOC_DAPM_PGA_S(wname, wsubseq, wreg, wshift, winvert, \ @@ -311,12 +305,8 @@ struct device; .get = snd_soc_dapm_get_enum_double, \ .put = snd_soc_dapm_put_enum_double, \ .private_value = (unsigned long)&xenum } -#define SOC_DAPM_ENUM_VIRT(xname, xenum) \ -{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \ - .info = snd_soc_info_enum_double, \ - .get = snd_soc_dapm_get_enum_virt, \ - .put = snd_soc_dapm_put_enum_virt, \ - .private_value = (unsigned long)&xenum } +#define SOC_DAPM_ENUM_VIRT(xname, xenum) \ + SOC_DAPM_ENUM(xname, xenum) #define SOC_DAPM_ENUM_EXT(xname, xenum, xget, xput) \ { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \ .info = snd_soc_info_enum_double, \ @@ -324,11 +314,7 @@ struct device; .put = xput, \ .private_value = (unsigned long)&xenum } #define SOC_DAPM_VALUE_ENUM(xname, xenum) \ -{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \ - .info = snd_soc_info_enum_double, \ - .get = snd_soc_dapm_get_value_enum_double, \ - .put = snd_soc_dapm_put_value_enum_double, \ - .private_value = (unsigned long)&xenum } + SOC_DAPM_ENUM(xname, xenum) #define SOC_DAPM_PIN_SWITCH(xname) \ { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname " Switch", \ .info = snd_soc_dapm_info_pin_switch, \ @@ -392,14 +378,6 @@ int snd_soc_dapm_get_enum_double(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol); int snd_soc_dapm_put_enum_double(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol); -int snd_soc_dapm_get_enum_virt(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol); -int snd_soc_dapm_put_enum_virt(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol); -int snd_soc_dapm_get_value_enum_double(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol); -int snd_soc_dapm_put_value_enum_double(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol); int snd_soc_dapm_info_pin_switch(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo); int snd_soc_dapm_get_pin_switch(struct snd_kcontrol *kcontrol, @@ -461,6 +439,7 @@ int snd_soc_dapm_nc_pin_unlocked(struct snd_soc_dapm_context *dapm, int snd_soc_dapm_get_pin_status(struct snd_soc_dapm_context *dapm, const char *pin); int snd_soc_dapm_sync(struct snd_soc_dapm_context *dapm); +int snd_soc_dapm_sync_unlocked(struct snd_soc_dapm_context *dapm); int snd_soc_dapm_force_enable_pin(struct snd_soc_dapm_context *dapm, const char *pin); int snd_soc_dapm_force_enable_pin_unlocked(struct snd_soc_dapm_context *dapm, @@ -470,7 +449,6 @@ int snd_soc_dapm_ignore_suspend(struct snd_soc_dapm_context *dapm, void snd_soc_dapm_auto_nc_codec_pins(struct snd_soc_codec *codec); /* Mostly internal - should not normally be used */ -void dapm_mark_dirty(struct snd_soc_dapm_widget *w, const char *reason); void dapm_mark_io_dirty(struct snd_soc_dapm_context *dapm); /* dapm path query */ @@ -484,8 +462,6 @@ enum snd_soc_dapm_type { snd_soc_dapm_input = 0, /* input pin */ snd_soc_dapm_output, /* output pin */ snd_soc_dapm_mux, /* selects 1 analog signal from many inputs */ - snd_soc_dapm_virt_mux, /* virtual version of snd_soc_dapm_mux */ - snd_soc_dapm_value_mux, /* selects 1 analog signal from many inputs */ snd_soc_dapm_mixer, /* mixes several analog signals together */ snd_soc_dapm_mixer_named_ctl, /* mixer with named controls */ snd_soc_dapm_pga, /* programmable gain/attenuation (volume) */ diff --git a/include/sound/soc.h b/include/sound/soc.h index 9a001472b96..0b83168d8ff 100644 --- a/include/sound/soc.h +++ b/include/sound/soc.h @@ -45,6 +45,11 @@ ((unsigned long)&(struct soc_mixer_control) \ {.reg = xlreg, .rreg = xrreg, .shift = xshift, .rshift = xshift, \ .max = xmax, .platform_max = xmax, .invert = xinvert}) +#define SOC_DOUBLE_R_S_VALUE(xlreg, xrreg, xshift, xmin, xmax, xsign_bit, xinvert) \ + ((unsigned long)&(struct soc_mixer_control) \ + {.reg = xlreg, .rreg = xrreg, .shift = xshift, .rshift = xshift, \ + .max = xmax, .min = xmin, .platform_max = xmax, .sign_bit = xsign_bit, \ + .invert = xinvert}) #define SOC_DOUBLE_R_RANGE_VALUE(xlreg, xrreg, xshift, xmin, xmax, xinvert) \ ((unsigned long)&(struct soc_mixer_control) \ {.reg = xlreg, .rreg = xrreg, .shift = xshift, .rshift = xshift, \ @@ -152,6 +157,15 @@ {.reg = xreg, .rreg = xrreg, \ .shift = xshift, .rshift = xshift, \ .max = xmax, .min = xmin} } +#define SOC_DOUBLE_R_S_TLV(xname, reg_left, reg_right, xshift, xmin, xmax, xsign_bit, xinvert, tlv_array) \ +{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname),\ + .access = SNDRV_CTL_ELEM_ACCESS_TLV_READ |\ + SNDRV_CTL_ELEM_ACCESS_READWRITE,\ + .tlv.p = (tlv_array), \ + .info = snd_soc_info_volsw, \ + .get = snd_soc_get_volsw, .put = snd_soc_put_volsw, \ + .private_value = SOC_DOUBLE_R_S_VALUE(reg_left, reg_right, xshift, \ + xmin, xmax, xsign_bit, xinvert) } #define SOC_DOUBLE_S8_TLV(xname, xreg, xmin, xmax, tlv_array) \ { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname), \ .access = SNDRV_CTL_ELEM_ACCESS_TLV_READ | \ @@ -162,30 +176,28 @@ .private_value = (unsigned long)&(struct soc_mixer_control) \ {.reg = xreg, .min = xmin, .max = xmax, \ .platform_max = xmax} } -#define SOC_ENUM_DOUBLE(xreg, xshift_l, xshift_r, xmax, xtexts) \ +#define SOC_ENUM_DOUBLE(xreg, xshift_l, xshift_r, xitems, xtexts) \ { .reg = xreg, .shift_l = xshift_l, .shift_r = xshift_r, \ - .max = xmax, .texts = xtexts, \ - .mask = xmax ? roundup_pow_of_two(xmax) - 1 : 0} -#define SOC_ENUM_SINGLE(xreg, xshift, xmax, xtexts) \ - SOC_ENUM_DOUBLE(xreg, xshift, xshift, xmax, xtexts) -#define SOC_ENUM_SINGLE_EXT(xmax, xtexts) \ -{ .max = xmax, .texts = xtexts } -#define SOC_VALUE_ENUM_DOUBLE(xreg, xshift_l, xshift_r, xmask, xmax, xtexts, xvalues) \ + .items = xitems, .texts = xtexts, \ + .mask = xitems ? roundup_pow_of_two(xitems) - 1 : 0} +#define SOC_ENUM_SINGLE(xreg, xshift, xitems, xtexts) \ + SOC_ENUM_DOUBLE(xreg, xshift, xshift, xitems, xtexts) +#define SOC_ENUM_SINGLE_EXT(xitems, xtexts) \ +{ .items = xitems, .texts = xtexts } +#define SOC_VALUE_ENUM_DOUBLE(xreg, xshift_l, xshift_r, xmask, xitems, xtexts, xvalues) \ { .reg = xreg, .shift_l = xshift_l, .shift_r = xshift_r, \ - .mask = xmask, .max = xmax, .texts = xtexts, .values = xvalues} -#define SOC_VALUE_ENUM_SINGLE(xreg, xshift, xmask, xmax, xtexts, xvalues) \ - SOC_VALUE_ENUM_DOUBLE(xreg, xshift, xshift, xmask, xmax, xtexts, xvalues) + .mask = xmask, .items = xitems, .texts = xtexts, .values = xvalues} +#define SOC_VALUE_ENUM_SINGLE(xreg, xshift, xmask, xnitmes, xtexts, xvalues) \ + SOC_VALUE_ENUM_DOUBLE(xreg, xshift, xshift, xmask, xnitmes, xtexts, xvalues) +#define SOC_ENUM_SINGLE_VIRT(xitems, xtexts) \ + SOC_ENUM_SINGLE(SND_SOC_NOPM, 0, xitems, xtexts) #define SOC_ENUM(xname, xenum) \ { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname,\ .info = snd_soc_info_enum_double, \ .get = snd_soc_get_enum_double, .put = snd_soc_put_enum_double, \ .private_value = (unsigned long)&xenum } #define SOC_VALUE_ENUM(xname, xenum) \ -{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname,\ - .info = snd_soc_info_enum_double, \ - .get = snd_soc_get_value_enum_double, \ - .put = snd_soc_put_value_enum_double, \ - .private_value = (unsigned long)&xenum } + SOC_ENUM(xname, xenum) #define SOC_SINGLE_EXT(xname, xreg, xshift, xmax, xinvert,\ xhandler_get, xhandler_put) \ { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \ @@ -272,17 +284,19 @@ * ARRAY_SIZE internally */ #define SOC_ENUM_DOUBLE_DECL(name, xreg, xshift_l, xshift_r, xtexts) \ - struct soc_enum name = SOC_ENUM_DOUBLE(xreg, xshift_l, xshift_r, \ + const struct soc_enum name = SOC_ENUM_DOUBLE(xreg, xshift_l, xshift_r, \ ARRAY_SIZE(xtexts), xtexts) #define SOC_ENUM_SINGLE_DECL(name, xreg, xshift, xtexts) \ SOC_ENUM_DOUBLE_DECL(name, xreg, xshift, xshift, xtexts) #define SOC_ENUM_SINGLE_EXT_DECL(name, xtexts) \ - struct soc_enum name = SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(xtexts), xtexts) + const struct soc_enum name = SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(xtexts), xtexts) #define SOC_VALUE_ENUM_DOUBLE_DECL(name, xreg, xshift_l, xshift_r, xmask, xtexts, xvalues) \ - struct soc_enum name = SOC_VALUE_ENUM_DOUBLE(xreg, xshift_l, xshift_r, xmask, \ + const struct soc_enum name = SOC_VALUE_ENUM_DOUBLE(xreg, xshift_l, xshift_r, xmask, \ ARRAY_SIZE(xtexts), xtexts, xvalues) #define SOC_VALUE_ENUM_SINGLE_DECL(name, xreg, xshift, xmask, xtexts, xvalues) \ SOC_VALUE_ENUM_DOUBLE_DECL(name, xreg, xshift, xshift, xmask, xtexts, xvalues) +#define SOC_ENUM_SINGLE_VIRT_DECL(name, xtexts) \ + const struct soc_enum name = SOC_ENUM_SINGLE_VIRT(ARRAY_SIZE(xtexts), xtexts) /* * Component probe and remove ordering levels for components with runtime @@ -340,12 +354,6 @@ typedef int (*hw_write_t)(void *,const char* ,int); extern struct snd_ac97_bus_ops *soc_ac97_ops; -enum snd_soc_control_type { - SND_SOC_I2C = 1, - SND_SOC_SPI, - SND_SOC_REGMAP, -}; - enum snd_soc_pcm_subclass { SND_SOC_PCM_CLASS_PCM = 0, SND_SOC_PCM_CLASS_BE = 1, @@ -392,8 +400,7 @@ int snd_soc_codec_readable_register(struct snd_soc_codec *codec, int snd_soc_codec_writable_register(struct snd_soc_codec *codec, unsigned int reg); int snd_soc_codec_set_cache_io(struct snd_soc_codec *codec, - int addr_bits, int data_bits, - enum snd_soc_control_type control); + struct regmap *regmap); int snd_soc_cache_sync(struct snd_soc_codec *codec); int snd_soc_cache_init(struct snd_soc_codec *codec); int snd_soc_cache_exit(struct snd_soc_codec *codec); @@ -413,6 +420,10 @@ struct snd_pcm_substream *snd_soc_get_dai_substream(struct snd_soc_card *card, struct snd_soc_pcm_runtime *snd_soc_get_pcm_runtime(struct snd_soc_card *card, const char *dai_link); +bool snd_soc_runtime_ignore_pmdown_time(struct snd_soc_pcm_runtime *rtd); +void snd_soc_runtime_activate(struct snd_soc_pcm_runtime *rtd, int stream); +void snd_soc_runtime_deactivate(struct snd_soc_pcm_runtime *rtd, int stream); + /* Utility functions to get clock rates from various things */ int snd_soc_calc_frame_size(int sample_size, int channels, int tdm_slots); int snd_soc_params_to_frame_size(struct snd_pcm_hw_params *params); @@ -496,10 +507,6 @@ int snd_soc_get_enum_double(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol); int snd_soc_put_enum_double(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol); -int snd_soc_get_value_enum_double(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol); -int snd_soc_put_value_enum_double(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol); int snd_soc_info_volsw(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo); #define snd_soc_info_bool_ext snd_ctl_boolean_mono_info @@ -600,7 +607,8 @@ struct snd_soc_jack_gpio { struct snd_soc_jack *jack; struct delayed_work work; - int (*jack_status_check)(void); + void *data; + int (*jack_status_check)(void *data); }; struct snd_soc_jack { @@ -656,12 +664,19 @@ struct snd_soc_component { const char *name; int id; struct device *dev; + + unsigned int active; + + unsigned int ignore_pmdown_time:1; /* pmdown_time is ignored at stop */ + struct list_head list; struct snd_soc_dai_driver *dai_drv; int num_dai; const struct snd_soc_component_driver *driver; + + struct list_head dai_list; }; /* SoC Audio Codec device */ @@ -683,7 +698,6 @@ struct snd_soc_codec { /* runtime */ struct snd_ac97 *ac97; /* for ad-hoc ac97 devices */ - unsigned int active; 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 */ @@ -697,7 +711,6 @@ struct snd_soc_codec { /* codec IO */ void *control_data; /* codec control (i2c/3wire) data */ hw_write_t hw_write; - unsigned int (*hw_read)(struct snd_soc_codec *, unsigned int); unsigned int (*read)(struct snd_soc_codec *, unsigned int); int (*write)(struct snd_soc_codec *, unsigned int, unsigned int); void *reg_cache; @@ -709,7 +722,6 @@ struct snd_soc_codec { /* dapm */ struct snd_soc_dapm_context dapm; - unsigned int ignore_pmdown_time:1; /* pmdown_time is ignored at stop */ #ifdef CONFIG_DEBUG_FS struct dentry *debugfs_codec_root; @@ -1067,6 +1079,7 @@ struct soc_mixer_control { int min, max, platform_max; int reg, rreg; unsigned int shift, rshift; + unsigned int sign_bit; unsigned int invert:1; unsigned int autodisable:1; }; @@ -1085,16 +1098,28 @@ struct soc_mreg_control { /* enumerated kcontrol */ struct soc_enum { - unsigned short reg; - unsigned short reg2; + int reg; unsigned char shift_l; unsigned char shift_r; - unsigned int max; + unsigned int items; unsigned int mask; const char * const *texts; const unsigned int *values; }; +/** + * snd_soc_component_to_codec() - Casts a component to the CODEC it is embedded in + * @component: The component to cast to a CODEC + * + * This function must only be used on components that are known to be CODECs. + * Otherwise the behavior is undefined. + */ +static inline struct snd_soc_codec *snd_soc_component_to_codec( + struct snd_soc_component *component) +{ + return container_of(component, struct snd_soc_codec, component); +} + /* codec IO */ unsigned int snd_soc_read(struct snd_soc_codec *codec, unsigned int reg); unsigned int snd_soc_write(struct snd_soc_codec *codec, @@ -1168,11 +1193,51 @@ static inline bool snd_soc_volsw_is_stereo(struct soc_mixer_control *mc) return 1; } +static inline unsigned int snd_soc_enum_val_to_item(struct soc_enum *e, + unsigned int val) +{ + unsigned int i; + + if (!e->values) + return val; + + for (i = 0; i < e->items; i++) + if (val == e->values[i]) + return i; + + return 0; +} + +static inline unsigned int snd_soc_enum_item_to_val(struct soc_enum *e, + unsigned int item) +{ + if (!e->values) + return item; + + return e->values[item]; +} + +static inline bool snd_soc_component_is_active( + struct snd_soc_component *component) +{ + return component->active != 0; +} + +static inline bool snd_soc_codec_is_active(struct snd_soc_codec *codec) +{ + return snd_soc_component_is_active(&codec->component); +} + int snd_soc_util_init(void); void snd_soc_util_exit(void); int snd_soc_of_parse_card_name(struct snd_soc_card *card, const char *propname); +int snd_soc_of_parse_audio_simple_widgets(struct snd_soc_card *card, + const char *propname); +int snd_soc_of_parse_tdm_slot(struct device_node *np, + unsigned int *slots, + unsigned int *slot_width); int snd_soc_of_parse_audio_routing(struct snd_soc_card *card, const char *propname); unsigned int snd_soc_of_parse_daifmt(struct device_node *np, @@ -1188,4 +1253,15 @@ extern struct dentry *snd_soc_debugfs_root; extern const struct dev_pm_ops snd_soc_pm_ops; +/* Helper functions */ +static inline void snd_soc_dapm_mutex_lock(struct snd_soc_dapm_context *dapm) +{ + mutex_lock(&dapm->card->dapm_mutex); +} + +static inline void snd_soc_dapm_mutex_unlock(struct snd_soc_dapm_context *dapm) +{ + mutex_unlock(&dapm->card->dapm_mutex); +} + #endif diff --git a/include/trace/events/hswadsp.h b/include/trace/events/hswadsp.h new file mode 100644 index 00000000000..0f78bbb0200 --- /dev/null +++ b/include/trace/events/hswadsp.h @@ -0,0 +1,384 @@ +#undef TRACE_SYSTEM +#define TRACE_SYSTEM hswadsp + +#if !defined(_TRACE_HSWADSP_H) || defined(TRACE_HEADER_MULTI_READ) +#define _TRACE_HSWADSP_H + +#include <linux/types.h> +#include <linux/ktime.h> +#include <linux/tracepoint.h> + +struct sst_hsw; +struct sst_hsw_stream; +struct sst_hsw_ipc_stream_free_req; +struct sst_hsw_ipc_volume_req; +struct sst_hsw_ipc_stream_alloc_req; +struct sst_hsw_audio_data_format_ipc; +struct sst_hsw_ipc_stream_info_reply; +struct sst_hsw_ipc_device_config_req; + +DECLARE_EVENT_CLASS(sst_irq, + + TP_PROTO(uint32_t status, uint32_t mask), + + TP_ARGS(status, mask), + + TP_STRUCT__entry( + __field( unsigned int, status ) + __field( unsigned int, mask ) + ), + + TP_fast_assign( + __entry->status = status; + __entry->mask = mask; + ), + + TP_printk("status 0x%8.8x mask 0x%8.8x", + (unsigned int)__entry->status, (unsigned int)__entry->mask) +); + +DEFINE_EVENT(sst_irq, sst_irq_busy, + + TP_PROTO(unsigned int status, unsigned int mask), + + TP_ARGS(status, mask) + +); + +DEFINE_EVENT(sst_irq, sst_irq_done, + + TP_PROTO(unsigned int status, unsigned int mask), + + TP_ARGS(status, mask) + +); + +DECLARE_EVENT_CLASS(ipc, + + TP_PROTO(const char *name, int val), + + TP_ARGS(name, val), + + TP_STRUCT__entry( + __string( name, name ) + __field( unsigned int, val ) + ), + + TP_fast_assign( + __assign_str(name, name); + __entry->val = val; + ), + + TP_printk("%s 0x%8.8x", __get_str(name), (unsigned int)__entry->val) + +); + +DEFINE_EVENT(ipc, ipc_request, + + TP_PROTO(const char *name, int val), + + TP_ARGS(name, val) + +); + +DEFINE_EVENT(ipc, ipc_reply, + + TP_PROTO(const char *name, int val), + + TP_ARGS(name, val) + +); + +DEFINE_EVENT(ipc, ipc_pending_reply, + + TP_PROTO(const char *name, int val), + + TP_ARGS(name, val) + +); + +DEFINE_EVENT(ipc, ipc_notification, + + TP_PROTO(const char *name, int val), + + TP_ARGS(name, val) + +); + +DEFINE_EVENT(ipc, ipc_error, + + TP_PROTO(const char *name, int val), + + TP_ARGS(name, val) + +); + +DECLARE_EVENT_CLASS(stream_position, + + TP_PROTO(unsigned int id, unsigned int pos), + + TP_ARGS(id, pos), + + TP_STRUCT__entry( + __field( unsigned int, id ) + __field( unsigned int, pos ) + ), + + TP_fast_assign( + __entry->id = id; + __entry->pos = pos; + ), + + TP_printk("id %d position 0x%x", + (unsigned int)__entry->id, (unsigned int)__entry->pos) +); + +DEFINE_EVENT(stream_position, stream_read_position, + + TP_PROTO(unsigned int id, unsigned int pos), + + TP_ARGS(id, pos) + +); + +DEFINE_EVENT(stream_position, stream_write_position, + + TP_PROTO(unsigned int id, unsigned int pos), + + TP_ARGS(id, pos) + +); + +TRACE_EVENT(hsw_stream_buffer, + + TP_PROTO(struct sst_hsw_stream *stream), + + TP_ARGS(stream), + + TP_STRUCT__entry( + __field( int, id ) + __field( int, pt_addr ) + __field( int, num_pages ) + __field( int, ring_size ) + __field( int, ring_offset ) + __field( int, first_pfn ) + ), + + TP_fast_assign( + __entry->id = stream->host_id; + __entry->pt_addr = stream->request.ringinfo.ring_pt_address; + __entry->num_pages = stream->request.ringinfo.num_pages; + __entry->ring_size = stream->request.ringinfo.ring_size; + __entry->ring_offset = stream->request.ringinfo.ring_offset; + __entry->first_pfn = stream->request.ringinfo.ring_first_pfn; + ), + + TP_printk("stream %d ring addr 0x%x pages %d size 0x%x offset 0x%x PFN 0x%x", + (int) __entry->id, (int)__entry->pt_addr, + (int)__entry->num_pages, (int)__entry->ring_size, + (int)__entry->ring_offset, (int)__entry->first_pfn) +); + +TRACE_EVENT(hsw_stream_alloc_reply, + + TP_PROTO(struct sst_hsw_stream *stream), + + TP_ARGS(stream), + + TP_STRUCT__entry( + __field( int, id ) + __field( int, stream_id ) + __field( int, mixer_id ) + __field( int, peak0 ) + __field( int, peak1 ) + __field( int, vol0 ) + __field( int, vol1 ) + ), + + TP_fast_assign( + __entry->id = stream->host_id; + __entry->stream_id = stream->reply.stream_hw_id; + __entry->mixer_id = stream->reply.mixer_hw_id; + __entry->peak0 = stream->reply.peak_meter_register_address[0]; + __entry->peak1 = stream->reply.peak_meter_register_address[1]; + __entry->vol0 = stream->reply.volume_register_address[0]; + __entry->vol1 = stream->reply.volume_register_address[1]; + ), + + TP_printk("stream %d hw id %d mixer %d peak 0x%x:0x%x vol 0x%x,0x%x", + (int) __entry->id, (int) __entry->stream_id, (int)__entry->mixer_id, + (int)__entry->peak0, (int)__entry->peak1, + (int)__entry->vol0, (int)__entry->vol1) +); + +TRACE_EVENT(hsw_mixer_info_reply, + + TP_PROTO(struct sst_hsw_ipc_stream_info_reply *reply), + + TP_ARGS(reply), + + TP_STRUCT__entry( + __field( int, mixer_id ) + __field( int, peak0 ) + __field( int, peak1 ) + __field( int, vol0 ) + __field( int, vol1 ) + ), + + TP_fast_assign( + __entry->mixer_id = reply->mixer_hw_id; + __entry->peak0 = reply->peak_meter_register_address[0]; + __entry->peak1 = reply->peak_meter_register_address[1]; + __entry->vol0 = reply->volume_register_address[0]; + __entry->vol1 = reply->volume_register_address[1]; + ), + + TP_printk("mixer id %d peak 0x%x:0x%x vol 0x%x,0x%x", + (int)__entry->mixer_id, + (int)__entry->peak0, (int)__entry->peak1, + (int)__entry->vol0, (int)__entry->vol1) +); + +TRACE_EVENT(hsw_stream_data_format, + + TP_PROTO(struct sst_hsw_stream *stream, + struct sst_hsw_audio_data_format_ipc *req), + + TP_ARGS(stream, req), + + TP_STRUCT__entry( + __field( uint32_t, id ) + __field( uint32_t, frequency ) + __field( uint32_t, bitdepth ) + __field( uint32_t, map ) + __field( uint32_t, config ) + __field( uint32_t, style ) + __field( uint8_t, ch_num ) + __field( uint8_t, valid_bit ) + ), + + TP_fast_assign( + __entry->id = stream->host_id; + __entry->frequency = req->frequency; + __entry->bitdepth = req->bitdepth; + __entry->map = req->map; + __entry->config = req->config; + __entry->style = req->style; + __entry->ch_num = req->ch_num; + __entry->valid_bit = req->valid_bit; + ), + + TP_printk("stream %d freq %d depth %d map 0x%x config 0x%x style 0x%x ch %d bits %d", + (int) __entry->id, (uint32_t)__entry->frequency, + (uint32_t)__entry->bitdepth, (uint32_t)__entry->map, + (uint32_t)__entry->config, (uint32_t)__entry->style, + (uint8_t)__entry->ch_num, (uint8_t)__entry->valid_bit) +); + +TRACE_EVENT(hsw_stream_alloc_request, + + TP_PROTO(struct sst_hsw_stream *stream, + struct sst_hsw_ipc_stream_alloc_req *req), + + TP_ARGS(stream, req), + + TP_STRUCT__entry( + __field( uint32_t, id ) + __field( uint8_t, path_id ) + __field( uint8_t, stream_type ) + __field( uint8_t, format_id ) + ), + + TP_fast_assign( + __entry->id = stream->host_id; + __entry->path_id = req->path_id; + __entry->stream_type = req->stream_type; + __entry->format_id = req->format_id; + ), + + TP_printk("stream %d path %d type %d format %d", + (int) __entry->id, (uint8_t)__entry->path_id, + (uint8_t)__entry->stream_type, (uint8_t)__entry->format_id) +); + +TRACE_EVENT(hsw_stream_free_req, + + TP_PROTO(struct sst_hsw_stream *stream, + struct sst_hsw_ipc_stream_free_req *req), + + TP_ARGS(stream, req), + + TP_STRUCT__entry( + __field( int, id ) + __field( int, stream_id ) + ), + + TP_fast_assign( + __entry->id = stream->host_id; + __entry->stream_id = req->stream_id; + ), + + TP_printk("stream %d hw id %d", + (int) __entry->id, (int) __entry->stream_id) +); + +TRACE_EVENT(hsw_volume_req, + + TP_PROTO(struct sst_hsw_stream *stream, + struct sst_hsw_ipc_volume_req *req), + + TP_ARGS(stream, req), + + TP_STRUCT__entry( + __field( int, id ) + __field( uint32_t, channel ) + __field( uint32_t, target_volume ) + __field( uint64_t, curve_duration ) + __field( uint32_t, curve_type ) + ), + + TP_fast_assign( + __entry->id = stream->host_id; + __entry->channel = req->channel; + __entry->target_volume = req->target_volume; + __entry->curve_duration = req->curve_duration; + __entry->curve_type = req->curve_type; + ), + + TP_printk("stream %d chan 0x%x vol %d duration %llu type %d", + (int) __entry->id, (uint32_t) __entry->channel, + (uint32_t)__entry->target_volume, + (uint64_t)__entry->curve_duration, + (uint32_t)__entry->curve_type) +); + +TRACE_EVENT(hsw_device_config_req, + + TP_PROTO(struct sst_hsw_ipc_device_config_req *req), + + TP_ARGS(req), + + TP_STRUCT__entry( + __field( uint32_t, ssp ) + __field( uint32_t, clock_freq ) + __field( uint32_t, mode ) + __field( uint16_t, clock_divider ) + ), + + TP_fast_assign( + __entry->ssp = req->ssp_interface; + __entry->clock_freq = req->clock_frequency; + __entry->mode = req->mode; + __entry->clock_divider = req->clock_divider; + ), + + TP_printk("SSP %d Freq %d mode %d div %d", + (uint32_t)__entry->ssp, + (uint32_t)__entry->clock_freq, (uint32_t)__entry->mode, + (uint32_t)__entry->clock_divider) +); + +#endif /* _TRACE_HSWADSP_H */ + +/* This part must be outside protection */ +#include <trace/define_trace.h> diff --git a/include/trace/events/intel-sst.h b/include/trace/events/intel-sst.h new file mode 100644 index 00000000000..76c72d3f190 --- /dev/null +++ b/include/trace/events/intel-sst.h @@ -0,0 +1,148 @@ +#undef TRACE_SYSTEM +#define TRACE_SYSTEM intel-sst + +#if !defined(_TRACE_INTEL_SST_H) || defined(TRACE_HEADER_MULTI_READ) +#define _TRACE_INTEL_SST_H + +#include <linux/types.h> +#include <linux/ktime.h> +#include <linux/tracepoint.h> + +DECLARE_EVENT_CLASS(sst_ipc_msg, + + TP_PROTO(unsigned int val), + + TP_ARGS(val), + + TP_STRUCT__entry( + __field( unsigned int, val ) + ), + + TP_fast_assign( + __entry->val = val; + ), + + TP_printk("0x%8.8x", (unsigned int)__entry->val) +); + +DEFINE_EVENT(sst_ipc_msg, sst_ipc_msg_tx, + + TP_PROTO(unsigned int val), + + TP_ARGS(val) + +); + +DEFINE_EVENT(sst_ipc_msg, sst_ipc_msg_rx, + + TP_PROTO(unsigned int val), + + TP_ARGS(val) + +); + +DECLARE_EVENT_CLASS(sst_ipc_mailbox, + + TP_PROTO(unsigned int offset, unsigned int val), + + TP_ARGS(offset, val), + + TP_STRUCT__entry( + __field( unsigned int, offset ) + __field( unsigned int, val ) + ), + + TP_fast_assign( + __entry->offset = offset; + __entry->val = val; + ), + + TP_printk(" 0x%4.4x = 0x%8.8x", + (unsigned int)__entry->offset, (unsigned int)__entry->val) +); + +DEFINE_EVENT(sst_ipc_mailbox, sst_ipc_inbox_rdata, + + TP_PROTO(unsigned int offset, unsigned int val), + + TP_ARGS(offset, val) + +); + +DEFINE_EVENT(sst_ipc_mailbox, sst_ipc_inbox_wdata, + + TP_PROTO(unsigned int offset, unsigned int val), + + TP_ARGS(offset, val) + +); + +DEFINE_EVENT(sst_ipc_mailbox, sst_ipc_outbox_rdata, + + TP_PROTO(unsigned int offset, unsigned int val), + + TP_ARGS(offset, val) + +); + +DEFINE_EVENT(sst_ipc_mailbox, sst_ipc_outbox_wdata, + + TP_PROTO(unsigned int offset, unsigned int val), + + TP_ARGS(offset, val) + +); + +DECLARE_EVENT_CLASS(sst_ipc_mailbox_info, + + TP_PROTO(unsigned int size), + + TP_ARGS(size), + + TP_STRUCT__entry( + __field( unsigned int, size ) + ), + + TP_fast_assign( + __entry->size = size; + ), + + TP_printk("Mailbox bytes 0x%8.8x", (unsigned int)__entry->size) +); + +DEFINE_EVENT(sst_ipc_mailbox_info, sst_ipc_inbox_read, + + TP_PROTO(unsigned int size), + + TP_ARGS(size) + +); + +DEFINE_EVENT(sst_ipc_mailbox_info, sst_ipc_inbox_write, + + TP_PROTO(unsigned int size), + + TP_ARGS(size) + +); + +DEFINE_EVENT(sst_ipc_mailbox_info, sst_ipc_outbox_read, + + TP_PROTO(unsigned int size), + + TP_ARGS(size) + +); + +DEFINE_EVENT(sst_ipc_mailbox_info, sst_ipc_outbox_write, + + TP_PROTO(unsigned int size), + + TP_ARGS(size) + +); + +#endif /* _TRACE_SST_H */ + +/* This part must be outside protection */ +#include <trace/define_trace.h> diff --git a/sound/aoa/aoa.h b/sound/aoa/aoa.h index e08789484e3..34c668f2779 100644 --- a/sound/aoa/aoa.h +++ b/sound/aoa/aoa.h @@ -116,7 +116,7 @@ struct aoa_card { struct snd_card *alsa_card; }; -extern int aoa_snd_device_new(snd_device_type_t type, +extern int aoa_snd_device_new(enum snd_device_type type, void * device_data, struct snd_device_ops * ops); extern struct snd_card *aoa_get_card(void); extern int aoa_snd_ctl_add(struct snd_kcontrol* control); diff --git a/sound/aoa/codecs/onyx.c b/sound/aoa/codecs/onyx.c index 4cedc6950d7..f01bffb702b 100644 --- a/sound/aoa/codecs/onyx.c +++ b/sound/aoa/codecs/onyx.c @@ -889,7 +889,7 @@ static int onyx_init_codec(struct aoa_codec *codec) return -ENODEV; } - if (aoa_snd_device_new(SNDRV_DEV_LOWLEVEL, onyx, &ops)) { + if (aoa_snd_device_new(SNDRV_DEV_CODEC, onyx, &ops)) { printk(KERN_ERR PFX "failed to create onyx snd device!\n"); return -ENODEV; } diff --git a/sound/aoa/codecs/tas.c b/sound/aoa/codecs/tas.c index c491ae0f749..cf3c6303b7e 100644 --- a/sound/aoa/codecs/tas.c +++ b/sound/aoa/codecs/tas.c @@ -826,7 +826,7 @@ static int tas_init_codec(struct aoa_codec *codec) return -ENODEV; } - if (aoa_snd_device_new(SNDRV_DEV_LOWLEVEL, tas, &ops)) { + if (aoa_snd_device_new(SNDRV_DEV_CODEC, tas, &ops)) { printk(KERN_ERR PFX "failed to create tas snd device!\n"); return -ENODEV; } diff --git a/sound/aoa/codecs/toonie.c b/sound/aoa/codecs/toonie.c index 69d2cb601f2..7e8c3417cd8 100644 --- a/sound/aoa/codecs/toonie.c +++ b/sound/aoa/codecs/toonie.c @@ -92,7 +92,7 @@ static int toonie_init_codec(struct aoa_codec *codec) if (toonie->codec.connected != 1) return -ENOTCONN; - if (aoa_snd_device_new(SNDRV_DEV_LOWLEVEL, toonie, &ops)) { + if (aoa_snd_device_new(SNDRV_DEV_CODEC, toonie, &ops)) { printk(KERN_ERR PFX "failed to create toonie snd device!\n"); return -ENODEV; } diff --git a/sound/aoa/core/alsa.c b/sound/aoa/core/alsa.c index 0fa3855b479..4a7e4e6b746 100644 --- a/sound/aoa/core/alsa.c +++ b/sound/aoa/core/alsa.c @@ -23,13 +23,12 @@ int aoa_alsa_init(char *name, struct module *mod, struct device *dev) /* cannot be EEXIST due to usage in aoa_fabric_register */ return -EBUSY; - err = snd_card_create(index, name, mod, sizeof(struct aoa_card), - &alsa_card); + err = snd_card_new(dev, index, name, mod, sizeof(struct aoa_card), + &alsa_card); if (err < 0) return err; aoa_card = alsa_card->private_data; aoa_card->alsa_card = alsa_card; - alsa_card->dev = dev; strlcpy(alsa_card->driver, "AppleOnbdAudio", sizeof(alsa_card->driver)); strlcpy(alsa_card->shortname, name, sizeof(alsa_card->shortname)); strlcpy(alsa_card->longname, name, sizeof(alsa_card->longname)); @@ -60,7 +59,7 @@ void aoa_alsa_cleanup(void) } } -int aoa_snd_device_new(snd_device_type_t type, +int aoa_snd_device_new(enum snd_device_type type, void * device_data, struct snd_device_ops * ops) { struct snd_card *card = aoa_get_card(); diff --git a/sound/arm/aaci.c b/sound/arm/aaci.c index c421fdb3c7a..0e83a73efb1 100644 --- a/sound/arm/aaci.c +++ b/sound/arm/aaci.c @@ -899,8 +899,8 @@ static struct aaci *aaci_init_card(struct amba_device *dev) struct snd_card *card; int err; - err = snd_card_create(SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1, - THIS_MODULE, sizeof(struct aaci), &card); + err = snd_card_new(&dev->dev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1, + THIS_MODULE, sizeof(struct aaci), &card); if (err < 0) return NULL; @@ -1055,8 +1055,6 @@ static int aaci_probe(struct amba_device *dev, if (ret) goto out; - snd_card_set_dev(aaci->card, &dev->dev); - ret = snd_card_register(aaci->card); if (ret == 0) { dev_info(&dev->dev, "%s\n", aaci->card->longname); diff --git a/sound/arm/pxa2xx-ac97.c b/sound/arm/pxa2xx-ac97.c index 9a2ac1e0f77..3a10df6688e 100644 --- a/sound/arm/pxa2xx-ac97.c +++ b/sound/arm/pxa2xx-ac97.c @@ -179,12 +179,11 @@ static int pxa2xx_ac97_probe(struct platform_device *dev) goto err_dev; } - ret = snd_card_create(SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1, - THIS_MODULE, 0, &card); + ret = snd_card_new(&dev->dev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1, + THIS_MODULE, 0, &card); if (ret < 0) goto err; - card->dev = &dev->dev; strlcpy(card->driver, dev->dev.driver->name, sizeof(card->driver)); ret = pxa2xx_pcm_new(card, &pxa2xx_ac97_pcm_client, &pxa2xx_ac97_pcm); @@ -210,7 +209,6 @@ static int pxa2xx_ac97_probe(struct platform_device *dev) if (pdata && pdata->codec_pdata[0]) snd_ac97_dev_add_pdata(ac97_bus->codec[0], pdata->codec_pdata[0]); - snd_card_set_dev(card, &dev->dev); ret = snd_card_register(card); if (ret == 0) { platform_set_drvdata(dev, card); diff --git a/sound/atmel/abdac.c b/sound/atmel/abdac.c index 3519518e25a..edf2ca72d51 100644 --- a/sound/atmel/abdac.c +++ b/sound/atmel/abdac.c @@ -429,8 +429,9 @@ static int atmel_abdac_probe(struct platform_device *pdev) } clk_enable(pclk); - retval = snd_card_create(SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1, - THIS_MODULE, sizeof(struct atmel_abdac), &card); + retval = snd_card_new(&pdev->dev, SNDRV_DEFAULT_IDX1, + SNDRV_DEFAULT_STR1, THIS_MODULE, + sizeof(struct atmel_abdac), &card); if (retval) { dev_dbg(&pdev->dev, "could not create sound card device\n"); goto out_put_sample_clk; @@ -467,8 +468,6 @@ static int atmel_abdac_probe(struct platform_device *pdev) goto out_unmap_regs; } - snd_card_set_dev(card, &pdev->dev); - if (pdata->dws.dma_dev) { dma_cap_mask_t mask; @@ -492,7 +491,7 @@ static int atmel_abdac_probe(struct platform_device *pdev) if (!pdata->dws.dma_dev || !dac->dma.chan) { dev_dbg(&pdev->dev, "DMA not available\n"); retval = -ENODEV; - goto out_unset_card_dev; + goto out_unmap_regs; } strcpy(card->driver, "Atmel ABDAC"); @@ -521,9 +520,6 @@ static int atmel_abdac_probe(struct platform_device *pdev) out_release_dma: dma_release_channel(dac->dma.chan); dac->dma.chan = NULL; -out_unset_card_dev: - snd_card_set_dev(card, NULL); - free_irq(irq, dac); out_unmap_regs: iounmap(dac->regs); out_free_card: @@ -579,7 +575,6 @@ static int atmel_abdac_remove(struct platform_device *pdev) dma_release_channel(dac->dma.chan); dac->dma.chan = NULL; - snd_card_set_dev(card, NULL); iounmap(dac->regs); free_irq(dac->irq, dac); snd_card_free(card); diff --git a/sound/atmel/ac97c.c b/sound/atmel/ac97c.c index c5f0ddd729b..05ec049c9fa 100644 --- a/sound/atmel/ac97c.c +++ b/sound/atmel/ac97c.c @@ -945,8 +945,9 @@ static int atmel_ac97c_probe(struct platform_device *pdev) } clk_enable(pclk); - retval = snd_card_create(SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1, - THIS_MODULE, sizeof(struct atmel_ac97c), &card); + retval = snd_card_new(&pdev->dev, SNDRV_DEFAULT_IDX1, + SNDRV_DEFAULT_STR1, THIS_MODULE, + sizeof(struct atmel_ac97c), &card); if (retval) { dev_dbg(&pdev->dev, "could not create sound card device\n"); goto err_snd_card_new; @@ -990,8 +991,6 @@ static int atmel_ac97c_probe(struct platform_device *pdev) chip->reset_pin = -EINVAL; } - snd_card_set_dev(card, &pdev->dev); - atmel_ac97c_reset(chip); /* Enable overrun interrupt from codec channel */ @@ -1113,8 +1112,6 @@ err_dma: chip->dma.tx_chan = NULL; } err_ac97_bus: - snd_card_set_dev(card, NULL); - if (gpio_is_valid(chip->reset_pin)) gpio_free(chip->reset_pin); @@ -1195,7 +1192,6 @@ static int atmel_ac97c_remove(struct platform_device *pdev) chip->dma.tx_chan = NULL; } - snd_card_set_dev(card, NULL); snd_card_free(card); return 0; diff --git a/sound/core/control.c b/sound/core/control.c index d8aa206e8bd..f038f5afafe 100644 --- a/sound/core/control.c +++ b/sound/core/control.c @@ -151,7 +151,7 @@ void snd_ctl_notify(struct snd_card *card, unsigned int mask, if (snd_BUG_ON(!card || !id)) return; read_lock(&card->ctl_files_rwlock); -#if defined(CONFIG_SND_MIXER_OSS) || defined(CONFIG_SND_MIXER_OSS_MODULE) +#if IS_ENABLED(CONFIG_SND_MIXER_OSS) card->mixer_oss_change_count++; #endif list_for_each_entry(ctl, &card->ctl_files, list) { @@ -170,7 +170,7 @@ void snd_ctl_notify(struct snd_card *card, unsigned int mask, ev->mask = mask; list_add_tail(&ev->list, &ctl->events); } else { - snd_printk(KERN_ERR "No memory available to allocate event\n"); + dev_err(card->dev, "No memory available to allocate event\n"); } _found: wake_up(&ctl->change_sleep); @@ -206,7 +206,7 @@ static struct snd_kcontrol *snd_ctl_new(struct snd_kcontrol *control, kctl = kzalloc(sizeof(*kctl) + sizeof(struct snd_kcontrol_volatile) * control->count, GFP_KERNEL); if (kctl == NULL) { - snd_printk(KERN_ERR "Cannot allocate control instance\n"); + pr_err("ALSA: Cannot allocate control instance\n"); return NULL; } *kctl = *control; @@ -241,9 +241,8 @@ struct snd_kcontrol *snd_ctl_new1(const struct snd_kcontrol_new *ncontrol, if (ncontrol->name) { strlcpy(kctl.id.name, ncontrol->name, sizeof(kctl.id.name)); if (strcmp(ncontrol->name, kctl.id.name) != 0) - snd_printk(KERN_WARNING - "Control name '%s' truncated to '%s'\n", - ncontrol->name, kctl.id.name); + pr_warn("ALSA: Control name '%s' truncated to '%s'\n", + ncontrol->name, kctl.id.name); } kctl.id.index = ncontrol->index; kctl.count = ncontrol->count ? ncontrol->count : 1; @@ -306,7 +305,7 @@ static int snd_ctl_find_hole(struct snd_card *card, unsigned int count) while (snd_ctl_remove_numid_conflict(card, count)) { if (--iter == 0) { /* this situation is very unlikely */ - snd_printk(KERN_ERR "unable to allocate new control numid\n"); + dev_err(card->dev, "unable to allocate new control numid\n"); return -ENOMEM; } } @@ -341,7 +340,7 @@ int snd_ctl_add(struct snd_card *card, struct snd_kcontrol *kcontrol) down_write(&card->controls_rwsem); if (snd_ctl_find_id(card, &id)) { up_write(&card->controls_rwsem); - snd_printd(KERN_ERR "control %i:%i:%i:%s:%i is already present\n", + dev_err(card->dev, "control %i:%i:%i:%s:%i is already present\n", id.iface, id.device, id.subdevice, @@ -1406,7 +1405,7 @@ static long snd_ctl_ioctl(struct file *file, unsigned int cmd, unsigned long arg } } up_read(&snd_ioctl_rwsem); - snd_printdd("unknown ioctl = 0x%x\n", cmd); + dev_dbg(card->dev, "unknown ioctl = 0x%x\n", cmd); return -ENOTTY; } diff --git a/sound/core/control_compat.c b/sound/core/control_compat.c index 2bb95a7a880..b9c0910fb8c 100644 --- a/sound/core/control_compat.c +++ b/sound/core/control_compat.c @@ -247,7 +247,7 @@ static int copy_ctl_value_from_user(struct snd_card *card, } else { size = get_elem_size(type, count); if (size < 0) { - printk(KERN_ERR "snd_ioctl32_ctl_elem_value: unknown type %d\n", type); + dev_err(card->dev, "snd_ioctl32_ctl_elem_value: unknown type %d\n", type); return -EINVAL; } if (copy_from_user(data->value.bytes.data, diff --git a/sound/core/device.c b/sound/core/device.c index df88defed17..41bec3075ae 100644 --- a/sound/core/device.c +++ b/sound/core/device.c @@ -41,29 +41,73 @@ * * Return: Zero if successful, or a negative error code on failure. */ -int snd_device_new(struct snd_card *card, snd_device_type_t type, +int snd_device_new(struct snd_card *card, enum snd_device_type type, void *device_data, struct snd_device_ops *ops) { struct snd_device *dev; + struct list_head *p; if (snd_BUG_ON(!card || !device_data || !ops)) return -ENXIO; dev = kzalloc(sizeof(*dev), GFP_KERNEL); if (dev == NULL) { - snd_printk(KERN_ERR "Cannot allocate device\n"); + dev_err(card->dev, "Cannot allocate device, type=%d\n", type); return -ENOMEM; } + INIT_LIST_HEAD(&dev->list); dev->card = card; dev->type = type; dev->state = SNDRV_DEV_BUILD; dev->device_data = device_data; dev->ops = ops; - list_add(&dev->list, &card->devices); /* add to the head of list */ + + /* insert the entry in an incrementally sorted list */ + list_for_each_prev(p, &card->devices) { + struct snd_device *pdev = list_entry(p, struct snd_device, list); + if ((unsigned int)pdev->type <= (unsigned int)type) + break; + } + + list_add(&dev->list, p); return 0; } - EXPORT_SYMBOL(snd_device_new); +static int __snd_device_disconnect(struct snd_device *dev) +{ + if (dev->state == SNDRV_DEV_REGISTERED) { + if (dev->ops->dev_disconnect && + dev->ops->dev_disconnect(dev)) + dev_err(dev->card->dev, "device disconnect failure\n"); + dev->state = SNDRV_DEV_DISCONNECTED; + } + return 0; +} + +static void __snd_device_free(struct snd_device *dev) +{ + /* unlink */ + list_del(&dev->list); + + __snd_device_disconnect(dev); + if (dev->ops->dev_free) { + if (dev->ops->dev_free(dev)) + dev_err(dev->card->dev, "device free failure\n"); + } + kfree(dev); +} + +static struct snd_device *look_for_dev(struct snd_card *card, void *device_data) +{ + struct snd_device *dev; + + list_for_each_entry(dev, &card->devices, list) + if (dev->device_data == device_data) + return dev; + + return NULL; +} + /** * snd_device_free - release the device from the card * @card: the card instance @@ -72,73 +116,33 @@ EXPORT_SYMBOL(snd_device_new); * Removes the device from the list on the card and invokes the * callbacks, dev_disconnect and dev_free, corresponding to the state. * Then release the device. - * - * Return: Zero if successful, or a negative error code on failure or if the - * device not found. */ -int snd_device_free(struct snd_card *card, void *device_data) +void snd_device_free(struct snd_card *card, void *device_data) { struct snd_device *dev; if (snd_BUG_ON(!card || !device_data)) - return -ENXIO; - list_for_each_entry(dev, &card->devices, list) { - if (dev->device_data != device_data) - continue; - /* unlink */ - list_del(&dev->list); - if (dev->state == SNDRV_DEV_REGISTERED && - dev->ops->dev_disconnect) - if (dev->ops->dev_disconnect(dev)) - snd_printk(KERN_ERR - "device disconnect failure\n"); - if (dev->ops->dev_free) { - if (dev->ops->dev_free(dev)) - snd_printk(KERN_ERR "device free failure\n"); - } - kfree(dev); - return 0; - } - snd_printd("device free %p (from %pF), not found\n", device_data, - __builtin_return_address(0)); - return -ENXIO; + return; + dev = look_for_dev(card, device_data); + if (dev) + __snd_device_free(dev); + else + dev_dbg(card->dev, "device free %p (from %pF), not found\n", + device_data, __builtin_return_address(0)); } - EXPORT_SYMBOL(snd_device_free); -/** - * snd_device_disconnect - disconnect the device - * @card: the card instance - * @device_data: the data pointer to disconnect - * - * Turns the device into the disconnection state, invoking - * dev_disconnect callback, if the device was already registered. - * - * Usually called from snd_card_disconnect(). - * - * Return: Zero if successful, or a negative error code on failure or if the - * device not found. - */ -int snd_device_disconnect(struct snd_card *card, void *device_data) +static int __snd_device_register(struct snd_device *dev) { - struct snd_device *dev; - - if (snd_BUG_ON(!card || !device_data)) - return -ENXIO; - list_for_each_entry(dev, &card->devices, list) { - if (dev->device_data != device_data) - continue; - if (dev->state == SNDRV_DEV_REGISTERED && - dev->ops->dev_disconnect) { - if (dev->ops->dev_disconnect(dev)) - snd_printk(KERN_ERR "device disconnect failure\n"); - dev->state = SNDRV_DEV_DISCONNECTED; + if (dev->state == SNDRV_DEV_BUILD) { + if (dev->ops->dev_register) { + int err = dev->ops->dev_register(dev); + if (err < 0) + return err; } - return 0; + dev->state = SNDRV_DEV_REGISTERED; } - snd_printd("device disconnect %p (from %pF), not found\n", device_data, - __builtin_return_address(0)); - return -ENXIO; + return 0; } /** @@ -157,26 +161,15 @@ int snd_device_disconnect(struct snd_card *card, void *device_data) int snd_device_register(struct snd_card *card, void *device_data) { struct snd_device *dev; - int err; if (snd_BUG_ON(!card || !device_data)) return -ENXIO; - list_for_each_entry(dev, &card->devices, list) { - if (dev->device_data != device_data) - continue; - if (dev->state == SNDRV_DEV_BUILD && dev->ops->dev_register) { - if ((err = dev->ops->dev_register(dev)) < 0) - return err; - dev->state = SNDRV_DEV_REGISTERED; - return 0; - } - snd_printd("snd_device_register busy\n"); - return -EBUSY; - } + dev = look_for_dev(card, device_data); + if (dev) + return __snd_device_register(dev); snd_BUG(); return -ENXIO; } - EXPORT_SYMBOL(snd_device_register); /* @@ -191,11 +184,9 @@ int snd_device_register_all(struct snd_card *card) if (snd_BUG_ON(!card)) return -ENXIO; list_for_each_entry(dev, &card->devices, list) { - if (dev->state == SNDRV_DEV_BUILD && dev->ops->dev_register) { - if ((err = dev->ops->dev_register(dev)) < 0) - return err; - dev->state = SNDRV_DEV_REGISTERED; - } + err = __snd_device_register(dev); + if (err < 0) + return err; } return 0; } @@ -211,8 +202,8 @@ int snd_device_disconnect_all(struct snd_card *card) if (snd_BUG_ON(!card)) return -ENXIO; - list_for_each_entry(dev, &card->devices, list) { - if (snd_device_disconnect(card, dev->device_data) < 0) + list_for_each_entry_reverse(dev, &card->devices, list) { + if (__snd_device_disconnect(dev) < 0) err = -ENXIO; } return err; @@ -222,24 +213,12 @@ int snd_device_disconnect_all(struct snd_card *card) * release all the devices on the card. * called from init.c */ -int snd_device_free_all(struct snd_card *card, snd_device_cmd_t cmd) +void snd_device_free_all(struct snd_card *card) { - struct snd_device *dev; - int err; - unsigned int range_low, range_high, type; + struct snd_device *dev, *next; if (snd_BUG_ON(!card)) - return -ENXIO; - range_low = (__force unsigned int)cmd * SNDRV_DEV_TYPE_RANGE_SIZE; - range_high = range_low + SNDRV_DEV_TYPE_RANGE_SIZE - 1; - __again: - list_for_each_entry(dev, &card->devices, list) { - type = (__force unsigned int)dev->type; - if (type >= range_low && type <= range_high) { - if ((err = snd_device_free(card, dev->device_data)) < 0) - return err; - goto __again; - } - } - return 0; + return; + list_for_each_entry_safe_reverse(dev, next, &card->devices, list) + __snd_device_free(dev); } diff --git a/sound/core/hrtimer.c b/sound/core/hrtimer.c index b8b31c433d6..886be7da989 100644 --- a/sound/core/hrtimer.c +++ b/sound/core/hrtimer.c @@ -126,8 +126,7 @@ static int __init snd_hrtimer_init(void) hrtimer_get_res(CLOCK_MONOTONIC, &tp); if (tp.tv_sec > 0 || !tp.tv_nsec) { - snd_printk(KERN_ERR - "snd-hrtimer: Invalid resolution %u.%09u", + pr_err("snd-hrtimer: Invalid resolution %u.%09u", (unsigned)tp.tv_sec, (unsigned)tp.tv_nsec); return -EINVAL; } diff --git a/sound/core/hwdep.c b/sound/core/hwdep.c index d105073298c..69459e5f712 100644 --- a/sound/core/hwdep.c +++ b/sound/core/hwdep.c @@ -375,7 +375,7 @@ int snd_hwdep_new(struct snd_card *card, char *id, int device, *rhwdep = NULL; hwdep = kzalloc(sizeof(*hwdep), GFP_KERNEL); if (hwdep == NULL) { - snd_printk(KERN_ERR "hwdep: cannot allocate\n"); + dev_err(card->dev, "hwdep: cannot allocate\n"); return -ENOMEM; } hwdep->card = card; @@ -395,6 +395,7 @@ int snd_hwdep_new(struct snd_card *card, char *id, int device, *rhwdep = hwdep; return 0; } +EXPORT_SYMBOL(snd_hwdep_new); static int snd_hwdep_free(struct snd_hwdep *hwdep) { @@ -415,37 +416,61 @@ static int snd_hwdep_dev_free(struct snd_device *device) static int snd_hwdep_dev_register(struct snd_device *device) { struct snd_hwdep *hwdep = device->device_data; + struct snd_card *card = hwdep->card; + struct device *dev; int err; char name[32]; mutex_lock(®ister_mutex); - if (snd_hwdep_search(hwdep->card, hwdep->device)) { + if (snd_hwdep_search(card, hwdep->device)) { mutex_unlock(®ister_mutex); return -EBUSY; } list_add_tail(&hwdep->list, &snd_hwdep_devices); sprintf(name, "hwC%iD%i", hwdep->card->number, hwdep->device); - if ((err = snd_register_device(SNDRV_DEVICE_TYPE_HWDEP, - hwdep->card, hwdep->device, - &snd_hwdep_f_ops, hwdep, name)) < 0) { - snd_printk(KERN_ERR "unable to register hardware dependent device %i:%i\n", - hwdep->card->number, hwdep->device); + dev = hwdep->dev; + if (!dev) + dev = snd_card_get_device_link(hwdep->card); + err = snd_register_device_for_dev(SNDRV_DEVICE_TYPE_HWDEP, + hwdep->card, hwdep->device, + &snd_hwdep_f_ops, hwdep, name, dev); + if (err < 0) { + dev_err(dev, + "unable to register hardware dependent device %i:%i\n", + card->number, hwdep->device); list_del(&hwdep->list); mutex_unlock(®ister_mutex); return err; } + + if (hwdep->groups) { + struct device *d = snd_get_device(SNDRV_DEVICE_TYPE_HWDEP, + hwdep->card, hwdep->device); + if (d) { + if (hwdep->private_data) + dev_set_drvdata(d, hwdep->private_data); + err = sysfs_create_groups(&d->kobj, hwdep->groups); + if (err < 0) + dev_warn(dev, + "hwdep %d:%d: cannot create sysfs groups\n", + card->number, hwdep->device); + put_device(d); + } + } + #ifdef CONFIG_SND_OSSEMUL hwdep->ossreg = 0; if (hwdep->oss_type >= 0) { if ((hwdep->oss_type == SNDRV_OSS_DEVICE_TYPE_DMFM) && (hwdep->device != 0)) { - snd_printk (KERN_WARNING "only hwdep device 0 can be registered as OSS direct FM device!\n"); + dev_warn(dev, + "only hwdep device 0 can be registered as OSS direct FM device!\n"); } else { if (snd_register_oss_device(hwdep->oss_type, - hwdep->card, hwdep->device, - &snd_hwdep_f_ops, hwdep, - hwdep->oss_dev) < 0) { - snd_printk(KERN_ERR "unable to register OSS compatibility device %i:%i\n", - hwdep->card->number, hwdep->device); + card, hwdep->device, + &snd_hwdep_f_ops, hwdep) < 0) { + dev_err(dev, + "unable to register OSS compatibility device %i:%i\n", + card->number, hwdep->device); } else hwdep->ossreg = 1; } @@ -543,5 +568,3 @@ static void __exit alsa_hwdep_exit(void) module_init(alsa_hwdep_init) module_exit(alsa_hwdep_exit) - -EXPORT_SYMBOL(snd_hwdep_new); diff --git a/sound/core/info.c b/sound/core/info.c index e79baa11b60..051d55b0552 100644 --- a/sound/core/info.c +++ b/sound/core/info.c @@ -418,9 +418,14 @@ static int snd_info_entry_release(struct inode *inode, struct file *file) if (entry->c.text.write) { entry->c.text.write(entry, data->wbuffer); if (data->wbuffer->error) { - snd_printk(KERN_WARNING "data write error to %s (%i)\n", - entry->name, - data->wbuffer->error); + if (entry->card) + dev_warn(entry->card->dev, "info: data write error to %s (%i)\n", + entry->name, + data->wbuffer->error); + else + pr_warn("ALSA: info: data write error to %s (%i)\n", + entry->name, + data->wbuffer->error); } } kfree(data->wbuffer->buffer); @@ -540,7 +545,7 @@ int __init snd_info_init(void) snd_oss_root = entry; } #endif -#if defined(CONFIG_SND_SEQUENCER) || defined(CONFIG_SND_SEQUENCER_MODULE) +#if IS_ENABLED(CONFIG_SND_SEQUENCER) { struct snd_info_entry *entry; if ((entry = snd_info_create_module_entry(THIS_MODULE, "seq", NULL)) == NULL) @@ -567,7 +572,7 @@ int __exit snd_info_done(void) snd_minor_info_done(); snd_info_version_done(); if (snd_proc_root) { -#if defined(CONFIG_SND_SEQUENCER) || defined(CONFIG_SND_SEQUENCER_MODULE) +#if IS_ENABLED(CONFIG_SND_SEQUENCER) snd_info_free_entry(snd_seq_root); #endif #ifdef CONFIG_SND_OSSEMUL diff --git a/sound/core/init.c b/sound/core/init.c index 0d42fcda0de..5ee83845c5d 100644 --- a/sound/core/init.c +++ b/sound/core/init.c @@ -28,6 +28,7 @@ #include <linux/time.h> #include <linux/ctype.h> #include <linux/pm.h> +#include <linux/completion.h> #include <sound/core.h> #include <sound/control.h> @@ -94,7 +95,7 @@ static int module_slot_match(struct module *module, int idx) return match; } -#if defined(CONFIG_SND_MIXER_OSS) || defined(CONFIG_SND_MIXER_OSS_MODULE) +#if IS_ENABLED(CONFIG_SND_MIXER_OSS) int (*snd_mixer_oss_notify_callback)(struct snd_card *card, int free_flag); EXPORT_SYMBOL(snd_mixer_oss_notify_callback); #endif @@ -112,11 +113,11 @@ static inline int init_info_for_card(struct snd_card *card) struct snd_info_entry *entry; if ((err = snd_info_card_register(card)) < 0) { - snd_printd("unable to create card info\n"); + dev_dbg(card->dev, "unable to create card info\n"); return err; } if ((entry = snd_info_create_card_entry(card, "id", card->proc_root)) == NULL) { - snd_printd("unable to create card entry\n"); + dev_dbg(card->dev, "unable to create card entry\n"); return err; } entry->c.text.read = snd_card_id_read; @@ -156,8 +157,17 @@ static int get_slot_from_bitmask(int mask, int (*check)(struct module *, int), return mask; /* unchanged */ } +static int snd_card_do_free(struct snd_card *card); +static const struct attribute_group *card_dev_attr_groups[]; + +static void release_card_device(struct device *dev) +{ + snd_card_do_free(dev_to_snd_card(dev)); +} + /** - * snd_card_create - create and initialize a soundcard structure + * snd_card_new - create and initialize a soundcard structure + * @parent: the parent device object * @idx: card index (address) [0 ... (SNDRV_CARDS-1)] * @xid: card identification (ASCII string) * @module: top level module for locking @@ -172,7 +182,7 @@ static int get_slot_from_bitmask(int mask, int (*check)(struct module *, int), * * Return: Zero if successful or a negative error code. */ -int snd_card_create(int idx, const char *xid, +int snd_card_new(struct device *parent, int idx, const char *xid, struct module *module, int extra_size, struct snd_card **card_ret) { @@ -188,6 +198,8 @@ int snd_card_create(int idx, const char *xid, card = kzalloc(sizeof(*card) + extra_size, GFP_KERNEL); if (!card) return -ENOMEM; + if (extra_size > 0) + card->private_data = (char *)card + sizeof(struct snd_card); if (xid) strlcpy(card->id, xid, sizeof(card->id)); err = 0; @@ -205,14 +217,16 @@ int snd_card_create(int idx, const char *xid, err = -ENODEV; if (err < 0) { mutex_unlock(&snd_card_mutex); - snd_printk(KERN_ERR "cannot find the slot for index %d (range 0-%i), error: %d\n", + dev_err(parent, "cannot find the slot for index %d (range 0-%i), error: %d\n", idx, snd_ecards_limit - 1, err); - goto __error; + kfree(card); + return err; } set_bit(idx, snd_cards_lock); /* lock it */ if (idx >= snd_ecards_limit) snd_ecards_limit = idx + 1; /* increase the limit */ mutex_unlock(&snd_card_mutex); + card->dev = parent; card->number = idx; card->module = module; INIT_LIST_HEAD(&card->devices); @@ -222,36 +236,42 @@ int snd_card_create(int idx, const char *xid, INIT_LIST_HEAD(&card->ctl_files); spin_lock_init(&card->files_lock); INIT_LIST_HEAD(&card->files_list); - init_waitqueue_head(&card->shutdown_sleep); - atomic_set(&card->refcount, 0); #ifdef CONFIG_PM mutex_init(&card->power_lock); init_waitqueue_head(&card->power_sleep); #endif + + device_initialize(&card->card_dev); + card->card_dev.parent = parent; + card->card_dev.class = sound_class; + card->card_dev.release = release_card_device; + card->card_dev.groups = card_dev_attr_groups; + err = kobject_set_name(&card->card_dev.kobj, "card%d", idx); + if (err < 0) + goto __error; + /* the control interface cannot be accessed from the user space until */ /* snd_cards_bitmask and snd_cards are set with snd_card_register */ err = snd_ctl_create(card); if (err < 0) { - snd_printk(KERN_ERR "unable to register control minors\n"); + dev_err(parent, "unable to register control minors\n"); goto __error; } err = snd_info_card_create(card); if (err < 0) { - snd_printk(KERN_ERR "unable to create card info\n"); + dev_err(parent, "unable to create card info\n"); goto __error_ctl; } - if (extra_size > 0) - card->private_data = (char *)card + sizeof(struct snd_card); *card_ret = card; return 0; __error_ctl: - snd_device_free_all(card, SNDRV_DEV_CMD_PRE); + snd_device_free_all(card); __error: - kfree(card); + put_device(&card->card_dev); return err; } -EXPORT_SYMBOL(snd_card_create); +EXPORT_SYMBOL(snd_card_new); /* return non-zero if a card is already locked */ int snd_card_locked(int card) @@ -394,7 +414,7 @@ int snd_card_disconnect(struct snd_card *card) /* phase 3: notify all connected devices about disconnection */ /* at this point, they cannot respond to any calls except release() */ -#if defined(CONFIG_SND_MIXER_OSS) || defined(CONFIG_SND_MIXER_OSS_MODULE) +#if IS_ENABLED(CONFIG_SND_MIXER_OSS) if (snd_mixer_oss_notify_callback) snd_mixer_oss_notify_callback(card, SND_MIXER_OSS_NOTIFY_DISCONNECT); #endif @@ -402,12 +422,12 @@ int snd_card_disconnect(struct snd_card *card) /* notify all devices that we are disconnected */ err = snd_device_disconnect_all(card); if (err < 0) - snd_printk(KERN_ERR "not all devices for card %i can be disconnected\n", card->number); + dev_err(card->dev, "not all devices for card %i can be disconnected\n", card->number); snd_info_card_disconnect(card); - if (card->card_dev) { - device_unregister(card->card_dev); - card->card_dev = NULL; + if (card->registered) { + device_del(&card->card_dev); + card->registered = false; } #ifdef CONFIG_PM wake_up(&card->power_sleep); @@ -430,81 +450,48 @@ EXPORT_SYMBOL(snd_card_disconnect); */ static int snd_card_do_free(struct snd_card *card) { -#if defined(CONFIG_SND_MIXER_OSS) || defined(CONFIG_SND_MIXER_OSS_MODULE) +#if IS_ENABLED(CONFIG_SND_MIXER_OSS) if (snd_mixer_oss_notify_callback) snd_mixer_oss_notify_callback(card, SND_MIXER_OSS_NOTIFY_FREE); #endif - if (snd_device_free_all(card, SNDRV_DEV_CMD_PRE) < 0) { - snd_printk(KERN_ERR "unable to free all devices (pre)\n"); - /* Fatal, but this situation should never occur */ - } - if (snd_device_free_all(card, SNDRV_DEV_CMD_NORMAL) < 0) { - snd_printk(KERN_ERR "unable to free all devices (normal)\n"); - /* Fatal, but this situation should never occur */ - } - if (snd_device_free_all(card, SNDRV_DEV_CMD_POST) < 0) { - snd_printk(KERN_ERR "unable to free all devices (post)\n"); - /* Fatal, but this situation should never occur */ - } + snd_device_free_all(card); if (card->private_free) card->private_free(card); snd_info_free_entry(card->proc_id); if (snd_info_card_free(card) < 0) { - snd_printk(KERN_WARNING "unable to free card info\n"); + dev_warn(card->dev, "unable to free card info\n"); /* Not fatal error */ } + if (card->release_completion) + complete(card->release_completion); kfree(card); return 0; } -/** - * snd_card_unref - release the reference counter - * @card: the card instance - * - * Decrements the reference counter. When it reaches to zero, wake up - * the sleeper and call the destructor if needed. - */ -void snd_card_unref(struct snd_card *card) -{ - if (atomic_dec_and_test(&card->refcount)) { - wake_up(&card->shutdown_sleep); - if (card->free_on_last_close) - snd_card_do_free(card); - } -} -EXPORT_SYMBOL(snd_card_unref); - int snd_card_free_when_closed(struct snd_card *card) { - int ret; - - atomic_inc(&card->refcount); - ret = snd_card_disconnect(card); - if (ret) { - atomic_dec(&card->refcount); + int ret = snd_card_disconnect(card); + if (ret) return ret; - } - - card->free_on_last_close = 1; - if (atomic_dec_and_test(&card->refcount)) - snd_card_do_free(card); + put_device(&card->card_dev); return 0; } - EXPORT_SYMBOL(snd_card_free_when_closed); int snd_card_free(struct snd_card *card) { - int ret = snd_card_disconnect(card); + struct completion released; + int ret; + + init_completion(&released); + card->release_completion = &released; + ret = snd_card_free_when_closed(card); if (ret) return ret; - /* wait, until all devices are ready for the free operation */ - wait_event(card->shutdown_sleep, !atomic_read(&card->refcount)); - snd_card_do_free(card); + wait_for_completion(&released); return 0; } - EXPORT_SYMBOL(snd_card_free); /* retrieve the last word of shortname or longname */ @@ -598,7 +585,7 @@ static void snd_card_set_id_no_lock(struct snd_card *card, const char *src, goto again; } /* last resort... */ - snd_printk(KERN_ERR "unable to set card id (%s)\n", id); + dev_err(card->dev, "unable to set card id (%s)\n", id); if (card->proc_root->name) strlcpy(card->id, card->proc_root->name, sizeof(card->id)); } @@ -626,15 +613,15 @@ static ssize_t card_id_show_attr(struct device *dev, struct device_attribute *attr, char *buf) { - struct snd_card *card = dev_get_drvdata(dev); - return snprintf(buf, PAGE_SIZE, "%s\n", card ? card->id : "(null)"); + struct snd_card *card = container_of(dev, struct snd_card, card_dev); + return snprintf(buf, PAGE_SIZE, "%s\n", card->id); } static ssize_t card_id_store_attr(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { - struct snd_card *card = dev_get_drvdata(dev); + struct snd_card *card = container_of(dev, struct snd_card, card_dev); char buf1[sizeof(card->id)]; size_t copy = count > sizeof(card->id) - 1 ? sizeof(card->id) - 1 : count; @@ -660,19 +647,32 @@ card_id_store_attr(struct device *dev, struct device_attribute *attr, return count; } -static struct device_attribute card_id_attrs = - __ATTR(id, S_IRUGO | S_IWUSR, card_id_show_attr, card_id_store_attr); +static DEVICE_ATTR(id, S_IRUGO | S_IWUSR, card_id_show_attr, card_id_store_attr); static ssize_t card_number_show_attr(struct device *dev, struct device_attribute *attr, char *buf) { - struct snd_card *card = dev_get_drvdata(dev); - return snprintf(buf, PAGE_SIZE, "%i\n", card ? card->number : -1); + struct snd_card *card = container_of(dev, struct snd_card, card_dev); + return snprintf(buf, PAGE_SIZE, "%i\n", card->number); } -static struct device_attribute card_number_attrs = - __ATTR(number, S_IRUGO, card_number_show_attr, NULL); +static DEVICE_ATTR(number, S_IRUGO, card_number_show_attr, NULL); + +static struct attribute *card_dev_attrs[] = { + &dev_attr_id.attr, + &dev_attr_number.attr, + NULL +}; + +static struct attribute_group card_dev_attr_group = { + .attrs = card_dev_attrs, +}; + +static const struct attribute_group *card_dev_attr_groups[] = { + &card_dev_attr_group, + NULL +}; /** * snd_card_register - register the soundcard @@ -692,12 +692,11 @@ int snd_card_register(struct snd_card *card) if (snd_BUG_ON(!card)) return -EINVAL; - if (!card->card_dev) { - card->card_dev = device_create(sound_class, card->dev, - MKDEV(0, 0), card, - "card%i", card->number); - if (IS_ERR(card->card_dev)) - card->card_dev = NULL; + if (!card->registered) { + err = device_add(&card->card_dev); + if (err < 0) + return err; + card->registered = true; } if ((err = snd_device_register_all(card)) < 0) @@ -723,19 +722,10 @@ int snd_card_register(struct snd_card *card) snd_cards[card->number] = card; mutex_unlock(&snd_card_mutex); init_info_for_card(card); -#if defined(CONFIG_SND_MIXER_OSS) || defined(CONFIG_SND_MIXER_OSS_MODULE) +#if IS_ENABLED(CONFIG_SND_MIXER_OSS) if (snd_mixer_oss_notify_callback) snd_mixer_oss_notify_callback(card, SND_MIXER_OSS_NOTIFY_REGISTER); #endif - if (card->card_dev) { - err = device_create_file(card->card_dev, &card_id_attrs); - if (err < 0) - return err; - err = device_create_file(card->card_dev, &card_number_attrs); - if (err < 0) - return err; - } - return 0; } @@ -908,7 +898,7 @@ int snd_card_file_add(struct snd_card *card, struct file *file) return -ENODEV; } list_add(&mfile->list, &card->files_list); - atomic_inc(&card->refcount); + get_device(&card->card_dev); spin_unlock(&card->files_lock); return 0; } @@ -947,11 +937,11 @@ int snd_card_file_remove(struct snd_card *card, struct file *file) } spin_unlock(&card->files_lock); if (!found) { - snd_printk(KERN_ERR "ALSA card file remove problem (%p)\n", file); + dev_err(card->dev, "card file remove problem (%p)\n", file); return -ENOENT; } kfree(found); - snd_card_unref(card); + put_device(&card->card_dev); return 0; } diff --git a/sound/core/isadma.c b/sound/core/isadma.c index e2b386156a4..31e8544d7f2 100644 --- a/sound/core/isadma.c +++ b/sound/core/isadma.c @@ -106,7 +106,7 @@ unsigned int snd_dma_pointer(unsigned long dma, unsigned int size) result = result1; #ifdef CONFIG_SND_DEBUG if (result > size) - snd_printk(KERN_ERR "pointer (0x%x) for DMA #%ld is greater than transfer size (0x%x)\n", result, dma, size); + pr_err("ALSA: pointer (0x%x) for DMA #%ld is greater than transfer size (0x%x)\n", result, dma, size); #endif if (result >= size || result == 0) return 0; diff --git a/sound/core/memalloc.c b/sound/core/memalloc.c index 4595f93d151..082509eb805 100644 --- a/sound/core/memalloc.c +++ b/sound/core/memalloc.c @@ -207,7 +207,7 @@ int snd_dma_alloc_pages(int type, struct device *device, size_t size, break; #endif default: - printk(KERN_ERR "snd-malloc: invalid device type %d\n", type); + pr_err("snd-malloc: invalid device type %d\n", type); dmab->area = NULL; dmab->addr = 0; return -ENXIO; @@ -284,7 +284,7 @@ void snd_dma_free_pages(struct snd_dma_buffer *dmab) break; #endif default: - printk(KERN_ERR "snd-malloc: invalid device type %d\n", dmab->dev.type); + pr_err("snd-malloc: invalid device type %d\n", dmab->dev.type); } } diff --git a/sound/core/oss/mixer_oss.c b/sound/core/oss/mixer_oss.c index e8a1d18774b..5e6349f00ec 100644 --- a/sound/core/oss/mixer_oss.c +++ b/sound/core/oss/mixer_oss.c @@ -1187,7 +1187,8 @@ static void snd_mixer_oss_proc_write(struct snd_info_entry *entry, if (oss_mixer_names[ch] && strcmp(oss_mixer_names[ch], str) == 0) break; if (ch >= SNDRV_OSS_MAX_MIXERS) { - snd_printk(KERN_ERR "mixer_oss: invalid OSS volume '%s'\n", str); + pr_err("ALSA: mixer_oss: invalid OSS volume '%s'\n", + str); continue; } cptr = snd_info_get_str(str, cptr, sizeof(str)); @@ -1201,7 +1202,7 @@ static void snd_mixer_oss_proc_write(struct snd_info_entry *entry, snd_info_get_str(idxstr, cptr, sizeof(idxstr)); idx = simple_strtoul(idxstr, NULL, 10); if (idx >= 0x4000) { /* too big */ - snd_printk(KERN_ERR "mixer_oss: invalid index %d\n", idx); + pr_err("ALSA: mixer_oss: invalid index %d\n", idx); continue; } mutex_lock(&mixer->reg_mutex); @@ -1212,7 +1213,7 @@ static void snd_mixer_oss_proc_write(struct snd_info_entry *entry, goto __unlock; tbl = kmalloc(sizeof(*tbl), GFP_KERNEL); if (! tbl) { - snd_printk(KERN_ERR "mixer_oss: no memory\n"); + pr_err("ALSA: mixer_oss: no memory\n"); goto __unlock; } tbl->oss_id = ch; @@ -1343,20 +1344,18 @@ static int snd_mixer_oss_notify_handler(struct snd_card *card, int cmd) struct snd_mixer_oss *mixer; if (cmd == SND_MIXER_OSS_NOTIFY_REGISTER) { - char name[128]; int idx, err; mixer = kcalloc(2, sizeof(*mixer), GFP_KERNEL); if (mixer == NULL) return -ENOMEM; mutex_init(&mixer->reg_mutex); - sprintf(name, "mixer%i%i", card->number, 0); if ((err = snd_register_oss_device(SNDRV_OSS_DEVICE_TYPE_MIXER, card, 0, - &snd_mixer_oss_f_ops, card, - name)) < 0) { - snd_printk(KERN_ERR "unable to register OSS mixer device %i:%i\n", - card->number, 0); + &snd_mixer_oss_f_ops, card)) < 0) { + dev_err(card->dev, + "unable to register OSS mixer device %i:%i\n", + card->number, 0); kfree(mixer); return err; } @@ -1365,7 +1364,8 @@ static int snd_mixer_oss_notify_handler(struct snd_card *card, int cmd) if (*card->mixername) strlcpy(mixer->name, card->mixername, sizeof(mixer->name)); else - strlcpy(mixer->name, name, sizeof(mixer->name)); + snprintf(mixer->name, sizeof(mixer->name), + "mixer%i", card->number); #ifdef SNDRV_OSS_INFO_DEV_MIXERS snd_oss_info_register(SNDRV_OSS_INFO_DEV_MIXERS, card->number, diff --git a/sound/core/oss/pcm_oss.c b/sound/core/oss/pcm_oss.c index 4c1cc51772e..ada69d7a8d7 100644 --- a/sound/core/oss/pcm_oss.c +++ b/sound/core/oss/pcm_oss.c @@ -854,7 +854,7 @@ static int snd_pcm_oss_change_params(struct snd_pcm_substream *substream) params = kmalloc(sizeof(*params), GFP_KERNEL); sparams = kmalloc(sizeof(*sparams), GFP_KERNEL); if (!sw_params || !params || !sparams) { - snd_printd("No memory\n"); + pcm_dbg(substream->pcm, "No memory\n"); err = -ENOMEM; goto failure; } @@ -877,7 +877,7 @@ static int snd_pcm_oss_change_params(struct snd_pcm_substream *substream) } err = snd_pcm_hw_param_mask(substream, sparams, SNDRV_PCM_HW_PARAM_ACCESS, &mask); if (err < 0) { - snd_printd("No usable accesses\n"); + pcm_dbg(substream->pcm, "No usable accesses\n"); err = -EINVAL; goto failure; } @@ -902,7 +902,7 @@ static int snd_pcm_oss_change_params(struct snd_pcm_substream *substream) break; } if ((__force int)sformat > (__force int)SNDRV_PCM_FORMAT_LAST) { - snd_printd("Cannot find a format!!!\n"); + pcm_dbg(substream->pcm, "Cannot find a format!!!\n"); err = -EINVAL; goto failure; } @@ -942,14 +942,16 @@ static int snd_pcm_oss_change_params(struct snd_pcm_substream *substream) if ((err = snd_pcm_plug_format_plugins(substream, params, sparams)) < 0) { - snd_printd("snd_pcm_plug_format_plugins failed: %i\n", err); + pcm_dbg(substream->pcm, + "snd_pcm_plug_format_plugins failed: %i\n", err); snd_pcm_oss_plugin_clear(substream); goto failure; } if (runtime->oss.plugin_first) { struct snd_pcm_plugin *plugin; if ((err = snd_pcm_plugin_build_io(substream, sparams, &plugin)) < 0) { - snd_printd("snd_pcm_plugin_build_io failed: %i\n", err); + pcm_dbg(substream->pcm, + "snd_pcm_plugin_build_io failed: %i\n", err); snd_pcm_oss_plugin_clear(substream); goto failure; } @@ -983,7 +985,7 @@ static int snd_pcm_oss_change_params(struct snd_pcm_substream *substream) snd_pcm_kernel_ioctl(substream, SNDRV_PCM_IOCTL_DROP, NULL); if ((err = snd_pcm_kernel_ioctl(substream, SNDRV_PCM_IOCTL_HW_PARAMS, sparams)) < 0) { - snd_printd("HW_PARAMS failed: %i\n", err); + pcm_dbg(substream->pcm, "HW_PARAMS failed: %i\n", err); goto failure; } @@ -1016,7 +1018,7 @@ static int snd_pcm_oss_change_params(struct snd_pcm_substream *substream) } if ((err = snd_pcm_kernel_ioctl(substream, SNDRV_PCM_IOCTL_SW_PARAMS, sw_params)) < 0) { - snd_printd("SW_PARAMS failed: %i\n", err); + pcm_dbg(substream->pcm, "SW_PARAMS failed: %i\n", err); goto failure; } @@ -1110,7 +1112,8 @@ static int snd_pcm_oss_prepare(struct snd_pcm_substream *substream) err = snd_pcm_kernel_ioctl(substream, SNDRV_PCM_IOCTL_PREPARE, NULL); if (err < 0) { - snd_printd("snd_pcm_oss_prepare: SNDRV_PCM_IOCTL_PREPARE failed\n"); + pcm_dbg(substream->pcm, + "snd_pcm_oss_prepare: SNDRV_PCM_IOCTL_PREPARE failed\n"); return err; } runtime->oss.prepare = 0; @@ -1175,12 +1178,10 @@ snd_pcm_sframes_t snd_pcm_oss_write3(struct snd_pcm_substream *substream, const if (runtime->status->state == SNDRV_PCM_STATE_XRUN || runtime->status->state == SNDRV_PCM_STATE_SUSPENDED) { #ifdef OSS_DEBUG - if (runtime->status->state == SNDRV_PCM_STATE_XRUN) - printk(KERN_DEBUG "pcm_oss: write: " - "recovering from XRUN\n"); - else - printk(KERN_DEBUG "pcm_oss: write: " - "recovering from SUSPEND\n"); + pcm_dbg(substream->pcm, + "pcm_oss: write: recovering from %s\n", + runtime->status->state == SNDRV_PCM_STATE_XRUN ? + "XRUN" : "SUSPEND"); #endif ret = snd_pcm_oss_prepare(substream); if (ret < 0) @@ -1213,12 +1214,10 @@ snd_pcm_sframes_t snd_pcm_oss_read3(struct snd_pcm_substream *substream, char *p if (runtime->status->state == SNDRV_PCM_STATE_XRUN || runtime->status->state == SNDRV_PCM_STATE_SUSPENDED) { #ifdef OSS_DEBUG - if (runtime->status->state == SNDRV_PCM_STATE_XRUN) - printk(KERN_DEBUG "pcm_oss: read: " - "recovering from XRUN\n"); - else - printk(KERN_DEBUG "pcm_oss: read: " - "recovering from SUSPEND\n"); + pcm_dbg(substream->pcm, + "pcm_oss: read: recovering from %s\n", + runtime->status->state == SNDRV_PCM_STATE_XRUN ? + "XRUN" : "SUSPEND"); #endif ret = snd_pcm_kernel_ioctl(substream, SNDRV_PCM_IOCTL_DRAIN, NULL); if (ret < 0) @@ -1261,12 +1260,10 @@ snd_pcm_sframes_t snd_pcm_oss_writev3(struct snd_pcm_substream *substream, void if (runtime->status->state == SNDRV_PCM_STATE_XRUN || runtime->status->state == SNDRV_PCM_STATE_SUSPENDED) { #ifdef OSS_DEBUG - if (runtime->status->state == SNDRV_PCM_STATE_XRUN) - printk(KERN_DEBUG "pcm_oss: writev: " - "recovering from XRUN\n"); - else - printk(KERN_DEBUG "pcm_oss: writev: " - "recovering from SUSPEND\n"); + pcm_dbg(substream->pcm, + "pcm_oss: writev: recovering from %s\n", + runtime->status->state == SNDRV_PCM_STATE_XRUN ? + "XRUN" : "SUSPEND"); #endif ret = snd_pcm_oss_prepare(substream); if (ret < 0) @@ -1299,12 +1296,10 @@ snd_pcm_sframes_t snd_pcm_oss_readv3(struct snd_pcm_substream *substream, void * if (runtime->status->state == SNDRV_PCM_STATE_XRUN || runtime->status->state == SNDRV_PCM_STATE_SUSPENDED) { #ifdef OSS_DEBUG - if (runtime->status->state == SNDRV_PCM_STATE_XRUN) - printk(KERN_DEBUG "pcm_oss: readv: " - "recovering from XRUN\n"); - else - printk(KERN_DEBUG "pcm_oss: readv: " - "recovering from SUSPEND\n"); + pcm_dbg(substream->pcm, + "pcm_oss: readv: recovering from %s\n", + runtime->status->state == SNDRV_PCM_STATE_XRUN ? + "XRUN" : "SUSPEND"); #endif ret = snd_pcm_kernel_ioctl(substream, SNDRV_PCM_IOCTL_DRAIN, NULL); if (ret < 0) @@ -1561,7 +1556,7 @@ static int snd_pcm_oss_sync1(struct snd_pcm_substream *substream, size_t size) init_waitqueue_entry(&wait, current); add_wait_queue(&runtime->sleep, &wait); #ifdef OSS_DEBUG - printk(KERN_DEBUG "sync1: size = %li\n", size); + pcm_dbg(substream->pcm, "sync1: size = %li\n", size); #endif while (1) { result = snd_pcm_oss_write2(substream, runtime->oss.buffer, size, 1); @@ -1587,7 +1582,8 @@ static int snd_pcm_oss_sync1(struct snd_pcm_substream *substream, size_t size) break; } if (res == 0) { - snd_printk(KERN_ERR "OSS sync error - DMA timeout\n"); + pcm_err(substream->pcm, + "OSS sync error - DMA timeout\n"); result = -EIO; break; } @@ -1618,7 +1614,7 @@ static int snd_pcm_oss_sync(struct snd_pcm_oss_file *pcm_oss_file) mutex_lock(&runtime->oss.params_lock); if (runtime->oss.buffer_used > 0) { #ifdef OSS_DEBUG - printk(KERN_DEBUG "sync: buffer_used\n"); + pcm_dbg(substream->pcm, "sync: buffer_used\n"); #endif size = (8 * (runtime->oss.period_bytes - runtime->oss.buffer_used) + 7) / width; snd_pcm_format_set_silence(format, @@ -1631,7 +1627,7 @@ static int snd_pcm_oss_sync(struct snd_pcm_oss_file *pcm_oss_file) } } else if (runtime->oss.period_ptr > 0) { #ifdef OSS_DEBUG - printk(KERN_DEBUG "sync: period_ptr\n"); + pcm_dbg(substream->pcm, "sync: period_ptr\n"); #endif size = runtime->oss.period_bytes - runtime->oss.period_ptr; snd_pcm_format_set_silence(format, @@ -1983,7 +1979,7 @@ static int snd_pcm_oss_set_trigger(struct snd_pcm_oss_file *pcm_oss_file, int tr int err, cmd; #ifdef OSS_DEBUG - printk(KERN_DEBUG "pcm_oss: trigger = 0x%x\n", trigger); + pcm_dbg(substream->pcm, "pcm_oss: trigger = 0x%x\n", trigger); #endif psubstream = pcm_oss_file->streams[SNDRV_PCM_STREAM_PLAYBACK]; @@ -2203,9 +2199,9 @@ static int snd_pcm_oss_get_space(struct snd_pcm_oss_file *pcm_oss_file, int stre } #ifdef OSS_DEBUG - printk(KERN_DEBUG "pcm_oss: space: bytes = %i, fragments = %i, " - "fragstotal = %i, fragsize = %i\n", - info.bytes, info.fragments, info.fragstotal, info.fragsize); + pcm_dbg(substream->pcm, + "pcm_oss: space: bytes = %i, fragments = %i, fragstotal = %i, fragsize = %i\n", + info.bytes, info.fragments, info.fragstotal, info.fragsize); #endif if (copy_to_user(_info, &info, sizeof(info))) return -EFAULT; @@ -2215,7 +2211,7 @@ static int snd_pcm_oss_get_space(struct snd_pcm_oss_file *pcm_oss_file, int stre static int snd_pcm_oss_get_mapbuf(struct snd_pcm_oss_file *pcm_oss_file, int stream, struct buffmem_desc __user * _info) { // it won't be probably implemented - // snd_printd("TODO: snd_pcm_oss_get_mapbuf\n"); + // pr_debug("TODO: snd_pcm_oss_get_mapbuf\n"); return -EINVAL; } @@ -2519,7 +2515,7 @@ static long snd_pcm_oss_ioctl(struct file *file, unsigned int cmd, unsigned long if (((cmd >> 8) & 0xff) != 'P') return -EINVAL; #ifdef OSS_DEBUG - printk(KERN_DEBUG "pcm_oss: ioctl = 0x%x\n", cmd); + pr_debug("pcm_oss: ioctl = 0x%x\n", cmd); #endif switch (cmd) { case SNDCTL_DSP_RESET: @@ -2646,7 +2642,7 @@ static long snd_pcm_oss_ioctl(struct file *file, unsigned int cmd, unsigned long case SNDCTL_DSP_PROFILE: return 0; /* silently ignore */ default: - snd_printd("pcm_oss: unknown command = 0x%x\n", cmd); + pr_debug("pcm_oss: unknown command = 0x%x\n", cmd); } return -EINVAL; } @@ -2673,8 +2669,9 @@ static ssize_t snd_pcm_oss_read(struct file *file, char __user *buf, size_t coun #else { ssize_t res = snd_pcm_oss_read1(substream, buf, count); - printk(KERN_DEBUG "pcm_oss: read %li bytes " - "(returned %li bytes)\n", (long)count, (long)res); + pcm_dbg(substream->pcm, + "pcm_oss: read %li bytes (returned %li bytes)\n", + (long)count, (long)res); return res; } #endif @@ -2693,7 +2690,7 @@ static ssize_t snd_pcm_oss_write(struct file *file, const char __user *buf, size substream->f_flags = file->f_flags & O_NONBLOCK; result = snd_pcm_oss_write1(substream, buf, count); #ifdef OSS_DEBUG - printk(KERN_DEBUG "pcm_oss: write %li bytes (wrote %li bytes)\n", + pcm_dbg(substream->pcm, "pcm_oss: write %li bytes (wrote %li bytes)\n", (long)count, (long)result); #endif return result; @@ -2772,7 +2769,7 @@ static int snd_pcm_oss_mmap(struct file *file, struct vm_area_struct *area) int err; #ifdef OSS_DEBUG - printk(KERN_DEBUG "pcm_oss: mmap begin\n"); + pr_debug("pcm_oss: mmap begin\n"); #endif pcm_oss_file = file->private_data; switch ((area->vm_flags & (VM_READ | VM_WRITE))) { @@ -2822,7 +2819,7 @@ static int snd_pcm_oss_mmap(struct file *file, struct vm_area_struct *area) runtime->silence_threshold = 0; runtime->silence_size = 0; #ifdef OSS_DEBUG - printk(KERN_DEBUG "pcm_oss: mmap ok, bytes = 0x%x\n", + pr_debug("pcm_oss: mmap ok, bytes = 0x%x\n", runtime->oss.mmap_bytes); #endif /* In mmap mode we never stop */ @@ -3007,12 +3004,10 @@ static const struct file_operations snd_pcm_oss_f_reg = static void register_oss_dsp(struct snd_pcm *pcm, int index) { - char name[128]; - sprintf(name, "dsp%i%i", pcm->card->number, pcm->device); if (snd_register_oss_device(SNDRV_OSS_DEVICE_TYPE_PCM, pcm->card, index, &snd_pcm_oss_f_reg, - pcm, name) < 0) { - snd_printk(KERN_ERR "unable to register OSS PCM device %i:%i\n", + pcm) < 0) { + pcm_err(pcm, "unable to register OSS PCM device %i:%i\n", pcm->card->number, pcm->device); } } @@ -3093,12 +3088,12 @@ static int __init alsa_pcm_oss_init(void) /* check device map table */ for (i = 0; i < SNDRV_CARDS; i++) { if (dsp_map[i] < 0 || dsp_map[i] >= SNDRV_PCM_DEVICES) { - snd_printk(KERN_ERR "invalid dsp_map[%d] = %d\n", + pr_err("ALSA: pcm_oss: invalid dsp_map[%d] = %d\n", i, dsp_map[i]); dsp_map[i] = 0; } if (adsp_map[i] < 0 || adsp_map[i] >= SNDRV_PCM_DEVICES) { - snd_printk(KERN_ERR "invalid adsp_map[%d] = %d\n", + pr_err("ALSA: pcm_oss: invalid adsp_map[%d] = %d\n", i, adsp_map[i]); adsp_map[i] = 1; } diff --git a/sound/core/pcm.c b/sound/core/pcm.c index e1e9e0c999f..43932e8dce6 100644 --- a/sound/core/pcm.c +++ b/sound/core/pcm.c @@ -295,7 +295,7 @@ static const char *snd_pcm_state_name(snd_pcm_state_t state) return snd_pcm_state_names[(__force int)state]; } -#if defined(CONFIG_SND_PCM_OSS) || defined(CONFIG_SND_PCM_OSS_MODULE) +#if IS_ENABLED(CONFIG_SND_PCM_OSS) #include <linux/soundcard.h> static const char *snd_pcm_oss_format_name(int format) @@ -338,7 +338,8 @@ static void snd_pcm_proc_info_read(struct snd_pcm_substream *substream, info = kmalloc(sizeof(*info), GFP_KERNEL); if (! info) { - printk(KERN_DEBUG "snd_pcm_proc_info_read: cannot malloc\n"); + pcm_dbg(substream->pcm, + "snd_pcm_proc_info_read: cannot malloc\n"); return; } @@ -398,7 +399,7 @@ static void snd_pcm_substream_proc_hw_params_read(struct snd_info_entry *entry, snd_iprintf(buffer, "rate: %u (%u/%u)\n", runtime->rate, runtime->rate_num, runtime->rate_den); snd_iprintf(buffer, "period_size: %lu\n", runtime->period_size); snd_iprintf(buffer, "buffer_size: %lu\n", runtime->buffer_size); -#if defined(CONFIG_SND_PCM_OSS) || defined(CONFIG_SND_PCM_OSS_MODULE) +#if IS_ENABLED(CONFIG_SND_PCM_OSS) if (substream->oss.oss) { snd_iprintf(buffer, "OSS format: %s\n", snd_pcm_oss_format_name(runtime->oss.format)); snd_iprintf(buffer, "OSS channels: %u\n", runtime->oss.channels); @@ -651,7 +652,7 @@ int snd_pcm_new_stream(struct snd_pcm *pcm, int stream, int substream_count) struct snd_pcm_str *pstr = &pcm->streams[stream]; struct snd_pcm_substream *substream, *prev; -#if defined(CONFIG_SND_PCM_OSS) || defined(CONFIG_SND_PCM_OSS_MODULE) +#if IS_ENABLED(CONFIG_SND_PCM_OSS) mutex_init(&pstr->oss.setup_mutex); #endif pstr->stream = stream; @@ -660,7 +661,7 @@ int snd_pcm_new_stream(struct snd_pcm *pcm, int stream, int substream_count) if (substream_count > 0 && !pcm->internal) { err = snd_pcm_stream_proc_init(pstr); if (err < 0) { - snd_printk(KERN_ERR "Error in snd_pcm_stream_proc_init\n"); + pcm_err(pcm, "Error in snd_pcm_stream_proc_init\n"); return err; } } @@ -668,7 +669,7 @@ int snd_pcm_new_stream(struct snd_pcm *pcm, int stream, int substream_count) for (idx = 0, prev = NULL; idx < substream_count; idx++) { substream = kzalloc(sizeof(*substream), GFP_KERNEL); if (substream == NULL) { - snd_printk(KERN_ERR "Cannot allocate PCM substream\n"); + pcm_err(pcm, "Cannot allocate PCM substream\n"); return -ENOMEM; } substream->pcm = pcm; @@ -685,7 +686,8 @@ int snd_pcm_new_stream(struct snd_pcm *pcm, int stream, int substream_count) if (!pcm->internal) { err = snd_pcm_substream_proc_init(substream); if (err < 0) { - snd_printk(KERN_ERR "Error in snd_pcm_stream_proc_init\n"); + pcm_err(pcm, + "Error in snd_pcm_stream_proc_init\n"); if (prev == NULL) pstr->substream = NULL; else @@ -724,7 +726,7 @@ static int _snd_pcm_new(struct snd_card *card, const char *id, int device, *rpcm = NULL; pcm = kzalloc(sizeof(*pcm), GFP_KERNEL); if (pcm == NULL) { - snd_printk(KERN_ERR "Cannot allocate PCM\n"); + dev_err(card->dev, "Cannot allocate PCM\n"); return -ENOMEM; } pcm->card = card; @@ -807,7 +809,7 @@ EXPORT_SYMBOL(snd_pcm_new_internal); static void snd_pcm_free_stream(struct snd_pcm_str * pstr) { struct snd_pcm_substream *substream, *substream_next; -#if defined(CONFIG_SND_PCM_OSS) || defined(CONFIG_SND_PCM_OSS_MODULE) +#if IS_ENABLED(CONFIG_SND_PCM_OSS) struct snd_pcm_oss_setup *setup, *setupn; #endif substream = pstr->substream; @@ -819,7 +821,7 @@ static void snd_pcm_free_stream(struct snd_pcm_str * pstr) substream = substream_next; } snd_pcm_stream_proc_done(pstr); -#if defined(CONFIG_SND_PCM_OSS) || defined(CONFIG_SND_PCM_OSS_MODULE) +#if IS_ENABLED(CONFIG_SND_PCM_OSS) for (setup = pstr->oss.setup_list; setup; setup = setupn) { setupn = setup->next; kfree(setup->task_name); @@ -1016,8 +1018,20 @@ static ssize_t show_pcm_class(struct device *dev, return snprintf(buf, PAGE_SIZE, "%s\n", str); } -static struct device_attribute pcm_attrs = - __ATTR(pcm_class, S_IRUGO, show_pcm_class, NULL); +static DEVICE_ATTR(pcm_class, S_IRUGO, show_pcm_class, NULL); +static struct attribute *pcm_dev_attrs[] = { + &dev_attr_pcm_class.attr, + NULL +}; + +static struct attribute_group pcm_dev_attr_group = { + .attrs = pcm_dev_attrs, +}; + +static const struct attribute_group *pcm_dev_attr_groups[] = { + &pcm_dev_attr_group, + NULL +}; static int snd_pcm_dev_register(struct snd_device *device) { @@ -1067,8 +1081,18 @@ static int snd_pcm_dev_register(struct snd_device *device) mutex_unlock(®ister_mutex); return err; } - snd_add_device_sysfs_file(devtype, pcm->card, pcm->device, - &pcm_attrs); + + dev = snd_get_device(devtype, pcm->card, pcm->device); + if (dev) { + err = sysfs_create_groups(&dev->kobj, + pcm_dev_attr_groups); + if (err < 0) + dev_warn(dev, + "pcm %d:%d: cannot create sysfs groups\n", + pcm->card->number, pcm->device); + put_device(dev); + } + for (substream = pcm->streams[cidx].substream; substream; substream = substream->next) snd_pcm_timer_init(substream); } diff --git a/sound/core/pcm_lib.c b/sound/core/pcm_lib.c index a2104671f51..ce83def9f43 100644 --- a/sound/core/pcm_lib.c +++ b/sound/core/pcm_lib.c @@ -174,7 +174,7 @@ static void xrun(struct snd_pcm_substream *substream) if (xrun_debug(substream, XRUN_DEBUG_BASIC)) { char name[16]; snd_pcm_debug_name(substream, name, sizeof(name)); - snd_printd(KERN_DEBUG "XRUN: %s\n", name); + pcm_warn(substream->pcm, "XRUN: %s\n", name); dump_stack_on_xrun(substream); } } @@ -184,9 +184,7 @@ static void xrun(struct snd_pcm_substream *substream) do { \ if (xrun_debug(substream, XRUN_DEBUG_BASIC)) { \ xrun_log_show(substream); \ - if (snd_printd_ratelimit()) { \ - snd_printd("PCM: " fmt, ##args); \ - } \ + pr_err_ratelimited("ALSA: PCM: " fmt, ##args); \ dump_stack_on_xrun(substream); \ } \ } while (0) @@ -253,7 +251,7 @@ static void xrun_log_show(struct snd_pcm_substream *substream) entry = &log->entries[idx]; if (entry->period_size == 0) break; - snd_printd("hwptr log: %s: %sj=%lu, pos=%ld/%ld/%ld, " + pr_info("hwptr log: %s: %sj=%lu, pos=%ld/%ld/%ld, " "hwptr=%ld/%ld\n", name, entry->in_interrupt ? "[Q] " : "", entry->jiffies, @@ -342,14 +340,14 @@ static int snd_pcm_update_hw_ptr0(struct snd_pcm_substream *substream, return -EPIPE; } if (pos >= runtime->buffer_size) { - if (snd_printd_ratelimit()) { + if (printk_ratelimit()) { char name[16]; snd_pcm_debug_name(substream, name, sizeof(name)); xrun_log_show(substream); - snd_printd(KERN_ERR "BUG: %s, pos = %ld, " - "buffer size = %ld, period size = %ld\n", - name, pos, runtime->buffer_size, - runtime->period_size); + pcm_err(substream->pcm, + "BUG: %s, pos = %ld, buffer size = %ld, period size = %ld\n", + name, pos, runtime->buffer_size, + runtime->period_size); } pos = 0; } @@ -394,8 +392,8 @@ static int snd_pcm_update_hw_ptr0(struct snd_pcm_substream *substream, XRUN_DEBUG_PERIODUPDATE : XRUN_DEBUG_HWPTRUPDATE)) { char name[16]; snd_pcm_debug_name(substream, name, sizeof(name)); - snd_printd("%s_update: %s: pos=%u/%u/%u, " - "hwptr=%ld/%ld/%ld/%ld\n", + pcm_dbg(substream->pcm, + "%s_update: %s: pos=%u/%u/%u, hwptr=%ld/%ld/%ld/%ld\n", in_interrupt ? "period" : "hwptr", name, (unsigned int)pos, @@ -1242,6 +1240,7 @@ int snd_pcm_hw_constraint_mask64(struct snd_pcm_runtime *runtime, snd_pcm_hw_par return -EINVAL; return 0; } +EXPORT_SYMBOL(snd_pcm_hw_constraint_mask64); /** * snd_pcm_hw_constraint_integer - apply an integer constraint to an interval @@ -1941,8 +1940,9 @@ static int wait_for_avail(struct snd_pcm_substream *substream, continue; } if (!tout) { - snd_printd("%s write error (DMA or IRQ trouble?)\n", - is_playback ? "playback" : "capture"); + pcm_dbg(substream->pcm, + "%s write error (DMA or IRQ trouble?)\n", + is_playback ? "playback" : "capture"); err = -EIO; break; } diff --git a/sound/core/pcm_native.c b/sound/core/pcm_native.c index 01a5e05ede9..b653ab001fb 100644 --- a/sound/core/pcm_native.c +++ b/sound/core/pcm_native.c @@ -190,12 +190,12 @@ int snd_pcm_hw_refine(struct snd_pcm_substream *substream, if (!(params->rmask & (1 << k))) continue; #ifdef RULES_DEBUG - printk(KERN_DEBUG "%s = ", snd_pcm_hw_param_names[k]); - printk("%04x%04x%04x%04x -> ", m->bits[3], m->bits[2], m->bits[1], m->bits[0]); + pr_debug("%s = ", snd_pcm_hw_param_names[k]); + pr_cont("%04x%04x%04x%04x -> ", m->bits[3], m->bits[2], m->bits[1], m->bits[0]); #endif changed = snd_mask_refine(m, constrs_mask(constrs, k)); #ifdef RULES_DEBUG - printk("%04x%04x%04x%04x\n", m->bits[3], m->bits[2], m->bits[1], m->bits[0]); + pr_cont("%04x%04x%04x%04x\n", m->bits[3], m->bits[2], m->bits[1], m->bits[0]); #endif if (changed) params->cmask |= 1 << k; @@ -210,21 +210,21 @@ int snd_pcm_hw_refine(struct snd_pcm_substream *substream, if (!(params->rmask & (1 << k))) continue; #ifdef RULES_DEBUG - printk(KERN_DEBUG "%s = ", snd_pcm_hw_param_names[k]); + pr_debug("%s = ", snd_pcm_hw_param_names[k]); if (i->empty) - printk("empty"); + pr_cont("empty"); else - printk("%c%u %u%c", + pr_cont("%c%u %u%c", i->openmin ? '(' : '[', i->min, i->max, i->openmax ? ')' : ']'); - printk(" -> "); + pr_cont(" -> "); #endif changed = snd_interval_refine(i, constrs_interval(constrs, k)); #ifdef RULES_DEBUG if (i->empty) - printk("empty\n"); + pr_cont("empty\n"); else - printk("%c%u %u%c\n", + pr_cont("%c%u %u%c\n", i->openmin ? '(' : '[', i->min, i->max, i->openmax ? ')' : ']'); #endif @@ -255,18 +255,18 @@ int snd_pcm_hw_refine(struct snd_pcm_substream *substream, if (!doit) continue; #ifdef RULES_DEBUG - printk(KERN_DEBUG "Rule %d [%p]: ", k, r->func); + pr_debug("Rule %d [%p]: ", k, r->func); if (r->var >= 0) { - printk("%s = ", snd_pcm_hw_param_names[r->var]); + pr_cont("%s = ", snd_pcm_hw_param_names[r->var]); if (hw_is_mask(r->var)) { m = hw_param_mask(params, r->var); - printk("%x", *m->bits); + pr_cont("%x", *m->bits); } else { i = hw_param_interval(params, r->var); if (i->empty) - printk("empty"); + pr_cont("empty"); else - printk("%c%u %u%c", + pr_cont("%c%u %u%c", i->openmin ? '(' : '[', i->min, i->max, i->openmax ? ')' : ']'); } @@ -275,19 +275,19 @@ int snd_pcm_hw_refine(struct snd_pcm_substream *substream, changed = r->func(params, r); #ifdef RULES_DEBUG if (r->var >= 0) { - printk(" -> "); + pr_cont(" -> "); if (hw_is_mask(r->var)) - printk("%x", *m->bits); + pr_cont("%x", *m->bits); else { if (i->empty) - printk("empty"); + pr_cont("empty"); else - printk("%c%u %u%c", + pr_cont("%c%u %u%c", i->openmin ? '(' : '[', i->min, i->max, i->openmax ? ')' : ']'); } } - printk("\n"); + pr_cont("\n"); #endif rstamps[k] = stamp; if (changed && r->var >= 0) { @@ -399,7 +399,7 @@ static int snd_pcm_hw_params(struct snd_pcm_substream *substream, return -EBADFD; } snd_pcm_stream_unlock_irq(substream); -#if defined(CONFIG_SND_PCM_OSS) || defined(CONFIG_SND_PCM_OSS_MODULE) +#if IS_ENABLED(CONFIG_SND_PCM_OSS) if (!substream->oss.oss) #endif if (atomic_read(&substream->mmap_count)) @@ -954,7 +954,7 @@ static struct action_ops snd_pcm_action_stop = { * * The state of each stream is then changed to the given state unconditionally. * - * Return: Zero if succesful, or a negative error code. + * Return: Zero if successful, or a negative error code. */ int snd_pcm_stop(struct snd_pcm_substream *substream, snd_pcm_state_t state) { @@ -1541,7 +1541,8 @@ static int snd_pcm_drain(struct snd_pcm_substream *substream, if (substream->runtime->status->state == SNDRV_PCM_STATE_SUSPENDED) result = -ESTRPIPE; else { - snd_printd("playback drain error (DMA or IRQ trouble?)\n"); + dev_dbg(substream->pcm->card->dev, + "playback drain error (DMA or IRQ trouble?)\n"); snd_pcm_stop(substream, SNDRV_PCM_STATE_SETUP); result = -EIO; } @@ -2066,7 +2067,7 @@ int snd_pcm_open_substream(struct snd_pcm *pcm, int stream, err = snd_pcm_hw_constraints_init(substream); if (err < 0) { - snd_printd("snd_pcm_hw_constraints_init failed\n"); + pcm_dbg(pcm, "snd_pcm_hw_constraints_init failed\n"); goto error; } @@ -2077,7 +2078,7 @@ int snd_pcm_open_substream(struct snd_pcm *pcm, int stream, err = snd_pcm_hw_constraints_complete(substream); if (err < 0) { - snd_printd("snd_pcm_hw_constraints_complete failed\n"); + pcm_dbg(pcm, "snd_pcm_hw_constraints_complete failed\n"); goto error; } @@ -2609,7 +2610,7 @@ static int snd_pcm_common_ioctl1(struct file *file, return res; } } - snd_printd("unknown ioctl = 0x%x\n", cmd); + pcm_dbg(substream->pcm, "unknown ioctl = 0x%x\n", cmd); return -ENOTTY; } diff --git a/sound/core/pcm_timer.c b/sound/core/pcm_timer.c index b01d9481d63..20ecd8f1808 100644 --- a/sound/core/pcm_timer.c +++ b/sound/core/pcm_timer.c @@ -53,7 +53,9 @@ void snd_pcm_timer_resolution_change(struct snd_pcm_substream *substream) post *= 2; } if (rate == 0) { - snd_printk(KERN_ERR "pcm timer resolution out of range (rate = %u, period_size = %lu)\n", runtime->rate, runtime->period_size); + pcm_err(substream->pcm, + "pcm timer resolution out of range (rate = %u, period_size = %lu)\n", + runtime->rate, runtime->period_size); runtime->timer_resolution = -1; return; } diff --git a/sound/core/rawmidi.c b/sound/core/rawmidi.c index 7b596b5751d..6fc71a4c8a5 100644 --- a/sound/core/rawmidi.c +++ b/sound/core/rawmidi.c @@ -56,6 +56,13 @@ static int snd_rawmidi_dev_disconnect(struct snd_device *device); static LIST_HEAD(snd_rawmidi_devices); static DEFINE_MUTEX(register_mutex); +#define rmidi_err(rmidi, fmt, args...) \ + dev_err((rmidi)->card->dev, fmt, ##args) +#define rmidi_warn(rmidi, fmt, args...) \ + dev_warn((rmidi)->card->dev, fmt, ##args) +#define rmidi_dbg(rmidi, fmt, args...) \ + dev_dbg((rmidi)->card->dev, fmt, ##args) + static struct snd_rawmidi *snd_rawmidi_search(struct snd_card *card, int device) { struct snd_rawmidi *rawmidi; @@ -165,6 +172,7 @@ int snd_rawmidi_drop_output(struct snd_rawmidi_substream *substream) spin_unlock_irqrestore(&runtime->lock, flags); return 0; } +EXPORT_SYMBOL(snd_rawmidi_drop_output); int snd_rawmidi_drain_output(struct snd_rawmidi_substream *substream) { @@ -180,7 +188,9 @@ int snd_rawmidi_drain_output(struct snd_rawmidi_substream *substream) if (signal_pending(current)) err = -ERESTARTSYS; if (runtime->avail < runtime->buffer_size && !timeout) { - snd_printk(KERN_WARNING "rawmidi drain error (avail = %li, buffer_size = %li)\n", (long)runtime->avail, (long)runtime->buffer_size); + rmidi_warn(substream->rmidi, + "rawmidi drain error (avail = %li, buffer_size = %li)\n", + (long)runtime->avail, (long)runtime->buffer_size); err = -EIO; } runtime->drain = 0; @@ -194,6 +204,7 @@ int snd_rawmidi_drain_output(struct snd_rawmidi_substream *substream) } return err; } +EXPORT_SYMBOL(snd_rawmidi_drain_output); int snd_rawmidi_drain_input(struct snd_rawmidi_substream *substream) { @@ -208,6 +219,7 @@ int snd_rawmidi_drain_input(struct snd_rawmidi_substream *substream) spin_unlock_irqrestore(&runtime->lock, flags); return 0; } +EXPORT_SYMBOL(snd_rawmidi_drain_input); /* look for an available substream for the given stream direction; * if a specific subdevice is given, try to assign it @@ -345,6 +357,7 @@ int snd_rawmidi_kernel_open(struct snd_card *card, int device, int subdevice, module_put(rmidi->card->module); return err; } +EXPORT_SYMBOL(snd_rawmidi_kernel_open); static int snd_rawmidi_open(struct inode *inode, struct file *file) { @@ -523,6 +536,7 @@ int snd_rawmidi_kernel_release(struct snd_rawmidi_file *rfile) module_put(rmidi->card->module); return 0; } +EXPORT_SYMBOL(snd_rawmidi_kernel_release); static int snd_rawmidi_release(struct inode *inode, struct file *file) { @@ -599,6 +613,7 @@ int snd_rawmidi_info_select(struct snd_card *card, struct snd_rawmidi_info *info } return -ENXIO; } +EXPORT_SYMBOL(snd_rawmidi_info_select); static int snd_rawmidi_info_select_user(struct snd_card *card, struct snd_rawmidi_info __user *_info) @@ -646,6 +661,7 @@ int snd_rawmidi_output_params(struct snd_rawmidi_substream *substream, substream->active_sensing = !params->no_active_sensing; return 0; } +EXPORT_SYMBOL(snd_rawmidi_output_params); int snd_rawmidi_input_params(struct snd_rawmidi_substream *substream, struct snd_rawmidi_params * params) @@ -671,6 +687,7 @@ int snd_rawmidi_input_params(struct snd_rawmidi_substream *substream, runtime->avail_min = params->avail_min; return 0; } +EXPORT_SYMBOL(snd_rawmidi_input_params); static int snd_rawmidi_output_status(struct snd_rawmidi_substream *substream, struct snd_rawmidi_status * status) @@ -802,10 +819,9 @@ static long snd_rawmidi_ioctl(struct file *file, unsigned int cmd, unsigned long return -EINVAL; } } -#ifdef CONFIG_SND_DEBUG default: - snd_printk(KERN_WARNING "rawmidi: unknown command = 0x%x\n", cmd); -#endif + rmidi_dbg(rfile->rmidi, + "rawmidi: unknown command = 0x%x\n", cmd); } return -ENOTTY; } @@ -875,7 +891,8 @@ int snd_rawmidi_receive(struct snd_rawmidi_substream *substream, if (!substream->opened) return -EBADFD; if (runtime->buffer == NULL) { - snd_printd("snd_rawmidi_receive: input is not active!!!\n"); + rmidi_dbg(substream->rmidi, + "snd_rawmidi_receive: input is not active!!!\n"); return -EINVAL; } spin_lock_irqsave(&runtime->lock, flags); @@ -926,6 +943,7 @@ int snd_rawmidi_receive(struct snd_rawmidi_substream *substream, spin_unlock_irqrestore(&runtime->lock, flags); return result; } +EXPORT_SYMBOL(snd_rawmidi_receive); static long snd_rawmidi_kernel_read1(struct snd_rawmidi_substream *substream, unsigned char __user *userbuf, @@ -968,6 +986,7 @@ long snd_rawmidi_kernel_read(struct snd_rawmidi_substream *substream, snd_rawmidi_input_trigger(substream, 1); return snd_rawmidi_kernel_read1(substream, NULL/*userbuf*/, buf, count); } +EXPORT_SYMBOL(snd_rawmidi_kernel_read); static ssize_t snd_rawmidi_read(struct file *file, char __user *buf, size_t count, loff_t *offset) @@ -1034,7 +1053,8 @@ int snd_rawmidi_transmit_empty(struct snd_rawmidi_substream *substream) unsigned long flags; if (runtime->buffer == NULL) { - snd_printd("snd_rawmidi_transmit_empty: output is not active!!!\n"); + rmidi_dbg(substream->rmidi, + "snd_rawmidi_transmit_empty: output is not active!!!\n"); return 1; } spin_lock_irqsave(&runtime->lock, flags); @@ -1042,6 +1062,7 @@ int snd_rawmidi_transmit_empty(struct snd_rawmidi_substream *substream) spin_unlock_irqrestore(&runtime->lock, flags); return result; } +EXPORT_SYMBOL(snd_rawmidi_transmit_empty); /** * snd_rawmidi_transmit_peek - copy data from the internal buffer @@ -1065,7 +1086,8 @@ int snd_rawmidi_transmit_peek(struct snd_rawmidi_substream *substream, struct snd_rawmidi_runtime *runtime = substream->runtime; if (runtime->buffer == NULL) { - snd_printd("snd_rawmidi_transmit_peek: output is not active!!!\n"); + rmidi_dbg(substream->rmidi, + "snd_rawmidi_transmit_peek: output is not active!!!\n"); return -EINVAL; } result = 0; @@ -1097,11 +1119,12 @@ int snd_rawmidi_transmit_peek(struct snd_rawmidi_substream *substream, spin_unlock_irqrestore(&runtime->lock, flags); return result; } +EXPORT_SYMBOL(snd_rawmidi_transmit_peek); /** * snd_rawmidi_transmit_ack - acknowledge the transmission * @substream: the rawmidi substream - * @count: the tranferred count + * @count: the transferred count * * Advances the hardware pointer for the internal output buffer with * the given size and updates the condition. @@ -1115,7 +1138,8 @@ int snd_rawmidi_transmit_ack(struct snd_rawmidi_substream *substream, int count) struct snd_rawmidi_runtime *runtime = substream->runtime; if (runtime->buffer == NULL) { - snd_printd("snd_rawmidi_transmit_ack: output is not active!!!\n"); + rmidi_dbg(substream->rmidi, + "snd_rawmidi_transmit_ack: output is not active!!!\n"); return -EINVAL; } spin_lock_irqsave(&runtime->lock, flags); @@ -1131,6 +1155,7 @@ int snd_rawmidi_transmit_ack(struct snd_rawmidi_substream *substream, int count) spin_unlock_irqrestore(&runtime->lock, flags); return count; } +EXPORT_SYMBOL(snd_rawmidi_transmit_ack); /** * snd_rawmidi_transmit - copy from the buffer to the device @@ -1152,6 +1177,7 @@ int snd_rawmidi_transmit(struct snd_rawmidi_substream *substream, return count; return snd_rawmidi_transmit_ack(substream, count); } +EXPORT_SYMBOL(snd_rawmidi_transmit); static long snd_rawmidi_kernel_write1(struct snd_rawmidi_substream *substream, const unsigned char __user *userbuf, @@ -1213,6 +1239,7 @@ long snd_rawmidi_kernel_write(struct snd_rawmidi_substream *substream, { return snd_rawmidi_kernel_write1(substream, NULL, buf, count); } +EXPORT_SYMBOL(snd_rawmidi_kernel_write); static ssize_t snd_rawmidi_write(struct file *file, const char __user *buf, size_t count, loff_t *offset) @@ -1413,7 +1440,7 @@ static int snd_rawmidi_alloc_substreams(struct snd_rawmidi *rmidi, for (idx = 0; idx < count; idx++) { substream = kzalloc(sizeof(*substream), GFP_KERNEL); if (substream == NULL) { - snd_printk(KERN_ERR "rawmidi: cannot allocate substream\n"); + rmidi_err(rmidi, "rawmidi: cannot allocate substream\n"); return -ENOMEM; } substream->stream = direction; @@ -1458,7 +1485,7 @@ int snd_rawmidi_new(struct snd_card *card, char *id, int device, *rrawmidi = NULL; rmidi = kzalloc(sizeof(*rmidi), GFP_KERNEL); if (rmidi == NULL) { - snd_printk(KERN_ERR "rawmidi: cannot allocate\n"); + dev_err(card->dev, "rawmidi: cannot allocate\n"); return -ENOMEM; } rmidi->card = card; @@ -1492,6 +1519,7 @@ int snd_rawmidi_new(struct snd_card *card, char *id, int device, *rrawmidi = rmidi; return 0; } +EXPORT_SYMBOL(snd_rawmidi_new); static void snd_rawmidi_free_substreams(struct snd_rawmidi_str *stream) { @@ -1557,7 +1585,8 @@ static int snd_rawmidi_dev_register(struct snd_device *device) if ((err = snd_register_device(SNDRV_DEVICE_TYPE_RAWMIDI, rmidi->card, rmidi->device, &snd_rawmidi_f_ops, rmidi, name)) < 0) { - snd_printk(KERN_ERR "unable to register rawmidi device %i:%i\n", rmidi->card->number, rmidi->device); + rmidi_err(rmidi, "unable to register rawmidi device %i:%i\n", + rmidi->card->number, rmidi->device); list_del(&rmidi->list); mutex_unlock(®ister_mutex); return err; @@ -1574,8 +1603,10 @@ static int snd_rawmidi_dev_register(struct snd_device *device) if ((int)rmidi->device == midi_map[rmidi->card->number]) { if (snd_register_oss_device(SNDRV_OSS_DEVICE_TYPE_MIDI, rmidi->card, 0, &snd_rawmidi_f_ops, - rmidi, name) < 0) { - snd_printk(KERN_ERR "unable to register OSS rawmidi device %i:%i\n", rmidi->card->number, 0); + rmidi) < 0) { + rmidi_err(rmidi, + "unable to register OSS rawmidi device %i:%i\n", + rmidi->card->number, 0); } else { rmidi->ossreg++; #ifdef SNDRV_OSS_INFO_DEV_MIDI @@ -1586,8 +1617,10 @@ static int snd_rawmidi_dev_register(struct snd_device *device) if ((int)rmidi->device == amidi_map[rmidi->card->number]) { if (snd_register_oss_device(SNDRV_OSS_DEVICE_TYPE_MIDI, rmidi->card, 1, &snd_rawmidi_f_ops, - rmidi, name) < 0) { - snd_printk(KERN_ERR "unable to register OSS rawmidi device %i:%i\n", rmidi->card->number, 1); + rmidi) < 0) { + rmidi_err(rmidi, + "unable to register OSS rawmidi device %i:%i\n", + rmidi->card->number, 1); } else { rmidi->ossreg++; } @@ -1670,6 +1703,7 @@ void snd_rawmidi_set_ops(struct snd_rawmidi *rmidi, int stream, list_for_each_entry(substream, &rmidi->streams[stream].substreams, list) substream->ops = ops; } +EXPORT_SYMBOL(snd_rawmidi_set_ops); /* * ENTRY functions @@ -1685,11 +1719,13 @@ static int __init alsa_rawmidi_init(void) /* check device map table */ for (i = 0; i < SNDRV_CARDS; i++) { if (midi_map[i] < 0 || midi_map[i] >= SNDRV_RAWMIDI_DEVICES) { - snd_printk(KERN_ERR "invalid midi_map[%d] = %d\n", i, midi_map[i]); + pr_err("ALSA: rawmidi: invalid midi_map[%d] = %d\n", + i, midi_map[i]); midi_map[i] = 0; } if (amidi_map[i] < 0 || amidi_map[i] >= SNDRV_RAWMIDI_DEVICES) { - snd_printk(KERN_ERR "invalid amidi_map[%d] = %d\n", i, amidi_map[i]); + pr_err("ALSA: rawmidi: invalid amidi_map[%d] = %d\n", + i, amidi_map[i]); amidi_map[i] = 1; } } @@ -1706,21 +1742,3 @@ static void __exit alsa_rawmidi_exit(void) module_init(alsa_rawmidi_init) module_exit(alsa_rawmidi_exit) - -EXPORT_SYMBOL(snd_rawmidi_output_params); -EXPORT_SYMBOL(snd_rawmidi_input_params); -EXPORT_SYMBOL(snd_rawmidi_drop_output); -EXPORT_SYMBOL(snd_rawmidi_drain_output); -EXPORT_SYMBOL(snd_rawmidi_drain_input); -EXPORT_SYMBOL(snd_rawmidi_receive); -EXPORT_SYMBOL(snd_rawmidi_transmit_empty); -EXPORT_SYMBOL(snd_rawmidi_transmit_peek); -EXPORT_SYMBOL(snd_rawmidi_transmit_ack); -EXPORT_SYMBOL(snd_rawmidi_transmit); -EXPORT_SYMBOL(snd_rawmidi_new); -EXPORT_SYMBOL(snd_rawmidi_set_ops); -EXPORT_SYMBOL(snd_rawmidi_info_select); -EXPORT_SYMBOL(snd_rawmidi_kernel_open); -EXPORT_SYMBOL(snd_rawmidi_kernel_release); -EXPORT_SYMBOL(snd_rawmidi_kernel_read); -EXPORT_SYMBOL(snd_rawmidi_kernel_write); diff --git a/sound/core/rtctimer.c b/sound/core/rtctimer.c index e85e72baff9..f3420d11a12 100644 --- a/sound/core/rtctimer.c +++ b/sound/core/rtctimer.c @@ -27,7 +27,7 @@ #include <sound/core.h> #include <sound/timer.h> -#if defined(CONFIG_RTC) || defined(CONFIG_RTC_MODULE) +#if IS_ENABLED(CONFIG_RTC) #include <linux/mc146818rtc.h> @@ -132,8 +132,7 @@ static int __init rtctimer_init(void) if (rtctimer_freq < 2 || rtctimer_freq > 8192 || !is_power_of_2(rtctimer_freq)) { - snd_printk(KERN_ERR "rtctimer: invalid frequency %d\n", - rtctimer_freq); + pr_err("ALSA: rtctimer: invalid frequency %d\n", rtctimer_freq); return -EINVAL; } @@ -185,4 +184,4 @@ MODULE_LICENSE("GPL"); MODULE_ALIAS("snd-timer-" __stringify(SNDRV_TIMER_GLOBAL_RTC)); -#endif /* CONFIG_RTC || CONFIG_RTC_MODULE */ +#endif /* IS_ENABLED(CONFIG_RTC) */ diff --git a/sound/core/seq/oss/seq_oss.c b/sound/core/seq/oss/seq_oss.c index 8d4d5e853ef..16d42679e43 100644 --- a/sound/core/seq/oss/seq_oss.c +++ b/sound/core/seq/oss/seq_oss.c @@ -39,12 +39,6 @@ MODULE_LICENSE("GPL"); MODULE_ALIAS_SNDRV_MINOR(SNDRV_MINOR_OSS_SEQUENCER); MODULE_ALIAS_SNDRV_MINOR(SNDRV_MINOR_OSS_MUSIC); -#ifdef SNDRV_SEQ_OSS_DEBUG -module_param(seq_oss_debug, int, 0644); -MODULE_PARM_DESC(seq_oss_debug, "debug option"); -int seq_oss_debug = 0; -#endif - /* * prototypes @@ -231,22 +225,19 @@ register_device(void) mutex_lock(®ister_mutex); if ((rc = snd_register_oss_device(SNDRV_OSS_DEVICE_TYPE_SEQUENCER, NULL, 0, - &seq_oss_f_ops, NULL, - SNDRV_SEQ_OSS_DEVNAME)) < 0) { - snd_printk(KERN_ERR "can't register device seq\n"); + &seq_oss_f_ops, NULL)) < 0) { + pr_err("ALSA: seq_oss: can't register device seq\n"); mutex_unlock(®ister_mutex); return rc; } if ((rc = snd_register_oss_device(SNDRV_OSS_DEVICE_TYPE_MUSIC, NULL, 0, - &seq_oss_f_ops, NULL, - SNDRV_SEQ_OSS_DEVNAME)) < 0) { - snd_printk(KERN_ERR "can't register device music\n"); + &seq_oss_f_ops, NULL)) < 0) { + pr_err("ALSA: seq_oss: can't register device music\n"); snd_unregister_oss_device(SNDRV_OSS_DEVICE_TYPE_SEQUENCER, NULL, 0); mutex_unlock(®ister_mutex); return rc; } - debug_printk(("device registered\n")); mutex_unlock(®ister_mutex); return 0; } @@ -255,11 +246,10 @@ static void unregister_device(void) { mutex_lock(®ister_mutex); - debug_printk(("device unregistered\n")); if (snd_unregister_oss_device(SNDRV_OSS_DEVICE_TYPE_MUSIC, NULL, 0) < 0) - snd_printk(KERN_ERR "error unregister device music\n"); + pr_err("ALSA: seq_oss: error unregister device music\n"); if (snd_unregister_oss_device(SNDRV_OSS_DEVICE_TYPE_SEQUENCER, NULL, 0) < 0) - snd_printk(KERN_ERR "error unregister device seq\n"); + pr_err("ALSA: seq_oss: error unregister device seq\n"); mutex_unlock(®ister_mutex); } diff --git a/sound/core/seq/oss/seq_oss_device.h b/sound/core/seq/oss/seq_oss_device.h index c0154a959d5..b4392432524 100644 --- a/sound/core/seq/oss/seq_oss_device.h +++ b/sound/core/seq/oss/seq_oss_device.h @@ -31,9 +31,6 @@ #include <sound/seq_kernel.h> #include <sound/info.h> -/* enable debug print */ -#define SNDRV_SEQ_OSS_DEBUG - /* max. applications */ #define SNDRV_SEQ_OSS_MAX_CLIENTS 16 #define SNDRV_SEQ_OSS_MAX_SYNTH_DEVS 16 @@ -46,7 +43,6 @@ #define SNDRV_SEQ_OSS_VERSION_STR "0.1.8" /* device and proc interface name */ -#define SNDRV_SEQ_OSS_DEVNAME "seq_oss" #define SNDRV_SEQ_OSS_PROCNAME "oss" @@ -177,13 +173,4 @@ snd_seq_oss_fill_addr(struct seq_oss_devinfo *dp, struct snd_seq_event *ev, /* misc. functions for proc interface */ char *enabled_str(int bool); - -/* for debug */ -#ifdef SNDRV_SEQ_OSS_DEBUG -extern int seq_oss_debug; -#define debug_printk(x) do { if (seq_oss_debug > 0) snd_printd x; } while (0) -#else -#define debug_printk(x) /**/ -#endif - #endif /* __SEQ_OSS_DEVICE_H */ diff --git a/sound/core/seq/oss/seq_oss_init.c b/sound/core/seq/oss/seq_oss_init.c index b3f39b5ed74..b9184d20c39 100644 --- a/sound/core/seq/oss/seq_oss_init.c +++ b/sound/core/seq/oss/seq_oss_init.c @@ -92,7 +92,6 @@ snd_seq_oss_create_client(void) goto __error; system_client = rc; - debug_printk(("new client = %d\n", rc)); /* create annoucement receiver port */ memset(port, 0, sizeof(*port)); @@ -190,10 +189,9 @@ snd_seq_oss_open(struct file *file, int level) dp = kzalloc(sizeof(*dp), GFP_KERNEL); if (!dp) { - snd_printk(KERN_ERR "can't malloc device info\n"); + pr_err("ALSA: seq_oss: can't malloc device info\n"); return -ENOMEM; } - debug_printk(("oss_open: dp = %p\n", dp)); dp->cseq = system_client; dp->port = -1; @@ -206,7 +204,7 @@ snd_seq_oss_open(struct file *file, int level) dp->index = i; if (i >= SNDRV_SEQ_OSS_MAX_CLIENTS) { - snd_printk(KERN_ERR "too many applications\n"); + pr_err("ALSA: seq_oss: too many applications\n"); rc = -ENOMEM; goto _error; } @@ -216,21 +214,19 @@ snd_seq_oss_open(struct file *file, int level) snd_seq_oss_midi_setup(dp); if (dp->synth_opened == 0 && dp->max_mididev == 0) { - /* snd_printk(KERN_ERR "no device found\n"); */ + /* pr_err("ALSA: seq_oss: no device found\n"); */ rc = -ENODEV; goto _error; } /* create port */ - debug_printk(("create new port\n")); rc = create_port(dp); if (rc < 0) { - snd_printk(KERN_ERR "can't create port\n"); + pr_err("ALSA: seq_oss: can't create port\n"); goto _error; } /* allocate queue */ - debug_printk(("allocate queue\n")); rc = alloc_seq_queue(dp); if (rc < 0) goto _error; @@ -247,7 +243,6 @@ snd_seq_oss_open(struct file *file, int level) dp->file_mode = translate_mode(file); /* initialize read queue */ - debug_printk(("initialize read queue\n")); if (is_read_mode(dp->file_mode)) { dp->readq = snd_seq_oss_readq_new(dp, maxqlen); if (!dp->readq) { @@ -257,7 +252,6 @@ snd_seq_oss_open(struct file *file, int level) } /* initialize write queue */ - debug_printk(("initialize write queue\n")); if (is_write_mode(dp->file_mode)) { dp->writeq = snd_seq_oss_writeq_new(dp, maxqlen); if (!dp->writeq) { @@ -267,14 +261,12 @@ snd_seq_oss_open(struct file *file, int level) } /* initialize timer */ - debug_printk(("initialize timer\n")); dp->timer = snd_seq_oss_timer_new(dp); if (!dp->timer) { - snd_printk(KERN_ERR "can't alloc timer\n"); + pr_err("ALSA: seq_oss: can't alloc timer\n"); rc = -ENOMEM; goto _error; } - debug_printk(("timer initialized\n")); /* set private data pointer */ file->private_data = dp; @@ -288,7 +280,6 @@ snd_seq_oss_open(struct file *file, int level) client_table[dp->index] = dp; num_clients++; - debug_printk(("open done\n")); return 0; _error: @@ -347,7 +338,6 @@ create_port(struct seq_oss_devinfo *dp) return rc; dp->port = port.addr.port; - debug_printk(("new port = %d\n", port.addr.port)); return 0; } @@ -363,7 +353,6 @@ delete_port(struct seq_oss_devinfo *dp) return 0; } - debug_printk(("delete_port %i\n", dp->port)); return snd_seq_event_port_detach(dp->cseq, dp->port); } @@ -401,7 +390,7 @@ delete_seq_queue(int queue) qinfo.queue = queue; rc = call_ctl(SNDRV_SEQ_IOCTL_DELETE_QUEUE, &qinfo); if (rc < 0) - printk(KERN_ERR "seq-oss: unable to delete queue %d (%d)\n", queue, rc); + pr_err("ALSA: seq_oss: unable to delete queue %d (%d)\n", queue, rc); return rc; } @@ -438,21 +427,16 @@ snd_seq_oss_release(struct seq_oss_devinfo *dp) client_table[dp->index] = NULL; num_clients--; - debug_printk(("resetting..\n")); snd_seq_oss_reset(dp); - debug_printk(("cleaning up..\n")); snd_seq_oss_synth_cleanup(dp); snd_seq_oss_midi_cleanup(dp); /* clear slot */ - debug_printk(("releasing resource..\n")); queue = dp->queue; if (dp->port >= 0) delete_port(dp); delete_seq_queue(queue); - - debug_printk(("release done\n")); } @@ -466,7 +450,6 @@ snd_seq_oss_drain_write(struct seq_oss_devinfo *dp) return; if (is_write_mode(dp->file_mode) && !is_nonblock_mode(dp->file_mode) && dp->writeq) { - debug_printk(("syncing..\n")); while (snd_seq_oss_writeq_sync(dp->writeq)) ; } diff --git a/sound/core/seq/oss/seq_oss_ioctl.c b/sound/core/seq/oss/seq_oss_ioctl.c index 5ac701c903c..5b8520177b0 100644 --- a/sound/core/seq/oss/seq_oss_ioctl.c +++ b/sound/core/seq/oss/seq_oss_ioctl.c @@ -90,12 +90,10 @@ snd_seq_oss_ioctl(struct seq_oss_devinfo *dp, unsigned int cmd, unsigned long ca return snd_seq_oss_timer_ioctl(dp->timer, cmd, arg); case SNDCTL_SEQ_PANIC: - debug_printk(("panic\n")); snd_seq_oss_reset(dp); return -EINVAL; case SNDCTL_SEQ_SYNC: - debug_printk(("sync\n")); if (! is_write_mode(dp->file_mode) || dp->writeq == NULL) return 0; while (snd_seq_oss_writeq_sync(dp->writeq)) @@ -105,55 +103,45 @@ snd_seq_oss_ioctl(struct seq_oss_devinfo *dp, unsigned int cmd, unsigned long ca return 0; case SNDCTL_SEQ_RESET: - debug_printk(("reset\n")); snd_seq_oss_reset(dp); return 0; case SNDCTL_SEQ_TESTMIDI: - debug_printk(("test midi\n")); if (get_user(dev, p)) return -EFAULT; return snd_seq_oss_midi_open(dp, dev, dp->file_mode); case SNDCTL_SEQ_GETINCOUNT: - debug_printk(("get in count\n")); if (dp->readq == NULL || ! is_read_mode(dp->file_mode)) return 0; return put_user(dp->readq->qlen, p) ? -EFAULT : 0; case SNDCTL_SEQ_GETOUTCOUNT: - debug_printk(("get out count\n")); if (! is_write_mode(dp->file_mode) || dp->writeq == NULL) return 0; return put_user(snd_seq_oss_writeq_get_free_size(dp->writeq), p) ? -EFAULT : 0; case SNDCTL_SEQ_GETTIME: - debug_printk(("get time\n")); return put_user(snd_seq_oss_timer_cur_tick(dp->timer), p) ? -EFAULT : 0; case SNDCTL_SEQ_RESETSAMPLES: - debug_printk(("reset samples\n")); if (get_user(dev, p)) return -EFAULT; return snd_seq_oss_synth_ioctl(dp, dev, cmd, carg); case SNDCTL_SEQ_NRSYNTHS: - debug_printk(("nr synths\n")); return put_user(dp->max_synthdev, p) ? -EFAULT : 0; case SNDCTL_SEQ_NRMIDIS: - debug_printk(("nr midis\n")); return put_user(dp->max_mididev, p) ? -EFAULT : 0; case SNDCTL_SYNTH_MEMAVL: - debug_printk(("mem avail\n")); if (get_user(dev, p)) return -EFAULT; val = snd_seq_oss_synth_ioctl(dp, dev, cmd, carg); return put_user(val, p) ? -EFAULT : 0; case SNDCTL_FM_4OP_ENABLE: - debug_printk(("4op\n")); if (get_user(dev, p)) return -EFAULT; snd_seq_oss_synth_ioctl(dp, dev, cmd, carg); @@ -161,19 +149,15 @@ snd_seq_oss_ioctl(struct seq_oss_devinfo *dp, unsigned int cmd, unsigned long ca case SNDCTL_SYNTH_INFO: case SNDCTL_SYNTH_ID: - debug_printk(("synth info\n")); return snd_seq_oss_synth_info_user(dp, arg); case SNDCTL_SEQ_OUTOFBAND: - debug_printk(("out of band\n")); return snd_seq_oss_oob_user(dp, arg); case SNDCTL_MIDI_INFO: - debug_printk(("midi info\n")); return snd_seq_oss_midi_info_user(dp, arg); case SNDCTL_SEQ_THRESHOLD: - debug_printk(("threshold\n")); if (! is_write_mode(dp->file_mode)) return 0; if (get_user(val, p)) @@ -186,7 +170,6 @@ snd_seq_oss_ioctl(struct seq_oss_devinfo *dp, unsigned int cmd, unsigned long ca return 0; case SNDCTL_MIDI_PRETIME: - debug_printk(("pretime\n")); if (dp->readq == NULL || !is_read_mode(dp->file_mode)) return 0; if (get_user(val, p)) @@ -199,7 +182,6 @@ snd_seq_oss_ioctl(struct seq_oss_devinfo *dp, unsigned int cmd, unsigned long ca return put_user(val, p) ? -EFAULT : 0; default: - debug_printk(("others\n")); if (! is_write_mode(dp->file_mode)) return -EIO; return snd_seq_oss_synth_ioctl(dp, 0, cmd, carg); diff --git a/sound/core/seq/oss/seq_oss_midi.c b/sound/core/seq/oss/seq_oss_midi.c index 862d84893ee..3a4569669ef 100644 --- a/sound/core/seq/oss/seq_oss_midi.c +++ b/sound/core/seq/oss/seq_oss_midi.c @@ -153,7 +153,6 @@ snd_seq_oss_midi_check_new_port(struct snd_seq_port_info *pinfo) struct seq_oss_midi *mdev; unsigned long flags; - debug_printk(("check for MIDI client %d port %d\n", pinfo->addr.client, pinfo->addr.port)); /* the port must include generic midi */ if (! (pinfo->type & SNDRV_SEQ_PORT_TYPE_MIDI_GENERIC)) return 0; @@ -175,7 +174,7 @@ snd_seq_oss_midi_check_new_port(struct snd_seq_port_info *pinfo) * allocate midi info record */ if ((mdev = kzalloc(sizeof(*mdev), GFP_KERNEL)) == NULL) { - snd_printk(KERN_ERR "can't malloc midi info\n"); + pr_err("ALSA: seq_oss: can't malloc midi info\n"); return -ENOMEM; } @@ -191,7 +190,7 @@ snd_seq_oss_midi_check_new_port(struct snd_seq_port_info *pinfo) /* create MIDI coder */ if (snd_midi_event_new(MAX_MIDI_EVENT_BUF, &mdev->coder) < 0) { - snd_printk(KERN_ERR "can't malloc midi coder\n"); + pr_err("ALSA: seq_oss: can't malloc midi coder\n"); kfree(mdev); return -ENOMEM; } @@ -406,7 +405,6 @@ snd_seq_oss_midi_close(struct seq_oss_devinfo *dp, int dev) return 0; } - debug_printk(("closing client %d port %d mode %d\n", mdev->client, mdev->port, mdev->opened)); memset(&subs, 0, sizeof(subs)); if (mdev->opened & PERM_WRITE) { subs.sender = dp->addr; @@ -470,7 +468,6 @@ snd_seq_oss_midi_reset(struct seq_oss_devinfo *dp, int dev) struct snd_seq_event ev; int c; - debug_printk(("resetting client %d port %d\n", mdev->client, mdev->port)); memset(&ev, 0, sizeof(ev)); ev.dest.client = mdev->client; ev.dest.port = mdev->port; diff --git a/sound/core/seq/oss/seq_oss_readq.c b/sound/core/seq/oss/seq_oss_readq.c index 73661c4ab82..654d17a5023 100644 --- a/sound/core/seq/oss/seq_oss_readq.c +++ b/sound/core/seq/oss/seq_oss_readq.c @@ -48,12 +48,12 @@ snd_seq_oss_readq_new(struct seq_oss_devinfo *dp, int maxlen) struct seq_oss_readq *q; if ((q = kzalloc(sizeof(*q), GFP_KERNEL)) == NULL) { - snd_printk(KERN_ERR "can't malloc read queue\n"); + pr_err("ALSA: seq_oss: can't malloc read queue\n"); return NULL; } if ((q->q = kcalloc(maxlen, sizeof(union evrec), GFP_KERNEL)) == NULL) { - snd_printk(KERN_ERR "can't malloc read queue buffer\n"); + pr_err("ALSA: seq_oss: can't malloc read queue buffer\n"); kfree(q); return NULL; } diff --git a/sound/core/seq/oss/seq_oss_synth.c b/sound/core/seq/oss/seq_oss_synth.c index c5b773a1eea..701feb71b70 100644 --- a/sound/core/seq/oss/seq_oss_synth.c +++ b/sound/core/seq/oss/seq_oss_synth.c @@ -106,7 +106,7 @@ snd_seq_oss_synth_register(struct snd_seq_device *dev) unsigned long flags; if ((rec = kzalloc(sizeof(*rec), GFP_KERNEL)) == NULL) { - snd_printk(KERN_ERR "can't malloc synth info\n"); + pr_err("ALSA: seq_oss: can't malloc synth info\n"); return -ENOMEM; } rec->seq_device = -1; @@ -130,7 +130,7 @@ snd_seq_oss_synth_register(struct snd_seq_device *dev) if (i >= max_synth_devs) { if (max_synth_devs >= SNDRV_SEQ_OSS_MAX_SYNTH_DEVS) { spin_unlock_irqrestore(®ister_lock, flags); - snd_printk(KERN_ERR "no more synth slot\n"); + pr_err("ALSA: seq_oss: no more synth slot\n"); kfree(rec); return -ENOMEM; } @@ -138,7 +138,6 @@ snd_seq_oss_synth_register(struct snd_seq_device *dev) } rec->seq_device = i; synth_devs[i] = rec; - debug_printk(("synth %s registered %d\n", rec->name, i)); spin_unlock_irqrestore(®ister_lock, flags); dev->driver_data = rec; #ifdef SNDRV_OSS_INFO_DEV_SYNTH @@ -163,7 +162,7 @@ snd_seq_oss_synth_unregister(struct snd_seq_device *dev) } if (index >= max_synth_devs) { spin_unlock_irqrestore(®ister_lock, flags); - snd_printk(KERN_ERR "can't unregister synth\n"); + pr_err("ALSA: seq_oss: can't unregister synth\n"); return -EINVAL; } synth_devs[index] = NULL; @@ -248,7 +247,7 @@ snd_seq_oss_synth_setup(struct seq_oss_devinfo *dp) if (info->nr_voices > 0) { info->ch = kcalloc(info->nr_voices, sizeof(struct seq_oss_chinfo), GFP_KERNEL); if (!info->ch) { - snd_printk(KERN_ERR "Cannot malloc\n"); + pr_err("ALSA: seq_oss: Cannot malloc voices\n"); rec->oper.close(&info->arg); module_put(rec->oper.owner); snd_use_lock_free(&rec->use_lock); @@ -256,7 +255,6 @@ snd_seq_oss_synth_setup(struct seq_oss_devinfo *dp) } reset_channels(info); } - debug_printk(("synth %d assigned\n", i)); info->opened++; rec->opened++; dp->synth_opened++; @@ -326,7 +324,6 @@ snd_seq_oss_synth_cleanup(struct seq_oss_devinfo *dp) if (rec == NULL) continue; if (rec->opened > 0) { - debug_printk(("synth %d closed\n", i)); rec->oper.close(&info->arg); module_put(rec->oper.owner); rec->opened = 0; diff --git a/sound/core/seq/oss/seq_oss_timer.c b/sound/core/seq/oss/seq_oss_timer.c index ab59cbfbcaf..4f24ea9fad9 100644 --- a/sound/core/seq/oss/seq_oss_timer.c +++ b/sound/core/seq/oss/seq_oss_timer.c @@ -233,7 +233,6 @@ snd_seq_oss_timer_ioctl(struct seq_oss_timer *timer, unsigned int cmd, int __use int value; if (cmd == SNDCTL_SEQ_CTRLRATE) { - debug_printk(("ctrl rate\n")); /* if *arg == 0, just return the current rate */ if (get_user(value, arg)) return -EFAULT; @@ -248,21 +247,16 @@ snd_seq_oss_timer_ioctl(struct seq_oss_timer *timer, unsigned int cmd, int __use switch (cmd) { case SNDCTL_TMR_START: - debug_printk(("timer start\n")); return snd_seq_oss_timer_start(timer); case SNDCTL_TMR_STOP: - debug_printk(("timer stop\n")); return snd_seq_oss_timer_stop(timer); case SNDCTL_TMR_CONTINUE: - debug_printk(("timer continue\n")); return snd_seq_oss_timer_continue(timer); case SNDCTL_TMR_TEMPO: - debug_printk(("timer tempo\n")); if (get_user(value, arg)) return -EFAULT; return snd_seq_oss_timer_tempo(timer, value); case SNDCTL_TMR_TIMEBASE: - debug_printk(("timer timebase\n")); if (get_user(value, arg)) return -EFAULT; if (value < MIN_OSS_TIMEBASE) @@ -276,7 +270,6 @@ snd_seq_oss_timer_ioctl(struct seq_oss_timer *timer, unsigned int cmd, int __use case SNDCTL_TMR_METRONOME: case SNDCTL_TMR_SELECT: case SNDCTL_TMR_SOURCE: - debug_printk(("timer XXX\n")); /* not supported */ return 0; } diff --git a/sound/core/seq/seq_clientmgr.c b/sound/core/seq/seq_clientmgr.c index 4dc6bae80e1..9ca5e647e54 100644 --- a/sound/core/seq/seq_clientmgr.c +++ b/sound/core/seq/seq_clientmgr.c @@ -123,7 +123,7 @@ static inline int snd_seq_write_pool_allocated(struct snd_seq_client *client) static struct snd_seq_client *clientptr(int clientid) { if (clientid < 0 || clientid >= SNDRV_SEQ_MAX_CLIENTS) { - snd_printd("Seq: oops. Trying to get pointer to client %d\n", + pr_debug("ALSA: seq: oops. Trying to get pointer to client %d\n", clientid); return NULL; } @@ -136,7 +136,7 @@ struct snd_seq_client *snd_seq_client_use_ptr(int clientid) struct snd_seq_client *client; if (clientid < 0 || clientid >= SNDRV_SEQ_MAX_CLIENTS) { - snd_printd("Seq: oops. Trying to get pointer to client %d\n", + pr_debug("ALSA: seq: oops. Trying to get pointer to client %d\n", clientid); return NULL; } @@ -291,8 +291,8 @@ static void seq_free_client(struct snd_seq_client * client) mutex_lock(®ister_mutex); switch (client->type) { case NO_CLIENT: - snd_printk(KERN_WARNING "Seq: Trying to free unused client %d\n", - client->number); + pr_warn("ALSA: seq: Trying to free unused client %d\n", + client->number); break; case USER_CLIENT: case KERNEL_CLIENT: @@ -301,7 +301,7 @@ static void seq_free_client(struct snd_seq_client * client) break; default: - snd_printk(KERN_ERR "Seq: Trying to free client %d with undefined type = %d\n", + pr_err("ALSA: seq: Trying to free client %d with undefined type = %d\n", client->number, client->type); } mutex_unlock(®ister_mutex); @@ -773,7 +773,7 @@ static int broadcast_event(struct snd_seq_client *client, static int multicast_event(struct snd_seq_client *client, struct snd_seq_event *event, int atomic, int hop) { - snd_printd("seq: multicast not supported yet.\n"); + pr_debug("ALSA: seq: multicast not supported yet.\n"); return 0; /* ignored */ } #endif /* SUPPORT_BROADCAST */ @@ -794,7 +794,7 @@ static int snd_seq_deliver_event(struct snd_seq_client *client, struct snd_seq_e hop++; if (hop >= SNDRV_SEQ_MAX_HOPS) { - snd_printd("too long delivery path (%d:%d->%d:%d)\n", + pr_debug("ALSA: seq: too long delivery path (%d:%d->%d:%d)\n", event->source.client, event->source.port, event->dest.client, event->dest.port); return -EMLINK; @@ -2196,7 +2196,7 @@ static int snd_seq_do_ioctl(struct snd_seq_client *client, unsigned int cmd, if (p->cmd == cmd) return p->func(client, arg); } - snd_printd("seq unknown ioctl() 0x%x (type='%c', number=0x%02x)\n", + pr_debug("ALSA: seq unknown ioctl() 0x%x (type='%c', number=0x%02x)\n", cmd, _IOC_TYPE(cmd), _IOC_NR(cmd)); return -ENOTTY; } diff --git a/sound/core/seq/seq_device.c b/sound/core/seq/seq_device.c index 040c60e1da2..91a786a783e 100644 --- a/sound/core/seq/seq_device.c +++ b/sound/core/seq/seq_device.c @@ -168,7 +168,7 @@ void snd_seq_device_load_drivers(void) /* * register a sequencer device - * card = card info (NULL allowed) + * card = card info * device = device number (if any) * id = id of driver * result = return pointer (NULL allowed if unnecessary) @@ -325,7 +325,7 @@ int snd_seq_device_register_driver(char *id, struct snd_seq_dev_ops *entry, return -ENOMEM; } if (ops->driver & DRIVER_LOADED) { - snd_printk(KERN_WARNING "driver_register: driver '%s' already exists\n", id); + pr_warn("ALSA: seq: driver_register: driver '%s' already exists\n", id); unlock_driver(ops); snd_seq_autoload_unlock(); return -EBUSY; @@ -398,7 +398,7 @@ int snd_seq_device_unregister_driver(char *id) return -ENXIO; if (! (ops->driver & DRIVER_LOADED) || (ops->driver & DRIVER_LOCKED)) { - snd_printk(KERN_ERR "driver_unregister: cannot unload driver '%s': status=%x\n", + pr_err("ALSA: seq: driver_unregister: cannot unload driver '%s': status=%x\n", id, ops->driver); unlock_driver(ops); return -EBUSY; @@ -413,7 +413,7 @@ int snd_seq_device_unregister_driver(char *id) ops->driver = 0; if (ops->num_init_devices > 0) - snd_printk(KERN_ERR "free_driver: init_devices > 0!! (%d)\n", + pr_err("ALSA: seq: free_driver: init_devices > 0!! (%d)\n", ops->num_init_devices); mutex_unlock(&ops->reg_mutex); @@ -459,7 +459,7 @@ static int init_device(struct snd_seq_device *dev, struct ops_list *ops) if (dev->status != SNDRV_SEQ_DEVICE_FREE) return 0; /* already initialized */ if (ops->argsize != dev->argsize) { - snd_printk(KERN_ERR "incompatible device '%s' for plug-in '%s' (%d %d)\n", + pr_err("ALSA: seq: incompatible device '%s' for plug-in '%s' (%d %d)\n", dev->name, ops->id, ops->argsize, dev->argsize); return -EINVAL; } @@ -467,7 +467,7 @@ static int init_device(struct snd_seq_device *dev, struct ops_list *ops) dev->status = SNDRV_SEQ_DEVICE_REGISTERED; ops->num_init_devices++; } else { - snd_printk(KERN_ERR "init_device failed: %s: %s\n", + pr_err("ALSA: seq: init_device failed: %s: %s\n", dev->name, dev->id); } @@ -486,7 +486,7 @@ static int free_device(struct snd_seq_device *dev, struct ops_list *ops) if (dev->status != SNDRV_SEQ_DEVICE_REGISTERED) return 0; /* not registered */ if (ops->argsize != dev->argsize) { - snd_printk(KERN_ERR "incompatible device '%s' for plug-in '%s' (%d %d)\n", + pr_err("ALSA: seq: incompatible device '%s' for plug-in '%s' (%d %d)\n", dev->name, ops->id, ops->argsize, dev->argsize); return -EINVAL; } @@ -495,7 +495,7 @@ static int free_device(struct snd_seq_device *dev, struct ops_list *ops) dev->driver_data = NULL; ops->num_init_devices--; } else { - snd_printk(KERN_ERR "free_device failed: %s: %s\n", + pr_err("ALSA: seq: free_device failed: %s: %s\n", dev->name, dev->id); } @@ -559,7 +559,7 @@ static void __exit alsa_seq_device_exit(void) snd_info_free_entry(info_entry); #endif if (num_ops) - snd_printk(KERN_ERR "drivers not released (%d)\n", num_ops); + pr_err("ALSA: seq: drivers not released (%d)\n", num_ops); } module_init(alsa_seq_device_init) diff --git a/sound/core/seq/seq_dummy.c b/sound/core/seq/seq_dummy.c index dbc55071679..ec667f158f1 100644 --- a/sound/core/seq/seq_dummy.c +++ b/sound/core/seq/seq_dummy.c @@ -198,7 +198,7 @@ register_client(void) int i; if (ports < 1) { - snd_printk(KERN_ERR "invalid number of ports %d\n", ports); + pr_err("ALSA: seq_dummy: invalid number of ports %d\n", ports); return -EINVAL; } diff --git a/sound/core/seq/seq_fifo.c b/sound/core/seq/seq_fifo.c index 0d75afa786b..559989992be 100644 --- a/sound/core/seq/seq_fifo.c +++ b/sound/core/seq/seq_fifo.c @@ -34,7 +34,7 @@ struct snd_seq_fifo *snd_seq_fifo_new(int poolsize) f = kzalloc(sizeof(*f), GFP_KERNEL); if (f == NULL) { - snd_printd("malloc failed for snd_seq_fifo_new() \n"); + pr_debug("ALSA: seq: malloc failed for snd_seq_fifo_new() \n"); return NULL; } diff --git a/sound/core/seq/seq_lock.c b/sound/core/seq/seq_lock.c index 2cfe50c71a9..3b693e924db 100644 --- a/sound/core/seq/seq_lock.c +++ b/sound/core/seq/seq_lock.c @@ -31,12 +31,12 @@ void snd_use_lock_sync_helper(snd_use_lock_t *lockp, const char *file, int line) int max_count = 5 * HZ; if (atomic_read(lockp) < 0) { - printk(KERN_WARNING "seq_lock: lock trouble [counter = %d] in %s:%d\n", atomic_read(lockp), file, line); + pr_warn("ALSA: seq_lock: lock trouble [counter = %d] in %s:%d\n", atomic_read(lockp), file, line); return; } while (atomic_read(lockp) > 0) { if (max_count == 0) { - snd_printk(KERN_WARNING "seq_lock: timeout [%d left] in %s:%d\n", atomic_read(lockp), file, line); + pr_warn("ALSA: seq_lock: timeout [%d left] in %s:%d\n", atomic_read(lockp), file, line); break; } schedule_timeout_uninterruptible(1); diff --git a/sound/core/seq/seq_memory.c b/sound/core/seq/seq_memory.c index f478f770bf5..1e206de0c2d 100644 --- a/sound/core/seq/seq_memory.c +++ b/sound/core/seq/seq_memory.c @@ -236,7 +236,7 @@ static int snd_seq_cell_alloc(struct snd_seq_pool *pool, init_waitqueue_entry(&wait, current); spin_lock_irqsave(&pool->lock, flags); if (pool->ptr == NULL) { /* not initialized */ - snd_printd("seq: pool is not initialized\n"); + pr_debug("ALSA: seq: pool is not initialized\n"); err = -EINVAL; goto __error; } @@ -388,7 +388,7 @@ int snd_seq_pool_init(struct snd_seq_pool *pool) pool->ptr = vmalloc(sizeof(struct snd_seq_event_cell) * pool->size); if (pool->ptr == NULL) { - snd_printd("seq: malloc for sequencer events failed\n"); + pr_debug("ALSA: seq: malloc for sequencer events failed\n"); return -ENOMEM; } @@ -431,7 +431,7 @@ int snd_seq_pool_done(struct snd_seq_pool *pool) while (atomic_read(&pool->counter) > 0) { if (max_count == 0) { - snd_printk(KERN_WARNING "snd_seq_pool_done timeout: %d cells remain\n", atomic_read(&pool->counter)); + pr_warn("ALSA: snd_seq_pool_done timeout: %d cells remain\n", atomic_read(&pool->counter)); break; } schedule_timeout_uninterruptible(1); @@ -464,7 +464,7 @@ struct snd_seq_pool *snd_seq_pool_new(int poolsize) /* create pool block */ pool = kzalloc(sizeof(*pool), GFP_KERNEL); if (pool == NULL) { - snd_printd("seq: malloc failed for pool\n"); + pr_debug("ALSA: seq: malloc failed for pool\n"); return NULL; } spin_lock_init(&pool->lock); diff --git a/sound/core/seq/seq_midi.c b/sound/core/seq/seq_midi.c index 64069dbf89c..3e05c55a288 100644 --- a/sound/core/seq/seq_midi.c +++ b/sound/core/seq/seq_midi.c @@ -121,7 +121,7 @@ static int dump_midi(struct snd_rawmidi_substream *substream, const char *buf, i runtime = substream->runtime; if ((tmp = runtime->avail) < count) { if (printk_ratelimit()) - snd_printk(KERN_ERR "MIDI output buffer overrun\n"); + pr_err("ALSA: seq_midi: MIDI output buffer overrun\n"); return -ENOMEM; } if (snd_rawmidi_kernel_write(substream, buf, count) < count) @@ -145,7 +145,7 @@ static int event_process_midi(struct snd_seq_event *ev, int direct, if (ev->type == SNDRV_SEQ_EVENT_SYSEX) { /* special case, to save space */ if ((ev->flags & SNDRV_SEQ_EVENT_LENGTH_MASK) != SNDRV_SEQ_EVENT_LENGTH_VARIABLE) { /* invalid event */ - snd_printd("seq_midi: invalid sysex event flags = 0x%x\n", ev->flags); + pr_debug("ALSA: seq_midi: invalid sysex event flags = 0x%x\n", ev->flags); return 0; } snd_seq_dump_var_event(ev, (snd_seq_dump_func_t)dump_midi, substream); @@ -189,7 +189,7 @@ static int midisynth_subscribe(void *private_data, struct snd_seq_port_subscribe msynth->subdevice, SNDRV_RAWMIDI_LFLG_INPUT, &msynth->input_rfile)) < 0) { - snd_printd("midi input open failed!!!\n"); + pr_debug("ALSA: seq_midi: midi input open failed!!!\n"); return err; } runtime = msynth->input_rfile.input->runtime; @@ -231,7 +231,7 @@ static int midisynth_use(void *private_data, struct snd_seq_port_subscribe *info msynth->subdevice, SNDRV_RAWMIDI_LFLG_OUTPUT, &msynth->output_rfile)) < 0) { - snd_printd("midi output open failed!!!\n"); + pr_debug("ALSA: seq_midi: midi output open failed!!!\n"); return err; } memset(¶ms, 0, sizeof(params)); diff --git a/sound/core/seq/seq_midi_emul.c b/sound/core/seq/seq_midi_emul.c index 6f64471ddde..9b6470cdcf2 100644 --- a/sound/core/seq/seq_midi_emul.c +++ b/sound/core/seq/seq_midi_emul.c @@ -89,7 +89,7 @@ snd_midi_process_event(struct snd_midi_op *ops, int dest_channel = 0; if (ev == NULL || chanset == NULL) { - snd_printd("ev or chanbase NULL (snd_midi_process_event)\n"); + pr_debug("ALSA: seq_midi_emul: ev or chanbase NULL (snd_midi_process_event)\n"); return; } if (chanset->channels == NULL) @@ -98,7 +98,7 @@ snd_midi_process_event(struct snd_midi_op *ops, if (snd_seq_ev_is_channel_type(ev)) { dest_channel = ev->data.note.channel; if (dest_channel >= chanset->max_channels) { - snd_printd("dest channel is %d, max is %d\n", + pr_debug("ALSA: seq_midi_emul: dest channel is %d, max is %d\n", dest_channel, chanset->max_channels); return; } @@ -232,7 +232,7 @@ snd_midi_process_event(struct snd_midi_op *ops, case SNDRV_SEQ_EVENT_ECHO: not_yet: default: - /*snd_printd("Unimplemented event %d\n", ev->type);*/ + /*pr_debug("ALSA: seq_midi_emul: Unimplemented event %d\n", ev->type);*/ break; } } diff --git a/sound/core/seq/seq_ports.c b/sound/core/seq/seq_ports.c index 9516e5ce3aa..794a341bf0e 100644 --- a/sound/core/seq/seq_ports.c +++ b/sound/core/seq/seq_ports.c @@ -135,14 +135,14 @@ struct snd_seq_client_port *snd_seq_create_port(struct snd_seq_client *client, return NULL; if (client->num_ports >= SNDRV_SEQ_MAX_PORTS - 1) { - snd_printk(KERN_WARNING "too many ports for client %d\n", client->number); + pr_warn("ALSA: seq: too many ports for client %d\n", client->number); return NULL; } /* create a new port */ new_port = kzalloc(sizeof(*new_port), GFP_KERNEL); if (! new_port) { - snd_printd("malloc failed for registering client port\n"); + pr_debug("ALSA: seq: malloc failed for registering client port\n"); return NULL; /* failure, out of memory */ } /* init port data */ diff --git a/sound/core/seq/seq_prioq.c b/sound/core/seq/seq_prioq.c index 29896ab2340..021b02bc933 100644 --- a/sound/core/seq/seq_prioq.c +++ b/sound/core/seq/seq_prioq.c @@ -60,7 +60,7 @@ struct snd_seq_prioq *snd_seq_prioq_new(void) f = kzalloc(sizeof(*f), GFP_KERNEL); if (f == NULL) { - snd_printd("oops: malloc failed for snd_seq_prioq_new()\n"); + pr_debug("ALSA: seq: malloc failed for snd_seq_prioq_new()\n"); return NULL; } @@ -79,7 +79,7 @@ void snd_seq_prioq_delete(struct snd_seq_prioq **fifo) *fifo = NULL; if (f == NULL) { - snd_printd("oops: snd_seq_prioq_delete() called with NULL prioq\n"); + pr_debug("ALSA: seq: snd_seq_prioq_delete() called with NULL prioq\n"); return; } @@ -197,7 +197,7 @@ int snd_seq_prioq_cell_in(struct snd_seq_prioq * f, cur = cur->next; if (! --count) { spin_unlock_irqrestore(&f->lock, flags); - snd_printk(KERN_ERR "cannot find a pointer.. infinite loop?\n"); + pr_err("ALSA: seq: cannot find a pointer.. infinite loop?\n"); return -EINVAL; } } @@ -223,7 +223,7 @@ struct snd_seq_event_cell *snd_seq_prioq_cell_out(struct snd_seq_prioq *f) unsigned long flags; if (f == NULL) { - snd_printd("oops: snd_seq_prioq_cell_in() called with NULL prioq\n"); + pr_debug("ALSA: seq: snd_seq_prioq_cell_in() called with NULL prioq\n"); return NULL; } spin_lock_irqsave(&f->lock, flags); @@ -248,7 +248,7 @@ struct snd_seq_event_cell *snd_seq_prioq_cell_out(struct snd_seq_prioq *f) int snd_seq_prioq_avail(struct snd_seq_prioq * f) { if (f == NULL) { - snd_printd("oops: snd_seq_prioq_cell_in() called with NULL prioq\n"); + pr_debug("ALSA: seq: snd_seq_prioq_cell_in() called with NULL prioq\n"); return 0; } return f->cells; @@ -259,7 +259,7 @@ int snd_seq_prioq_avail(struct snd_seq_prioq * f) struct snd_seq_event_cell *snd_seq_prioq_cell_peek(struct snd_seq_prioq * f) { if (f == NULL) { - snd_printd("oops: snd_seq_prioq_cell_in() called with NULL prioq\n"); + pr_debug("ALSA: seq: snd_seq_prioq_cell_in() called with NULL prioq\n"); return NULL; } return f->head; @@ -321,7 +321,7 @@ void snd_seq_prioq_leave(struct snd_seq_prioq * f, int client, int timestamp) freeprev = cell; } else { #if 0 - printk(KERN_DEBUG "type = %i, source = %i, dest = %i, " + pr_debug("ALSA: seq: type = %i, source = %i, dest = %i, " "client = %i\n", cell->event.type, cell->event.source.client, diff --git a/sound/core/seq/seq_queue.c b/sound/core/seq/seq_queue.c index f9077361c11..aad4878cee5 100644 --- a/sound/core/seq/seq_queue.c +++ b/sound/core/seq/seq_queue.c @@ -112,7 +112,7 @@ static struct snd_seq_queue *queue_new(int owner, int locked) q = kzalloc(sizeof(*q), GFP_KERNEL); if (q == NULL) { - snd_printd("malloc failed for snd_seq_queue_new()\n"); + pr_debug("ALSA: seq: malloc failed for snd_seq_queue_new()\n"); return NULL; } diff --git a/sound/core/seq/seq_timer.c b/sound/core/seq/seq_timer.c index 24d44b2f61a..e73605393ee 100644 --- a/sound/core/seq/seq_timer.c +++ b/sound/core/seq/seq_timer.c @@ -57,7 +57,7 @@ struct snd_seq_timer *snd_seq_timer_new(void) tmr = kzalloc(sizeof(*tmr), GFP_KERNEL); if (tmr == NULL) { - snd_printd("malloc failed for snd_seq_timer_new() \n"); + pr_debug("ALSA: seq: malloc failed for snd_seq_timer_new() \n"); return NULL; } spin_lock_init(&tmr->lock); @@ -78,7 +78,7 @@ void snd_seq_timer_delete(struct snd_seq_timer **tmr) *tmr = NULL; if (t == NULL) { - snd_printd("oops: snd_seq_timer_delete() called with NULL timer\n"); + pr_debug("ALSA: seq: snd_seq_timer_delete() called with NULL timer\n"); return; } t->running = 0; @@ -199,7 +199,7 @@ int snd_seq_timer_set_ppq(struct snd_seq_timer * tmr, int ppq) /* refuse to change ppq on running timers */ /* because it will upset the song position (ticks) */ spin_unlock_irqrestore(&tmr->lock, flags); - snd_printd("seq: cannot change ppq of a running timer\n"); + pr_debug("ALSA: seq: cannot change ppq of a running timer\n"); return -EBUSY; } @@ -252,7 +252,7 @@ int snd_seq_timer_set_skew(struct snd_seq_timer *tmr, unsigned int skew, /* FIXME */ if (base != SKEW_BASE) { - snd_printd("invalid skew base 0x%x\n", base); + pr_debug("ALSA: seq: invalid skew base 0x%x\n", base); return -EINVAL; } spin_lock_irqsave(&tmr->lock, flags); @@ -292,7 +292,7 @@ int snd_seq_timer_open(struct snd_seq_queue *q) } } if (err < 0) { - snd_printk(KERN_ERR "seq fatal error: cannot create timer (%i)\n", err); + pr_err("ALSA: seq fatal error: cannot create timer (%i)\n", err); return err; } t->callback = snd_seq_timer_interrupt; diff --git a/sound/core/seq/seq_virmidi.c b/sound/core/seq/seq_virmidi.c index 4b50e604276..56e0f4cd3f8 100644 --- a/sound/core/seq/seq_virmidi.c +++ b/sound/core/seq/seq_virmidi.c @@ -446,7 +446,7 @@ static int snd_virmidi_dev_register(struct snd_rawmidi *rmidi) /* should check presence of port more strictly.. */ break; default: - snd_printk(KERN_ERR "seq_mode is not set: %d\n", rdev->seq_mode); + pr_err("ALSA: seq_virmidi: seq_mode is not set: %d\n", rdev->seq_mode); return -EINVAL; } return 0; diff --git a/sound/core/sound.c b/sound/core/sound.c index 437c25ea640..38ad1a0dd3f 100644 --- a/sound/core/sound.c +++ b/sound/core/sound.c @@ -118,7 +118,7 @@ void *snd_lookup_minor_data(unsigned int minor, int type) if (mreg && mreg->type == type) { private_data = mreg->private_data; if (private_data && mreg->card_ptr) - atomic_inc(&mreg->card_ptr->refcount); + get_device(&mreg->card_ptr->card_dev); } else private_data = NULL; mutex_unlock(&sound_mutex); @@ -355,22 +355,25 @@ int snd_unregister_device(int type, struct snd_card *card, int dev) EXPORT_SYMBOL(snd_unregister_device); -int snd_add_device_sysfs_file(int type, struct snd_card *card, int dev, - struct device_attribute *attr) +/* get the assigned device to the given type and device number; + * the caller needs to release it via put_device() after using it + */ +struct device *snd_get_device(int type, struct snd_card *card, int dev) { - int minor, ret = -EINVAL; - struct device *d; + int minor; + struct device *d = NULL; mutex_lock(&sound_mutex); minor = find_snd_minor(type, card, dev); - if (minor >= 0 && (d = snd_minors[minor]->dev) != NULL) - ret = device_create_file(d, attr); + if (minor >= 0) { + d = snd_minors[minor]->dev; + if (d) + get_device(d); + } mutex_unlock(&sound_mutex); - return ret; - + return d; } - -EXPORT_SYMBOL(snd_add_device_sysfs_file); +EXPORT_SYMBOL(snd_get_device); #ifdef CONFIG_PROC_FS /* @@ -458,7 +461,7 @@ static int __init alsa_sound_init(void) snd_major = major; snd_ecards_limit = cards_limit; if (register_chrdev(major, "alsa", &snd_fops)) { - snd_printk(KERN_ERR "unable to register native major device number %d\n", major); + pr_err("ALSA core: unable to register native major device number %d\n", major); return -EIO; } if (snd_info_init() < 0) { @@ -467,7 +470,7 @@ static int __init alsa_sound_init(void) } snd_info_minor_register(); #ifndef MODULE - printk(KERN_INFO "Advanced Linux Sound Architecture Driver Initialized.\n"); + pr_info("Advanced Linux Sound Architecture Driver Initialized.\n"); #endif return 0; } diff --git a/sound/core/sound_oss.c b/sound/core/sound_oss.c index 726a49ac972..573a65eb2b7 100644 --- a/sound/core/sound_oss.c +++ b/sound/core/sound_oss.c @@ -21,7 +21,7 @@ #ifdef CONFIG_SND_OSSEMUL -#if !defined(CONFIG_SOUND) && !(defined(MODULE) && defined(CONFIG_SOUND_MODULE)) +#if !IS_ENABLED(CONFIG_SOUND) #error "Enable the OSS soundcore multiplexer (CONFIG_SOUND) in the kernel." #endif @@ -55,7 +55,7 @@ void *snd_lookup_oss_minor_data(unsigned int minor, int type) if (mreg && mreg->type == type) { private_data = mreg->private_data; if (private_data && mreg->card_ptr) - atomic_inc(&mreg->card_ptr->refcount); + get_device(&mreg->card_ptr->card_dev); } else private_data = NULL; mutex_unlock(&sound_oss_mutex); @@ -105,8 +105,7 @@ static int snd_oss_kernel_minor(int type, struct snd_card *card, int dev) } int snd_register_oss_device(int type, struct snd_card *card, int dev, - const struct file_operations *f_ops, void *private_data, - const char *name) + const struct file_operations *f_ops, void *private_data) { int minor = snd_oss_kernel_minor(type, card, dev); int minor_unit; diff --git a/sound/core/timer.c b/sound/core/timer.c index 6ddcf06f52f..cfd455a8ac1 100644 --- a/sound/core/timer.c +++ b/sound/core/timer.c @@ -35,9 +35,9 @@ #include <sound/initval.h> #include <linux/kmod.h> -#if defined(CONFIG_SND_HRTIMER) || defined(CONFIG_SND_HRTIMER_MODULE) +#if IS_ENABLED(CONFIG_SND_HRTIMER) #define DEFAULT_TIMER_LIMIT 4 -#elif defined(CONFIG_SND_RTCTIMER) || defined(CONFIG_SND_RTCTIMER_MODULE) +#elif IS_ENABLED(CONFIG_SND_RTCTIMER) #define DEFAULT_TIMER_LIMIT 2 #else #define DEFAULT_TIMER_LIMIT 1 @@ -240,7 +240,8 @@ int snd_timer_open(struct snd_timer_instance **ti, /* open a slave instance */ if (tid->dev_sclass <= SNDRV_TIMER_SCLASS_NONE || tid->dev_sclass > SNDRV_TIMER_SCLASS_OSS_SEQUENCER) { - snd_printd("invalid slave class %i\n", tid->dev_sclass); + pr_debug("ALSA: timer: invalid slave class %i\n", + tid->dev_sclass); return -EINVAL; } mutex_lock(®ister_mutex); @@ -774,7 +775,7 @@ int snd_timer_new(struct snd_card *card, char *id, struct snd_timer_id *tid, *rtimer = NULL; timer = kzalloc(sizeof(*timer), GFP_KERNEL); if (timer == NULL) { - snd_printk(KERN_ERR "timer: cannot allocate\n"); + pr_err("ALSA: timer: cannot allocate\n"); return -ENOMEM; } timer->tmr_class = tid->dev_class; @@ -813,7 +814,7 @@ static int snd_timer_free(struct snd_timer *timer) if (! list_empty(&timer->open_list_head)) { struct list_head *p, *n; struct snd_timer_instance *ti; - snd_printk(KERN_WARNING "timer %p is busy?\n", timer); + pr_warn("ALSA: timer %p is busy?\n", timer); list_for_each_safe(p, n, &timer->open_list_head) { list_del_init(p); ti = list_entry(p, struct snd_timer_instance, open_list); @@ -1955,12 +1956,10 @@ static int __init alsa_timer_init(void) #endif if ((err = snd_timer_register_system()) < 0) - snd_printk(KERN_ERR "unable to register system timer (%i)\n", - err); + pr_err("ALSA: unable to register system timer (%i)\n", err); if ((err = snd_register_device(SNDRV_DEVICE_TYPE_TIMER, NULL, 0, &snd_timer_f_ops, NULL, "timer")) < 0) - snd_printk(KERN_ERR "unable to register timer device (%i)\n", - err); + pr_err("ALSA: unable to register timer device (%i)\n", err); snd_timer_proc_init(); return 0; } diff --git a/sound/core/vmaster.c b/sound/core/vmaster.c index 842a97d5fc3..6c58e6f73a0 100644 --- a/sound/core/vmaster.c +++ b/sound/core/vmaster.c @@ -101,7 +101,7 @@ static int slave_init(struct link_slave *slave) if (slave->info.count > 2 || (slave->info.type != SNDRV_CTL_ELEM_TYPE_INTEGER && slave->info.type != SNDRV_CTL_ELEM_TYPE_BOOLEAN)) { - snd_printk(KERN_ERR "invalid slave element\n"); + pr_err("ALSA: vmaster: invalid slave element\n"); kfree(uinfo); return -EINVAL; } diff --git a/sound/drivers/aloop.c b/sound/drivers/aloop.c index f7589923eff..2a16c86a60b 100644 --- a/sound/drivers/aloop.c +++ b/sound/drivers/aloop.c @@ -1142,8 +1142,8 @@ static int loopback_probe(struct platform_device *devptr) int dev = devptr->id; int err; - err = snd_card_create(index[dev], id[dev], THIS_MODULE, - sizeof(struct loopback), &card); + err = snd_card_new(&devptr->dev, index[dev], id[dev], THIS_MODULE, + sizeof(struct loopback), &card); if (err < 0) return err; loopback = card->private_data; diff --git a/sound/drivers/dummy.c b/sound/drivers/dummy.c index 915b4d7fbb2..fab90bd2bd5 100644 --- a/sound/drivers/dummy.c +++ b/sound/drivers/dummy.c @@ -1054,8 +1054,8 @@ static int snd_dummy_probe(struct platform_device *devptr) int idx, err; int dev = devptr->id; - err = snd_card_create(index[dev], id[dev], THIS_MODULE, - sizeof(struct snd_dummy), &card); + err = snd_card_new(&devptr->dev, index[dev], id[dev], THIS_MODULE, + sizeof(struct snd_dummy), &card); if (err < 0) return err; dummy = card->private_data; @@ -1114,8 +1114,6 @@ static int snd_dummy_probe(struct platform_device *devptr) dummy_proc_init(dummy); - snd_card_set_dev(card, &devptr->dev); - err = snd_card_register(card); if (err == 0) { platform_set_drvdata(devptr, card); diff --git a/sound/drivers/ml403-ac97cr.c b/sound/drivers/ml403-ac97cr.c index 95ea4a153ea..33ed76530d0 100644 --- a/sound/drivers/ml403-ac97cr.c +++ b/sound/drivers/ml403-ac97cr.c @@ -1280,7 +1280,8 @@ static int snd_ml403_ac97cr_probe(struct platform_device *pfdev) if (!enable[dev]) return -ENOENT; - err = snd_card_create(index[dev], id[dev], THIS_MODULE, 0, &card); + err = snd_card_new(&pfdev->dev, index[dev], id[dev], THIS_MODULE, + 0, &card); if (err < 0) return err; err = snd_ml403_ac97cr_create(card, pfdev, &ml403_ac97cr); @@ -1310,8 +1311,6 @@ static int snd_ml403_ac97cr_probe(struct platform_device *pfdev) (unsigned long)ml403_ac97cr->port, ml403_ac97cr->irq, ml403_ac97cr->capture_irq, dev + 1); - snd_card_set_dev(card, &pfdev->dev); - err = snd_card_register(card); if (err < 0) { snd_card_free(card); diff --git a/sound/drivers/mpu401/mpu401.c b/sound/drivers/mpu401/mpu401.c index 90a3a7b38a2..83014b83a44 100644 --- a/sound/drivers/mpu401/mpu401.c +++ b/sound/drivers/mpu401/mpu401.c @@ -64,7 +64,8 @@ static struct platform_device *platform_devices[SNDRV_CARDS]; static int pnp_registered; static unsigned int snd_mpu401_devices; -static int snd_mpu401_create(int dev, struct snd_card **rcard) +static int snd_mpu401_create(struct device *devptr, int dev, + struct snd_card **rcard) { struct snd_card *card; int err; @@ -73,7 +74,8 @@ static int snd_mpu401_create(int dev, struct snd_card **rcard) snd_printk(KERN_ERR "the uart_enter option is obsolete; remove it\n"); *rcard = NULL; - err = snd_card_create(index[dev], id[dev], THIS_MODULE, 0, &card); + err = snd_card_new(devptr, index[dev], id[dev], THIS_MODULE, + 0, &card); if (err < 0) return err; strcpy(card->driver, "MPU-401 UART"); @@ -114,10 +116,9 @@ static int snd_mpu401_probe(struct platform_device *devptr) snd_printk(KERN_ERR "specify or disable IRQ\n"); return -EINVAL; } - err = snd_mpu401_create(dev, &card); + err = snd_mpu401_create(&devptr->dev, dev, &card); if (err < 0) return err; - snd_card_set_dev(card, &devptr->dev); if ((err = snd_card_register(card)) < 0) { snd_card_free(card); return err; @@ -194,14 +195,13 @@ static int snd_mpu401_pnp_probe(struct pnp_dev *pnp_dev, err = snd_mpu401_pnp(dev, pnp_dev, id); if (err < 0) return err; - err = snd_mpu401_create(dev, &card); + err = snd_mpu401_create(&pnp_dev->dev, dev, &card); if (err < 0) return err; if ((err = snd_card_register(card)) < 0) { snd_card_free(card); return err; } - snd_card_set_dev(card, &pnp_dev->dev); pnp_set_drvdata(pnp_dev, card); snd_mpu401_devices++; ++dev; diff --git a/sound/drivers/mtpav.c b/sound/drivers/mtpav.c index e5ec7eb27de..4b66c7f22af 100644 --- a/sound/drivers/mtpav.c +++ b/sound/drivers/mtpav.c @@ -697,7 +697,8 @@ static int snd_mtpav_probe(struct platform_device *dev) int err; struct mtpav *mtp_card; - err = snd_card_create(index, id, THIS_MODULE, sizeof(*mtp_card), &card); + err = snd_card_new(&dev->dev, index, id, THIS_MODULE, + sizeof(*mtp_card), &card); if (err < 0) return err; @@ -732,7 +733,6 @@ static int snd_mtpav_probe(struct platform_device *dev) snd_mtpav_portscan(mtp_card); - snd_card_set_dev(card, &dev->dev); err = snd_card_register(mtp_card->card); if (err < 0) goto __error; diff --git a/sound/drivers/mts64.c b/sound/drivers/mts64.c index 4e0dd22ba08..f5fd448dbc5 100644 --- a/sound/drivers/mts64.c +++ b/sound/drivers/mts64.c @@ -959,7 +959,8 @@ static int snd_mts64_probe(struct platform_device *pdev) if ((err = snd_mts64_probe_port(p)) < 0) return err; - err = snd_card_create(index[dev], id[dev], THIS_MODULE, 0, &card); + err = snd_card_new(&pdev->dev, index[dev], id[dev], THIS_MODULE, + 0, &card); if (err < 0) { snd_printd("Cannot create card\n"); return err; @@ -1009,8 +1010,6 @@ static int snd_mts64_probe(struct platform_device *pdev) platform_set_drvdata(pdev, card); - snd_card_set_dev(card, &pdev->dev); - /* At this point card will be usable */ if ((err = snd_card_register(card)) < 0) { snd_printd("Cannot register card\n"); diff --git a/sound/drivers/opl3/opl3_lib.c b/sound/drivers/opl3/opl3_lib.c index 33d9a857a26..f66af5884c4 100644 --- a/sound/drivers/opl3/opl3_lib.c +++ b/sound/drivers/opl3/opl3_lib.c @@ -501,10 +501,8 @@ int snd_opl3_hwdep_new(struct snd_opl3 * opl3, hw->private_data = opl3; hw->exclusive = 1; #ifdef CONFIG_SND_OSSEMUL - if (device == 0) { + if (device == 0) hw->oss_type = SNDRV_OSS_DEVICE_TYPE_DMFM; - sprintf(hw->oss_dev, "dmfm%i", card->number); - } #endif strcpy(hw->name, hw->id); switch (opl3->hardware & OPL3_HW_MASK) { diff --git a/sound/drivers/opl3/opl3_synth.c b/sound/drivers/opl3/opl3_synth.c index 742a4b642fd..ddcc1a325a6 100644 --- a/sound/drivers/opl3/opl3_synth.c +++ b/sound/drivers/opl3/opl3_synth.c @@ -24,7 +24,7 @@ #include <sound/opl3.h> #include <sound/asound_fm.h> -#if defined(CONFIG_SND_SEQUENCER) || defined(CONFIG_SND_SEQUENCER_MODULE) +#if IS_ENABLED(CONFIG_SND_SEQUENCER) #define OPL3_SUPPORT_SYNTH #endif diff --git a/sound/drivers/pcsp/pcsp.c b/sound/drivers/pcsp/pcsp.c index 328bd29264c..36808cdab06 100644 --- a/sound/drivers/pcsp/pcsp.c +++ b/sound/drivers/pcsp/pcsp.c @@ -105,7 +105,7 @@ static int snd_card_pcsp_probe(int devnum, struct device *dev) hrtimer_init(&pcsp_chip.timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); pcsp_chip.timer.function = pcsp_do_timer; - err = snd_card_create(index, id, THIS_MODULE, 0, &card); + err = snd_card_new(dev, index, id, THIS_MODULE, 0, &card); if (err < 0) return err; @@ -127,8 +127,6 @@ static int snd_card_pcsp_probe(int devnum, struct device *dev) return err; } - snd_card_set_dev(pcsp_chip.card, dev); - strcpy(card->driver, "PC-Speaker"); strcpy(card->shortname, "pcsp"); sprintf(card->longname, "Internal PC-Speaker at port 0x%x", diff --git a/sound/drivers/pcsp/pcsp_input.c b/sound/drivers/pcsp/pcsp_input.c index b874b0ad99c..0ecf8a453e0 100644 --- a/sound/drivers/pcsp/pcsp_input.c +++ b/sound/drivers/pcsp/pcsp_input.c @@ -16,6 +16,7 @@ #include <linux/input.h> #include <asm/io.h> #include "pcsp.h" +#include "pcsp_input.h" static void pcspkr_do_sound(unsigned int count) { diff --git a/sound/drivers/portman2x4.c b/sound/drivers/portman2x4.c index 991018df713..78ccfa45552 100644 --- a/sound/drivers/portman2x4.c +++ b/sound/drivers/portman2x4.c @@ -748,7 +748,8 @@ static int snd_portman_probe(struct platform_device *pdev) if ((err = snd_portman_probe_port(p)) < 0) return err; - err = snd_card_create(index[dev], id[dev], THIS_MODULE, 0, &card); + err = snd_card_new(&pdev->dev, index[dev], id[dev], THIS_MODULE, + 0, &card); if (err < 0) { snd_printd("Cannot create card\n"); return err; @@ -798,8 +799,6 @@ static int snd_portman_probe(struct platform_device *pdev) platform_set_drvdata(pdev, card); - snd_card_set_dev(card, &pdev->dev); - /* At this point card will be usable */ if ((err = snd_card_register(card)) < 0) { snd_printd("Cannot register card\n"); diff --git a/sound/drivers/serial-u16550.c b/sound/drivers/serial-u16550.c index e0bf5e77b43..9ad4414fa25 100644 --- a/sound/drivers/serial-u16550.c +++ b/sound/drivers/serial-u16550.c @@ -942,7 +942,8 @@ static int snd_serial_probe(struct platform_device *devptr) return -ENODEV; } - err = snd_card_create(index[dev], id[dev], THIS_MODULE, 0, &card); + err = snd_card_new(&devptr->dev, index[dev], id[dev], THIS_MODULE, + 0, &card); if (err < 0) return err; @@ -969,8 +970,6 @@ static int snd_serial_probe(struct platform_device *devptr) uart->base, uart->irq); - snd_card_set_dev(card, &devptr->dev); - if ((err = snd_card_register(card)) < 0) goto _err; diff --git a/sound/drivers/virmidi.c b/sound/drivers/virmidi.c index ace3879e8d9..b178724295f 100644 --- a/sound/drivers/virmidi.c +++ b/sound/drivers/virmidi.c @@ -90,8 +90,8 @@ static int snd_virmidi_probe(struct platform_device *devptr) int idx, err; int dev = devptr->id; - err = snd_card_create(index[dev], id[dev], THIS_MODULE, - sizeof(struct snd_card_virmidi), &card); + err = snd_card_new(&devptr->dev, index[dev], id[dev], THIS_MODULE, + sizeof(struct snd_card_virmidi), &card); if (err < 0) return err; vmidi = card->private_data; @@ -118,8 +118,6 @@ static int snd_virmidi_probe(struct platform_device *devptr) strcpy(card->shortname, "VirMIDI"); sprintf(card->longname, "Virtual MIDI Card %i", dev + 1); - snd_card_set_dev(card, &devptr->dev); - if ((err = snd_card_register(card)) == 0) { platform_set_drvdata(devptr, card); return 0; diff --git a/sound/firewire/dice.c b/sound/firewire/dice.c index c0aa64941ce..0c3948630cf 100644 --- a/sound/firewire/dice.c +++ b/sound/firewire/dice.c @@ -1326,10 +1326,10 @@ static int dice_probe(struct fw_unit *unit, const struct ieee1394_device_id *id) if (err < 0) return err; - err = snd_card_create(-1, NULL, THIS_MODULE, sizeof(*dice), &card); + err = snd_card_new(&unit->device, -1, NULL, THIS_MODULE, + sizeof(*dice), &card); if (err < 0) return err; - snd_card_set_dev(card, &unit->device); dice = card->private_data; dice->card = card; diff --git a/sound/firewire/isight.c b/sound/firewire/isight.c index fd42e6b315e..7ac94439e75 100644 --- a/sound/firewire/isight.c +++ b/sound/firewire/isight.c @@ -631,10 +631,10 @@ static int isight_probe(struct fw_unit *unit, struct isight *isight; int err; - err = snd_card_create(-1, NULL, THIS_MODULE, sizeof(*isight), &card); + err = snd_card_new(&unit->device, -1, NULL, THIS_MODULE, + sizeof(*isight), &card); if (err < 0) return err; - snd_card_set_dev(card, &unit->device); isight = card->private_data; isight->card = card; diff --git a/sound/firewire/scs1x.c b/sound/firewire/scs1x.c index 858023cf429..2dba848a781 100644 --- a/sound/firewire/scs1x.c +++ b/sound/firewire/scs1x.c @@ -391,10 +391,10 @@ static int scs_probe(struct fw_unit *unit, const struct ieee1394_device_id *id) struct scs *scs; int err; - err = snd_card_create(-16, NULL, THIS_MODULE, sizeof(*scs), &card); + err = snd_card_new(&unit->device, -16, NULL, THIS_MODULE, + sizeof(*scs), &card); if (err < 0) return err; - snd_card_set_dev(card, &unit->device); scs = card->private_data; scs->card = card; diff --git a/sound/firewire/speakers.c b/sound/firewire/speakers.c index cc8bc3a51bc..9f7ef219b10 100644 --- a/sound/firewire/speakers.c +++ b/sound/firewire/speakers.c @@ -668,10 +668,10 @@ static int fwspk_probe(struct fw_unit *unit, u32 firmware; int err; - err = snd_card_create(-1, NULL, THIS_MODULE, sizeof(*fwspk), &card); + err = snd_card_new(&unit->device, -1, NULL, THIS_MODULE, + sizeof(*fwspk), &card); if (err < 0) return err; - snd_card_set_dev(card, &unit->device); fwspk = card->private_data; fwspk->card = card; diff --git a/sound/i2c/other/ak4113.c b/sound/i2c/other/ak4113.c index e04e750a77e..1a3a6fa2715 100644 --- a/sound/i2c/other/ak4113.c +++ b/sound/i2c/other/ak4113.c @@ -98,7 +98,7 @@ int snd_ak4113_create(struct snd_card *card, ak4113_read_t *read, AK4113_CINT | AK4113_STC); chip->rcs1 = reg_read(chip, AK4113_REG_RCS1); chip->rcs2 = reg_read(chip, AK4113_REG_RCS2); - err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops); + err = snd_device_new(card, SNDRV_DEV_CODEC, chip, &ops); if (err < 0) goto __fail; diff --git a/sound/i2c/other/ak4114.c b/sound/i2c/other/ak4114.c index 15ae0250eac..c7f56339415 100644 --- a/sound/i2c/other/ak4114.c +++ b/sound/i2c/other/ak4114.c @@ -111,7 +111,7 @@ int snd_ak4114_create(struct snd_card *card, chip->rcs0 = reg_read(chip, AK4114_REG_RCS0) & ~(AK4114_QINT | AK4114_CINT); chip->rcs1 = reg_read(chip, AK4114_REG_RCS1); - if ((err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops)) < 0) + if ((err = snd_device_new(card, SNDRV_DEV_CODEC, chip, &ops)) < 0) goto __fail; if (r_ak4114) diff --git a/sound/i2c/other/ak4117.c b/sound/i2c/other/ak4117.c index 40e33c9f2b0..88452e899bd 100644 --- a/sound/i2c/other/ak4117.c +++ b/sound/i2c/other/ak4117.c @@ -62,7 +62,7 @@ static void reg_dump(struct ak4117 *ak4117) static void snd_ak4117_free(struct ak4117 *chip) { - del_timer(&chip->timer); + del_timer_sync(&chip->timer); kfree(chip); } diff --git a/sound/isa/ad1816a/ad1816a.c b/sound/isa/ad1816a/ad1816a.c index 26ce26a5884..f481a41e027 100644 --- a/sound/isa/ad1816a/ad1816a.c +++ b/sound/isa/ad1816a/ad1816a.c @@ -144,8 +144,9 @@ static int snd_card_ad1816a_probe(int dev, struct pnp_card_link *pcard, struct snd_opl3 *opl3; struct snd_timer *timer; - error = snd_card_create(index[dev], id[dev], THIS_MODULE, - sizeof(struct snd_ad1816a), &card); + error = snd_card_new(&pcard->card->dev, + index[dev], id[dev], THIS_MODULE, + sizeof(struct snd_ad1816a), &card); if (error < 0) return error; chip = card->private_data; @@ -154,7 +155,6 @@ static int snd_card_ad1816a_probe(int dev, struct pnp_card_link *pcard, snd_card_free(card); return error; } - snd_card_set_dev(card, &pcard->card->dev); if ((error = snd_ad1816a_create(card, port[dev], irq[dev], diff --git a/sound/isa/ad1848/ad1848.c b/sound/isa/ad1848/ad1848.c index e3f455bd85c..093f22a464d 100644 --- a/sound/isa/ad1848/ad1848.c +++ b/sound/isa/ad1848/ad1848.c @@ -91,7 +91,7 @@ static int snd_ad1848_probe(struct device *dev, unsigned int n) struct snd_pcm *pcm; int error; - error = snd_card_create(index[n], id[n], THIS_MODULE, 0, &card); + error = snd_card_new(dev, index[n], id[n], THIS_MODULE, 0, &card); if (error < 0) return error; @@ -119,8 +119,6 @@ static int snd_ad1848_probe(struct device *dev, unsigned int n) if (thinkpad[n]) strcat(card->longname, " [Thinkpad]"); - snd_card_set_dev(card, dev); - error = snd_card_register(card); if (error < 0) goto out; diff --git a/sound/isa/adlib.c b/sound/isa/adlib.c index 35659218710..120c524bb2a 100644 --- a/sound/isa/adlib.c +++ b/sound/isa/adlib.c @@ -53,7 +53,7 @@ static int snd_adlib_probe(struct device *dev, unsigned int n) struct snd_opl3 *opl3; int error; - error = snd_card_create(index[n], id[n], THIS_MODULE, 0, &card); + error = snd_card_new(dev, index[n], id[n], THIS_MODULE, 0, &card); if (error < 0) { dev_err(dev, "could not create card\n"); return error; @@ -83,8 +83,6 @@ static int snd_adlib_probe(struct device *dev, unsigned int n) goto out; } - snd_card_set_dev(card, dev); - error = snd_card_register(card); if (error < 0) { dev_err(dev, "could not register card\n"); diff --git a/sound/isa/als100.c b/sound/isa/als100.c index 10f08a18fe3..32d01525211 100644 --- a/sound/isa/als100.c +++ b/sound/isa/als100.c @@ -193,8 +193,9 @@ static int snd_card_als100_probe(int dev, struct snd_card_als100 *acard; struct snd_opl3 *opl3; - error = snd_card_create(index[dev], id[dev], THIS_MODULE, - sizeof(struct snd_card_als100), &card); + error = snd_card_new(&pcard->card->dev, + index[dev], id[dev], THIS_MODULE, + sizeof(struct snd_card_als100), &card); if (error < 0) return error; acard = card->private_data; @@ -203,7 +204,6 @@ static int snd_card_als100_probe(int dev, snd_card_free(card); return error; } - snd_card_set_dev(card, &pcard->card->dev); if (pid->driver_data == SB_HW_DT019X) dma16[dev] = -1; diff --git a/sound/isa/azt2320.c b/sound/isa/azt2320.c index db301ff94ec..0ea75fc6207 100644 --- a/sound/isa/azt2320.c +++ b/sound/isa/azt2320.c @@ -184,8 +184,9 @@ static int snd_card_azt2320_probe(int dev, struct snd_wss *chip; struct snd_opl3 *opl3; - error = snd_card_create(index[dev], id[dev], THIS_MODULE, - sizeof(struct snd_card_azt2320), &card); + error = snd_card_new(&pcard->card->dev, + index[dev], id[dev], THIS_MODULE, + sizeof(struct snd_card_azt2320), &card); if (error < 0) return error; acard = card->private_data; @@ -194,7 +195,6 @@ static int snd_card_azt2320_probe(int dev, snd_card_free(card); return error; } - snd_card_set_dev(card, &pcard->card->dev); if ((error = snd_card_azt2320_enable_wss(port[dev]))) { snd_card_free(card); diff --git a/sound/isa/cmi8328.c b/sound/isa/cmi8328.c index ab6b2dc043f..4778852a120 100644 --- a/sound/isa/cmi8328.c +++ b/sound/isa/cmi8328.c @@ -293,15 +293,14 @@ static int snd_cmi8328_probe(struct device *pdev, unsigned int ndev) } outb(val, port); - err = snd_card_create(index[ndev], id[ndev], THIS_MODULE, - sizeof(struct snd_cmi8328), &card); + err = snd_card_new(pdev, index[ndev], id[ndev], THIS_MODULE, + sizeof(struct snd_cmi8328), &card); if (err < 0) return err; cmi = card->private_data; cmi->card = card; cmi->port = port; cmi->wss_cfg = val; - snd_card_set_dev(card, pdev); err = snd_wss_create(card, port + 4, -1, irq[ndev], dma1[ndev], dma2[ndev], WSS_HW_DETECT, 0, &cmi->wss); diff --git a/sound/isa/cmi8330.c b/sound/isa/cmi8330.c index 270b9659ef7..dfedfd85f20 100644 --- a/sound/isa/cmi8330.c +++ b/sound/isa/cmi8330.c @@ -514,14 +514,15 @@ static int snd_cmi8330_resume(struct snd_card *card) #define PFX "cmi8330: " -static int snd_cmi8330_card_new(int dev, struct snd_card **cardp) +static int snd_cmi8330_card_new(struct device *pdev, int dev, + struct snd_card **cardp) { struct snd_card *card; struct snd_cmi8330 *acard; int err; - err = snd_card_create(index[dev], id[dev], THIS_MODULE, - sizeof(struct snd_cmi8330), &card); + err = snd_card_new(pdev, index[dev], id[dev], THIS_MODULE, + sizeof(struct snd_cmi8330), &card); if (err < 0) { snd_printk(KERN_ERR PFX "could not get a new card\n"); return err; @@ -635,10 +636,9 @@ static int snd_cmi8330_isa_probe(struct device *pdev, struct snd_card *card; int err; - err = snd_cmi8330_card_new(dev, &card); + err = snd_cmi8330_card_new(pdev, dev, &card); if (err < 0) return err; - snd_card_set_dev(card, pdev); if ((err = snd_cmi8330_probe(card, dev)) < 0) { snd_card_free(card); return err; @@ -698,7 +698,7 @@ static int snd_cmi8330_pnp_detect(struct pnp_card_link *pcard, if (dev >= SNDRV_CARDS) return -ENODEV; - res = snd_cmi8330_card_new(dev, &card); + res = snd_cmi8330_card_new(&pcard->card->dev, dev, &card); if (res < 0) return res; if ((res = snd_cmi8330_pnp(dev, card->private_data, pcard, pid)) < 0) { @@ -706,7 +706,6 @@ static int snd_cmi8330_pnp_detect(struct pnp_card_link *pcard, snd_card_free(card); return res; } - snd_card_set_dev(card, &pcard->card->dev); if ((res = snd_cmi8330_probe(card, dev)) < 0) { snd_card_free(card); return res; diff --git a/sound/isa/cs423x/cs4231.c b/sound/isa/cs423x/cs4231.c index ba9a74eff3e..7dba07a4343 100644 --- a/sound/isa/cs423x/cs4231.c +++ b/sound/isa/cs423x/cs4231.c @@ -95,7 +95,7 @@ static int snd_cs4231_probe(struct device *dev, unsigned int n) struct snd_pcm *pcm; int error; - error = snd_card_create(index[n], id[n], THIS_MODULE, 0, &card); + error = snd_card_new(dev, index[n], id[n], THIS_MODULE, 0, &card); if (error < 0) return error; @@ -135,8 +135,6 @@ static int snd_cs4231_probe(struct device *dev, unsigned int n) dev_warn(dev, "MPU401 not detected\n"); } - snd_card_set_dev(card, dev); - error = snd_card_register(card); if (error < 0) goto out; diff --git a/sound/isa/cs423x/cs4236.c b/sound/isa/cs423x/cs4236.c index 69614acb205..750f51c904f 100644 --- a/sound/isa/cs423x/cs4236.c +++ b/sound/isa/cs423x/cs4236.c @@ -364,13 +364,14 @@ static void snd_card_cs4236_free(struct snd_card *card) release_and_free_resource(acard->res_sb_port); } -static int snd_cs423x_card_new(int dev, struct snd_card **cardp) +static int snd_cs423x_card_new(struct device *pdev, int dev, + struct snd_card **cardp) { struct snd_card *card; int err; - err = snd_card_create(index[dev], id[dev], THIS_MODULE, - sizeof(struct snd_card_cs4236), &card); + err = snd_card_new(pdev, index[dev], id[dev], THIS_MODULE, + sizeof(struct snd_card_cs4236), &card); if (err < 0) return err; card->private_free = snd_card_cs4236_free; @@ -487,10 +488,9 @@ static int snd_cs423x_isa_probe(struct device *pdev, struct snd_card *card; int err; - err = snd_cs423x_card_new(dev, &card); + err = snd_cs423x_card_new(pdev, dev, &card); if (err < 0) return err; - snd_card_set_dev(card, pdev); if ((err = snd_cs423x_probe(card, dev)) < 0) { snd_card_free(card); return err; @@ -577,7 +577,7 @@ static int snd_cs423x_pnpbios_detect(struct pnp_dev *pdev, if (!strcmp(cdev->id[0].id, cid)) break; } - err = snd_cs423x_card_new(dev, &card); + err = snd_cs423x_card_new(&pdev->dev, dev, &card); if (err < 0) return err; err = snd_card_cs423x_pnp(dev, card->private_data, pdev, cdev); @@ -586,7 +586,6 @@ static int snd_cs423x_pnpbios_detect(struct pnp_dev *pdev, snd_card_free(card); return err; } - snd_card_set_dev(card, &pdev->dev); if ((err = snd_cs423x_probe(card, dev)) < 0) { snd_card_free(card); return err; @@ -638,7 +637,7 @@ static int snd_cs423x_pnpc_detect(struct pnp_card_link *pcard, if (dev >= SNDRV_CARDS) return -ENODEV; - res = snd_cs423x_card_new(dev, &card); + res = snd_cs423x_card_new(&pcard->card->dev, dev, &card); if (res < 0) return res; if ((res = snd_card_cs423x_pnpc(dev, card->private_data, pcard, pid)) < 0) { @@ -647,7 +646,6 @@ static int snd_cs423x_pnpc_detect(struct pnp_card_link *pcard, snd_card_free(card); return res; } - snd_card_set_dev(card, &pcard->card->dev); if ((res = snd_cs423x_probe(card, dev)) < 0) { snd_card_free(card); return res; diff --git a/sound/isa/es1688/es1688.c b/sound/isa/es1688/es1688.c index cdcfb57f1f0..76001fe0579 100644 --- a/sound/isa/es1688/es1688.c +++ b/sound/isa/es1688/es1688.c @@ -187,8 +187,8 @@ static int snd_es1688_isa_probe(struct device *dev, unsigned int n) struct snd_card *card; int error; - error = snd_card_create(index[n], id[n], THIS_MODULE, - sizeof(struct snd_es1688), &card); + error = snd_card_new(dev, index[n], id[n], THIS_MODULE, + sizeof(struct snd_es1688), &card); if (error < 0) return error; @@ -196,8 +196,6 @@ static int snd_es1688_isa_probe(struct device *dev, unsigned int n) if (error < 0) goto out; - snd_card_set_dev(card, dev); - error = snd_es1688_probe(card, n); if (error < 0) goto out; @@ -274,8 +272,9 @@ static int snd_es968_pnp_detect(struct pnp_card_link *pcard, if (dev == SNDRV_CARDS) return -ENODEV; - error = snd_card_create(index[dev], id[dev], THIS_MODULE, - sizeof(struct snd_es1688), &card); + error = snd_card_new(&pcard->card->dev, + index[dev], id[dev], THIS_MODULE, + sizeof(struct snd_es1688), &card); if (error < 0) return error; chip = card->private_data; @@ -285,7 +284,6 @@ static int snd_es968_pnp_detect(struct pnp_card_link *pcard, snd_card_free(card); return error; } - snd_card_set_dev(card, &pcard->card->dev); error = snd_es1688_probe(card, dev); if (error < 0) return error; diff --git a/sound/isa/es18xx.c b/sound/isa/es18xx.c index 12978b864c3..1c16830af3d 100644 --- a/sound/isa/es18xx.c +++ b/sound/isa/es18xx.c @@ -2105,10 +2105,11 @@ static int snd_audiodrive_pnpc(int dev, struct snd_es18xx *chip, #define is_isapnp_selected(dev) 0 #endif -static int snd_es18xx_card_new(int dev, struct snd_card **cardp) +static int snd_es18xx_card_new(struct device *pdev, int dev, + struct snd_card **cardp) { - return snd_card_create(index[dev], id[dev], THIS_MODULE, - sizeof(struct snd_es18xx), cardp); + return snd_card_new(pdev, index[dev], id[dev], THIS_MODULE, + sizeof(struct snd_es18xx), cardp); } static int snd_audiodrive_probe(struct snd_card *card, int dev) @@ -2179,10 +2180,9 @@ static int snd_es18xx_isa_probe1(int dev, struct device *devptr) struct snd_card *card; int err; - err = snd_es18xx_card_new(dev, &card); + err = snd_es18xx_card_new(devptr, dev, &card); if (err < 0) return err; - snd_card_set_dev(card, devptr); if ((err = snd_audiodrive_probe(card, dev)) < 0) { snd_card_free(card); return err; @@ -2284,14 +2284,13 @@ static int snd_audiodrive_pnp_detect(struct pnp_dev *pdev, if (dev >= SNDRV_CARDS) return -ENODEV; - err = snd_es18xx_card_new(dev, &card); + err = snd_es18xx_card_new(&pdev->dev, dev, &card); if (err < 0) return err; if ((err = snd_audiodrive_pnp(dev, card->private_data, pdev)) < 0) { snd_card_free(card); return err; } - snd_card_set_dev(card, &pdev->dev); if ((err = snd_audiodrive_probe(card, dev)) < 0) { snd_card_free(card); return err; @@ -2342,7 +2341,7 @@ static int snd_audiodrive_pnpc_detect(struct pnp_card_link *pcard, if (dev >= SNDRV_CARDS) return -ENODEV; - res = snd_es18xx_card_new(dev, &card); + res = snd_es18xx_card_new(&pcard->card->dev, dev, &card); if (res < 0) return res; @@ -2350,7 +2349,6 @@ static int snd_audiodrive_pnpc_detect(struct pnp_card_link *pcard, snd_card_free(card); return res; } - snd_card_set_dev(card, &pcard->card->dev); if ((res = snd_audiodrive_probe(card, dev)) < 0) { snd_card_free(card); return res; diff --git a/sound/isa/galaxy/galaxy.c b/sound/isa/galaxy/galaxy.c index 81244e7cea5..1eb2b1ec0fd 100644 --- a/sound/isa/galaxy/galaxy.c +++ b/sound/isa/galaxy/galaxy.c @@ -506,13 +506,11 @@ static int snd_galaxy_probe(struct device *dev, unsigned int n) u8 type; int err; - err = snd_card_create(index[n], id[n], THIS_MODULE, sizeof *galaxy, - &card); + err = snd_card_new(dev, index[n], id[n], THIS_MODULE, + sizeof(*galaxy), &card); if (err < 0) return err; - snd_card_set_dev(card, dev); - card->private_free = snd_galaxy_free; galaxy = card->private_data; diff --git a/sound/isa/gus/gusclassic.c b/sound/isa/gus/gusclassic.c index 1adc1b924f3..7ce29ffa1af 100644 --- a/sound/isa/gus/gusclassic.c +++ b/sound/isa/gus/gusclassic.c @@ -149,7 +149,7 @@ static int snd_gusclassic_probe(struct device *dev, unsigned int n) struct snd_gus_card *gus; int error; - error = snd_card_create(index[n], id[n], THIS_MODULE, 0, &card); + error = snd_card_new(dev, index[n], id[n], THIS_MODULE, 0, &card); if (error < 0) return error; @@ -199,8 +199,6 @@ static int snd_gusclassic_probe(struct device *dev, unsigned int n) sprintf(card->longname + strlen(card->longname), "&%d", gus->gf1.dma2); - snd_card_set_dev(card, dev); - error = snd_card_register(card); if (error < 0) goto out; diff --git a/sound/isa/gus/gusextreme.c b/sound/isa/gus/gusextreme.c index 38e1e3260c2..28a16936a39 100644 --- a/sound/isa/gus/gusextreme.c +++ b/sound/isa/gus/gusextreme.c @@ -242,8 +242,8 @@ static int snd_gusextreme_probe(struct device *dev, unsigned int n) struct snd_opl3 *opl3; int error; - error = snd_card_create(index[n], id[n], THIS_MODULE, - sizeof(struct snd_es1688), &card); + error = snd_card_new(dev, index[n], id[n], THIS_MODULE, + sizeof(struct snd_es1688), &card); if (error < 0) return error; @@ -328,8 +328,6 @@ static int snd_gusextreme_probe(struct device *dev, unsigned int n) "irq %i&%i, dma %i&%i", es1688->port, gus->gf1.irq, es1688->irq, gus->gf1.dma1, es1688->dma8); - snd_card_set_dev(card, dev); - error = snd_card_register(card); if (error < 0) goto out; diff --git a/sound/isa/gus/gusmax.c b/sound/isa/gus/gusmax.c index 652d5d83462..39df36ca3ac 100644 --- a/sound/isa/gus/gusmax.c +++ b/sound/isa/gus/gusmax.c @@ -214,8 +214,8 @@ static int snd_gusmax_probe(struct device *pdev, unsigned int dev) struct snd_wss *wss; struct snd_gusmax *maxcard; - err = snd_card_create(index[dev], id[dev], THIS_MODULE, - sizeof(struct snd_gusmax), &card); + err = snd_card_new(pdev, index[dev], id[dev], THIS_MODULE, + sizeof(struct snd_gusmax), &card); if (err < 0) return err; card->private_free = snd_gusmax_free; @@ -337,8 +337,6 @@ static int snd_gusmax_probe(struct device *pdev, unsigned int dev) if (xdma2 >= 0) sprintf(card->longname + strlen(card->longname), "&%i", xdma2); - snd_card_set_dev(card, pdev); - err = snd_card_register(card); if (err < 0) goto _err; diff --git a/sound/isa/gus/interwave.c b/sound/isa/gus/interwave.c index afef0d73807..5abbbe477d1 100644 --- a/sound/isa/gus/interwave.c +++ b/sound/isa/gus/interwave.c @@ -625,14 +625,15 @@ static void snd_interwave_free(struct snd_card *card) free_irq(iwcard->irq, (void *)iwcard); } -static int snd_interwave_card_new(int dev, struct snd_card **cardp) +static int snd_interwave_card_new(struct device *pdev, int dev, + struct snd_card **cardp) { struct snd_card *card; struct snd_interwave *iwcard; int err; - err = snd_card_create(index[dev], id[dev], THIS_MODULE, - sizeof(struct snd_interwave), &card); + err = snd_card_new(pdev, index[dev], id[dev], THIS_MODULE, + sizeof(struct snd_interwave), &card); if (err < 0) return err; iwcard = card->private_data; @@ -779,11 +780,10 @@ static int snd_interwave_isa_probe1(int dev, struct device *devptr) struct snd_card *card; int err; - err = snd_interwave_card_new(dev, &card); + err = snd_interwave_card_new(devptr, dev, &card); if (err < 0) return err; - snd_card_set_dev(card, devptr); if ((err = snd_interwave_probe(card, dev)) < 0) { snd_card_free(card); return err; @@ -876,7 +876,7 @@ static int snd_interwave_pnp_detect(struct pnp_card_link *pcard, if (dev >= SNDRV_CARDS) return -ENODEV; - res = snd_interwave_card_new(dev, &card); + res = snd_interwave_card_new(&pcard->card->dev, dev, &card); if (res < 0) return res; @@ -884,7 +884,6 @@ static int snd_interwave_pnp_detect(struct pnp_card_link *pcard, snd_card_free(card); return res; } - snd_card_set_dev(card, &pcard->card->dev); if ((res = snd_interwave_probe(card, dev)) < 0) { snd_card_free(card); return res; diff --git a/sound/isa/msnd/msnd_pinnacle.c b/sound/isa/msnd/msnd_pinnacle.c index 0a90bd6ae23..5016bf957f5 100644 --- a/sound/isa/msnd/msnd_pinnacle.c +++ b/sound/isa/msnd/msnd_pinnacle.c @@ -905,12 +905,11 @@ static int snd_msnd_isa_probe(struct device *pdev, unsigned int idx) return -ENODEV; } - err = snd_card_create(index[idx], id[idx], THIS_MODULE, - sizeof(struct snd_msnd), &card); + err = snd_card_new(pdev, index[idx], id[idx], THIS_MODULE, + sizeof(struct snd_msnd), &card); if (err < 0) return err; - snd_card_set_dev(card, pdev); chip = card->private_data; chip->card = card; @@ -1122,14 +1121,14 @@ static int snd_msnd_pnp_detect(struct pnp_card_link *pcard, * Create a new ALSA sound card entry, in anticipation * of detecting our hardware ... */ - ret = snd_card_create(index[idx], id[idx], THIS_MODULE, - sizeof(struct snd_msnd), &card); + ret = snd_card_new(&pcard->card->dev, + index[idx], id[idx], THIS_MODULE, + sizeof(struct snd_msnd), &card); if (ret < 0) return ret; chip = card->private_data; chip->card = card; - snd_card_set_dev(card, &pcard->card->dev); /* * Read the correct parameters off the ISA PnP bus ... diff --git a/sound/isa/opl3sa2.c b/sound/isa/opl3sa2.c index cc01c419b7e..a219bc37816 100644 --- a/sound/isa/opl3sa2.c +++ b/sound/isa/opl3sa2.c @@ -627,14 +627,15 @@ static void snd_opl3sa2_free(struct snd_card *card) release_and_free_resource(chip->res_port); } -static int snd_opl3sa2_card_new(int dev, struct snd_card **cardp) +static int snd_opl3sa2_card_new(struct device *pdev, int dev, + struct snd_card **cardp) { struct snd_card *card; struct snd_opl3sa2 *chip; int err; - err = snd_card_create(index[dev], id[dev], THIS_MODULE, - sizeof(struct snd_opl3sa2), &card); + err = snd_card_new(pdev, index[dev], id[dev], THIS_MODULE, + sizeof(struct snd_opl3sa2), &card); if (err < 0) return err; strcpy(card->driver, "OPL3SA2"); @@ -737,14 +738,13 @@ static int snd_opl3sa2_pnp_detect(struct pnp_dev *pdev, if (dev >= SNDRV_CARDS) return -ENODEV; - err = snd_opl3sa2_card_new(dev, &card); + err = snd_opl3sa2_card_new(&pdev->dev, dev, &card); if (err < 0) return err; if ((err = snd_opl3sa2_pnp(dev, card->private_data, pdev)) < 0) { snd_card_free(card); return err; } - snd_card_set_dev(card, &pdev->dev); if ((err = snd_opl3sa2_probe(card, dev)) < 0) { snd_card_free(card); return err; @@ -802,14 +802,13 @@ static int snd_opl3sa2_pnp_cdetect(struct pnp_card_link *pcard, if (dev >= SNDRV_CARDS) return -ENODEV; - err = snd_opl3sa2_card_new(dev, &card); + err = snd_opl3sa2_card_new(&pdev->dev, dev, &card); if (err < 0) return err; if ((err = snd_opl3sa2_pnp(dev, card->private_data, pdev)) < 0) { snd_card_free(card); return err; } - snd_card_set_dev(card, &pdev->dev); if ((err = snd_opl3sa2_probe(card, dev)) < 0) { snd_card_free(card); return err; @@ -883,10 +882,9 @@ static int snd_opl3sa2_isa_probe(struct device *pdev, struct snd_card *card; int err; - err = snd_opl3sa2_card_new(dev, &card); + err = snd_opl3sa2_card_new(pdev, dev, &card); if (err < 0) return err; - snd_card_set_dev(card, pdev); if ((err = snd_opl3sa2_probe(card, dev)) < 0) { snd_card_free(card); return err; diff --git a/sound/isa/opti9xx/miro.c b/sound/isa/opti9xx/miro.c index 619753d96ca..c2ca681ac51 100644 --- a/sound/isa/opti9xx/miro.c +++ b/sound/isa/opti9xx/miro.c @@ -1411,8 +1411,8 @@ static int snd_miro_isa_probe(struct device *devptr, unsigned int n) struct snd_miro *miro; struct snd_card *card; - error = snd_card_create(index, id, THIS_MODULE, - sizeof(struct snd_miro), &card); + error = snd_card_new(devptr, index, id, THIS_MODULE, + sizeof(struct snd_miro), &card); if (error < 0) return error; @@ -1479,8 +1479,6 @@ static int snd_miro_isa_probe(struct device *devptr, unsigned int n) } } - snd_card_set_dev(card, devptr); - error = snd_miro_probe(card); if (error < 0) { snd_card_free(card); @@ -1584,8 +1582,8 @@ static int snd_miro_pnp_probe(struct pnp_card_link *pcard, return -EBUSY; if (!isapnp) return -ENODEV; - err = snd_card_create(index, id, THIS_MODULE, - sizeof(struct snd_miro), &card); + err = snd_card_new(&pcard->card->dev, index, id, THIS_MODULE, + sizeof(struct snd_miro), &card); if (err < 0) return err; @@ -1612,7 +1610,6 @@ static int snd_miro_pnp_probe(struct pnp_card_link *pcard, return err; } - snd_card_set_dev(card, &pcard->card->dev); err = snd_miro_probe(card); if (err < 0) { snd_card_free(card); diff --git a/sound/isa/opti9xx/opti92x-ad1848.c b/sound/isa/opti9xx/opti92x-ad1848.c index 6effe99bbb9..c9b58284860 100644 --- a/sound/isa/opti9xx/opti92x-ad1848.c +++ b/sound/isa/opti9xx/opti92x-ad1848.c @@ -934,13 +934,13 @@ static int snd_opti9xx_probe(struct snd_card *card) return snd_card_register(card); } -static int snd_opti9xx_card_new(struct snd_card **cardp) +static int snd_opti9xx_card_new(struct device *pdev, struct snd_card **cardp) { struct snd_card *card; int err; - err = snd_card_create(index, id, THIS_MODULE, - sizeof(struct snd_opti9xx), &card); + err = snd_card_new(pdev, index, id, THIS_MODULE, + sizeof(struct snd_opti9xx), &card); if (err < 0) return err; card->private_free = snd_card_opti9xx_free; @@ -1010,7 +1010,7 @@ static int snd_opti9xx_isa_probe(struct device *devptr, } #endif - error = snd_opti9xx_card_new(&card); + error = snd_opti9xx_card_new(devptr, &card); if (error < 0) return error; @@ -1018,7 +1018,6 @@ static int snd_opti9xx_isa_probe(struct device *devptr, snd_card_free(card); return error; } - snd_card_set_dev(card, devptr); if ((error = snd_opti9xx_probe(card)) < 0) { snd_card_free(card); return error; @@ -1100,7 +1099,7 @@ static int snd_opti9xx_pnp_probe(struct pnp_card_link *pcard, return -EBUSY; if (! isapnp) return -ENODEV; - error = snd_opti9xx_card_new(&card); + error = snd_opti9xx_card_new(&pcard->card->dev, &card); if (error < 0) return error; chip = card->private_data; @@ -1131,7 +1130,6 @@ static int snd_opti9xx_pnp_probe(struct pnp_card_link *pcard, snd_card_free(card); return error; } - snd_card_set_dev(card, &pcard->card->dev); if ((error = snd_opti9xx_probe(card)) < 0) { snd_card_free(card); return error; diff --git a/sound/isa/sb/jazz16.c b/sound/isa/sb/jazz16.c index 356a6308392..90d2eba549e 100644 --- a/sound/isa/sb/jazz16.c +++ b/sound/isa/sb/jazz16.c @@ -229,8 +229,8 @@ static int snd_jazz16_probe(struct device *devptr, unsigned int dev) static int possible_dmas16[] = {5, 7, -1}; int err, xirq, xdma8, xdma16, xmpu_port, xmpu_irq; - err = snd_card_create(index[dev], id[dev], THIS_MODULE, - sizeof(struct snd_card_jazz16), &card); + err = snd_card_new(devptr, index[dev], id[dev], THIS_MODULE, + sizeof(struct snd_card_jazz16), &card); if (err < 0) return err; @@ -327,8 +327,6 @@ static int snd_jazz16_probe(struct device *devptr, unsigned int dev) mpu_port[dev]); } - snd_card_set_dev(card, devptr); - err = snd_card_register(card); if (err < 0) goto err_free; diff --git a/sound/isa/sb/sb16.c b/sound/isa/sb/sb16.c index a4130993955..3f694543a7e 100644 --- a/sound/isa/sb/sb16.c +++ b/sound/isa/sb/sb16.c @@ -323,13 +323,14 @@ static void snd_sb16_free(struct snd_card *card) #define is_isapnp_selected(dev) 0 #endif -static int snd_sb16_card_new(int dev, struct snd_card **cardp) +static int snd_sb16_card_new(struct device *devptr, int dev, + struct snd_card **cardp) { struct snd_card *card; int err; - err = snd_card_create(index[dev], id[dev], THIS_MODULE, - sizeof(struct snd_card_sb16), &card); + err = snd_card_new(devptr, index[dev], id[dev], THIS_MODULE, + sizeof(struct snd_card_sb16), &card); if (err < 0) return err; card->private_free = snd_sb16_free; @@ -493,7 +494,7 @@ static int snd_sb16_isa_probe1(int dev, struct device *pdev) struct snd_card *card; int err; - err = snd_sb16_card_new(dev, &card); + err = snd_sb16_card_new(pdev, dev, &card); if (err < 0) return err; @@ -507,7 +508,6 @@ static int snd_sb16_isa_probe1(int dev, struct device *pdev) awe_port[dev] = port[dev] + 0x400; #endif - snd_card_set_dev(card, pdev); if ((err = snd_sb16_probe(card, dev)) < 0) { snd_card_free(card); return err; @@ -613,10 +613,9 @@ static int snd_sb16_pnp_detect(struct pnp_card_link *pcard, for ( ; dev < SNDRV_CARDS; dev++) { if (!enable[dev] || !isapnp[dev]) continue; - res = snd_sb16_card_new(dev, &card); + res = snd_sb16_card_new(&pcard->card->dev, dev, &card); if (res < 0) return res; - snd_card_set_dev(card, &pcard->card->dev); if ((res = snd_card_sb16_pnp(dev, card->private_data, pcard, pid)) < 0 || (res = snd_sb16_probe(card, dev)) < 0) { snd_card_free(card); diff --git a/sound/isa/sb/sb8.c b/sound/isa/sb/sb8.c index a806ae90a94..6c32b3aa34a 100644 --- a/sound/isa/sb/sb8.c +++ b/sound/isa/sb/sb8.c @@ -102,8 +102,8 @@ static int snd_sb8_probe(struct device *pdev, unsigned int dev) struct snd_opl3 *opl3; int err; - err = snd_card_create(index[dev], id[dev], THIS_MODULE, - sizeof(struct snd_sb8), &card); + err = snd_card_new(pdev, index[dev], id[dev], THIS_MODULE, + sizeof(struct snd_sb8), &card); if (err < 0) return err; acard = card->private_data; @@ -192,8 +192,6 @@ static int snd_sb8_probe(struct device *pdev, unsigned int dev) chip->port, irq[dev], dma8[dev]); - snd_card_set_dev(card, pdev); - if ((err = snd_card_register(card)) < 0) goto _err; diff --git a/sound/isa/sc6000.c b/sound/isa/sc6000.c index 09d481b3ba7..15a152eaa2e 100644 --- a/sound/isa/sc6000.c +++ b/sound/isa/sc6000.c @@ -559,8 +559,8 @@ static int snd_sc6000_probe(struct device *devptr, unsigned int dev) char __iomem *vmss_port; - err = snd_card_create(index[dev], id[dev], THIS_MODULE, sizeof(vport), - &card); + err = snd_card_new(devptr, index[dev], id[dev], THIS_MODULE, + sizeof(vport), &card); if (err < 0) return err; @@ -668,8 +668,6 @@ static int snd_sc6000_probe(struct device *devptr, unsigned int dev) sprintf(card->longname, "Gallant SC-6000 at 0x%lx, irq %d, dma %d", mss_port[dev], xirq, xdma); - snd_card_set_dev(card, devptr); - err = snd_card_register(card); if (err < 0) goto err_unmap2; diff --git a/sound/isa/sscape.c b/sound/isa/sscape.c index 57b338973ed..44405df7d4b 100644 --- a/sound/isa/sscape.c +++ b/sound/isa/sscape.c @@ -1169,8 +1169,8 @@ static int snd_sscape_probe(struct device *pdev, unsigned int dev) struct soundscape *sscape; int ret; - ret = snd_card_create(index[dev], id[dev], THIS_MODULE, - sizeof(struct soundscape), &card); + ret = snd_card_new(pdev, index[dev], id[dev], THIS_MODULE, + sizeof(struct soundscape), &card); if (ret < 0) return ret; @@ -1178,7 +1178,6 @@ static int snd_sscape_probe(struct device *pdev, unsigned int dev) sscape->type = SSCAPE; dma[dev] &= 0x03; - snd_card_set_dev(card, pdev); ret = create_sscape(dev, card); if (ret < 0) @@ -1259,8 +1258,9 @@ static int sscape_pnp_detect(struct pnp_card_link *pcard, * Create a new ALSA sound card entry, in anticipation * of detecting our hardware ... */ - ret = snd_card_create(index[idx], id[idx], THIS_MODULE, - sizeof(struct soundscape), &card); + ret = snd_card_new(&pcard->card->dev, + index[idx], id[idx], THIS_MODULE, + sizeof(struct soundscape), &card); if (ret < 0) return ret; @@ -1288,7 +1288,6 @@ static int sscape_pnp_detect(struct pnp_card_link *pcard, wss_port[idx] = pnp_port_start(dev, 1); dma2[idx] = pnp_dma(dev, 1); } - snd_card_set_dev(card, &pcard->card->dev); ret = create_sscape(idx, card); if (ret < 0) diff --git a/sound/isa/wavefront/wavefront.c b/sound/isa/wavefront/wavefront.c index 82dd76939fa..bfbf38cf984 100644 --- a/sound/isa/wavefront/wavefront.c +++ b/sound/isa/wavefront/wavefront.c @@ -334,14 +334,15 @@ snd_wavefront_free(struct snd_card *card) } } -static int snd_wavefront_card_new(int dev, struct snd_card **cardp) +static int snd_wavefront_card_new(struct device *pdev, int dev, + struct snd_card **cardp) { struct snd_card *card; snd_wavefront_card_t *acard; int err; - err = snd_card_create(index[dev], id[dev], THIS_MODULE, - sizeof(snd_wavefront_card_t), &card); + err = snd_card_new(pdev, index[dev], id[dev], THIS_MODULE, + sizeof(snd_wavefront_card_t), &card); if (err < 0) return err; @@ -564,10 +565,9 @@ static int snd_wavefront_isa_probe(struct device *pdev, struct snd_card *card; int err; - err = snd_wavefront_card_new(dev, &card); + err = snd_wavefront_card_new(pdev, dev, &card); if (err < 0) return err; - snd_card_set_dev(card, pdev); if ((err = snd_wavefront_probe(card, dev)) < 0) { snd_card_free(card); return err; @@ -612,7 +612,7 @@ static int snd_wavefront_pnp_detect(struct pnp_card_link *pcard, if (dev >= SNDRV_CARDS) return -ENODEV; - res = snd_wavefront_card_new(dev, &card); + res = snd_wavefront_card_new(&pcard->card->dev, dev, &card); if (res < 0) return res; @@ -623,7 +623,6 @@ static int snd_wavefront_pnp_detect(struct pnp_card_link *pcard, return -ENODEV; } } - snd_card_set_dev(card, &pcard->card->dev); if ((res = snd_wavefront_probe(card, dev)) < 0) return res; diff --git a/sound/mips/au1x00.c b/sound/mips/au1x00.c index 224f54be15a..a7cc49e9606 100644 --- a/sound/mips/au1x00.c +++ b/sound/mips/au1x00.c @@ -37,6 +37,7 @@ #include <linux/ioport.h> #include <linux/interrupt.h> #include <linux/init.h> +#include <linux/platform_device.h> #include <linux/slab.h> #include <linux/module.h> #include <sound/core.h> @@ -98,6 +99,7 @@ struct snd_au1000 { struct snd_pcm *pcm; struct audio_stream *stream[2]; /* playback & capture */ + int dmaid[2]; /* tx(0)/rx(1) DMA ids */ }; /*--------------------------- Local Functions --------------------------------*/ @@ -465,15 +467,17 @@ snd_au1000_pcm_new(struct snd_au1000 *au1000) spin_lock_init(&au1000->stream[CAPTURE]->dma_lock); flags = claim_dma_lock(); - if ((au1000->stream[PLAYBACK]->dma = request_au1000_dma(DMA_ID_AC97C_TX, + au1000->stream[PLAYBACK]->dma = request_au1000_dma(au1000->dmaid[0], "AC97 TX", au1000_dma_interrupt, 0, - au1000->stream[PLAYBACK])) < 0) { + au1000->stream[PLAYBACK]); + if (au1000->stream[PLAYBACK]->dma < 0) { release_dma_lock(flags); return -EBUSY; } - if ((au1000->stream[CAPTURE]->dma = request_au1000_dma(DMA_ID_AC97C_RX, + au1000->stream[CAPTURE]->dma = request_au1000_dma(au1000->dmaid[1], "AC97 RX", au1000_dma_interrupt, 0, - au1000->stream[CAPTURE])) < 0){ + au1000->stream[CAPTURE]); + if (au1000->stream[CAPTURE]->dma < 0){ release_dma_lock(flags); return -EBUSY; } @@ -552,69 +556,12 @@ get the interrupt driven case to work efficiently */ spin_unlock(&au1000->ac97_lock); } -static int -snd_au1000_ac97_new(struct snd_au1000 *au1000) -{ - int err; - struct snd_ac97_bus *pbus; - struct snd_ac97_template ac97; - static struct snd_ac97_bus_ops ops = { - .write = snd_au1000_ac97_write, - .read = snd_au1000_ac97_read, - }; - - if ((au1000->ac97_res_port = request_mem_region(CPHYSADDR(AC97C_CONFIG), - 0x100000, "Au1x00 AC97")) == NULL) { - snd_printk(KERN_ERR "ALSA AC97: can't grap AC97 port\n"); - return -EBUSY; - } - au1000->ac97_ioport = (struct au1000_ac97_reg *) - KSEG1ADDR(au1000->ac97_res_port->start); - - spin_lock_init(&au1000->ac97_lock); - - /* configure pins for AC'97 - TODO: move to board_setup.c */ - au_writel(au_readl(SYS_PINFUNC) & ~0x02, SYS_PINFUNC); - - /* Initialise Au1000's AC'97 Control Block */ - au1000->ac97_ioport->cntrl = AC97C_RS | AC97C_CE; - udelay(10); - au1000->ac97_ioport->cntrl = AC97C_CE; - udelay(10); - - /* Initialise External CODEC -- cold reset */ - au1000->ac97_ioport->config = AC97C_RESET; - udelay(10); - au1000->ac97_ioport->config = 0x0; - mdelay(5); - - /* Initialise AC97 middle-layer */ - if ((err = snd_ac97_bus(au1000->card, 0, &ops, au1000, &pbus)) < 0) - return err; - - memset(&ac97, 0, sizeof(ac97)); - ac97.private_data = au1000; - if ((err = snd_ac97_mixer(pbus, &ac97, &au1000->ac97)) < 0) - return err; - - return 0; -} - /*------------------------------ Setup / Destroy ----------------------------*/ -void -snd_au1000_free(struct snd_card *card) +static void snd_au1000_free(struct snd_card *card) { struct snd_au1000 *au1000 = card->private_data; - if (au1000->ac97_res_port) { - /* put internal AC97 block into reset */ - au1000->ac97_ioport->cntrl = AC97C_RS; - au1000->ac97_ioport = NULL; - release_and_free_resource(au1000->ac97_res_port); - } - if (au1000->stream[PLAYBACK]) { if (au1000->stream[PLAYBACK]->dma >= 0) free_au1000_dma(au1000->stream[PLAYBACK]->dma); @@ -626,71 +573,167 @@ snd_au1000_free(struct snd_card *card) free_au1000_dma(au1000->stream[CAPTURE]->dma); kfree(au1000->stream[CAPTURE]); } -} + if (au1000->ac97_res_port) { + /* put internal AC97 block into reset */ + if (au1000->ac97_ioport) { + au1000->ac97_ioport->cntrl = AC97C_RS; + iounmap(au1000->ac97_ioport); + au1000->ac97_ioport = NULL; + } + release_and_free_resource(au1000->ac97_res_port); + au1000->ac97_res_port = NULL; + } +} -static struct snd_card *au1000_card; +static struct snd_ac97_bus_ops ops = { + .write = snd_au1000_ac97_write, + .read = snd_au1000_ac97_read, +}; -static int __init -au1000_init(void) +static int au1000_ac97_probe(struct platform_device *pdev) { int err; + void __iomem *io; + struct resource *r; struct snd_card *card; struct snd_au1000 *au1000; + struct snd_ac97_bus *pbus; + struct snd_ac97_template ac97; - err = snd_card_create(-1, "AC97", THIS_MODULE, - sizeof(struct snd_au1000), &card); + err = snd_card_new(&pdev->dev, -1, "AC97", THIS_MODULE, + sizeof(struct snd_au1000), &card); if (err < 0) return err; - card->private_free = snd_au1000_free; au1000 = card->private_data; au1000->card = card; + spin_lock_init(&au1000->ac97_lock); - au1000->stream[PLAYBACK] = kmalloc(sizeof(struct audio_stream), GFP_KERNEL); - au1000->stream[CAPTURE ] = kmalloc(sizeof(struct audio_stream), GFP_KERNEL); - /* so that snd_au1000_free will work as intended */ - au1000->ac97_res_port = NULL; - if (au1000->stream[PLAYBACK]) - au1000->stream[PLAYBACK]->dma = -1; - if (au1000->stream[CAPTURE ]) - au1000->stream[CAPTURE ]->dma = -1; - - if (au1000->stream[PLAYBACK] == NULL || - au1000->stream[CAPTURE ] == NULL) { - snd_card_free(card); - return -ENOMEM; - } + /* from here on let ALSA call the special freeing function */ + card->private_free = snd_au1000_free; - if ((err = snd_au1000_ac97_new(au1000)) < 0 ) { - snd_card_free(card); - return err; + /* TX DMA ID */ + r = platform_get_resource(pdev, IORESOURCE_DMA, 0); + if (!r) { + err = -ENODEV; + snd_printk(KERN_INFO "no TX DMA platform resource!\n"); + goto out; } - - if ((err = snd_au1000_pcm_new(au1000)) < 0) { - snd_card_free(card); - return err; + au1000->dmaid[0] = r->start; + + /* RX DMA ID */ + r = platform_get_resource(pdev, IORESOURCE_DMA, 1); + if (!r) { + err = -ENODEV; + snd_printk(KERN_INFO "no RX DMA platform resource!\n"); + goto out; + } + au1000->dmaid[1] = r->start; + + au1000->stream[PLAYBACK] = kmalloc(sizeof(struct audio_stream), + GFP_KERNEL); + if (!au1000->stream[PLAYBACK]) + goto out; + au1000->stream[PLAYBACK]->dma = -1; + + au1000->stream[CAPTURE] = kmalloc(sizeof(struct audio_stream), + GFP_KERNEL); + if (!au1000->stream[CAPTURE]) + goto out; + au1000->stream[CAPTURE]->dma = -1; + + r = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!r) + goto out; + + err = -EBUSY; + au1000->ac97_res_port = request_mem_region(r->start, + r->end - r->start + 1, pdev->name); + if (!au1000->ac97_res_port) { + snd_printk(KERN_ERR "ALSA AC97: can't grab AC97 port\n"); + goto out; } + io = ioremap(r->start, r->end - r->start + 1); + if (!io) + goto out; + + au1000->ac97_ioport = (struct au1000_ac97_reg *)io; + + /* configure pins for AC'97 + TODO: move to board_setup.c */ + au_writel(au_readl(SYS_PINFUNC) & ~0x02, SYS_PINFUNC); + + /* Initialise Au1000's AC'97 Control Block */ + au1000->ac97_ioport->cntrl = AC97C_RS | AC97C_CE; + udelay(10); + au1000->ac97_ioport->cntrl = AC97C_CE; + udelay(10); + + /* Initialise External CODEC -- cold reset */ + au1000->ac97_ioport->config = AC97C_RESET; + udelay(10); + au1000->ac97_ioport->config = 0x0; + mdelay(5); + + /* Initialise AC97 middle-layer */ + err = snd_ac97_bus(au1000->card, 0, &ops, au1000, &pbus); + if (err < 0) + goto out; + + memset(&ac97, 0, sizeof(ac97)); + ac97.private_data = au1000; + err = snd_ac97_mixer(pbus, &ac97, &au1000->ac97); + if (err < 0) + goto out; + + err = snd_au1000_pcm_new(au1000); + if (err < 0) + goto out; + strcpy(card->driver, "Au1000-AC97"); strcpy(card->shortname, "AMD Au1000-AC97"); sprintf(card->longname, "AMD Au1000--AC97 ALSA Driver"); - if ((err = snd_card_register(card)) < 0) { - snd_card_free(card); - return err; - } + err = snd_card_register(card); + if (err < 0) + goto out; printk(KERN_INFO "ALSA AC97: Driver Initialized\n"); - au1000_card = card; + + platform_set_drvdata(pdev, card); + return 0; + + out: + snd_card_free(card); + return err; +} + +static int au1000_ac97_remove(struct platform_device *pdev) +{ + return snd_card_free(platform_get_drvdata(pdev)); } -static void __exit au1000_exit(void) +struct platform_driver au1000_ac97c_driver = { + .driver = { + .name = "au1000-ac97c", + .owner = THIS_MODULE, + }, + .probe = au1000_ac97_probe, + .remove = au1000_ac97_remove, +}; + +static int __init au1000_ac97_load(void) { - snd_card_free(au1000_card); + return platform_driver_register(&au1000_ac97c_driver); } -module_init(au1000_init); -module_exit(au1000_exit); +static void __exit au1000_ac97_unload(void) +{ + platform_driver_unregister(&au1000_ac97c_driver); +} +module_init(au1000_ac97_load); +module_exit(au1000_ac97_unload); diff --git a/sound/mips/hal2.c b/sound/mips/hal2.c index 2b7f6e8bdd2..23441b9e614 100644 --- a/sound/mips/hal2.c +++ b/sound/mips/hal2.c @@ -880,7 +880,7 @@ static int hal2_probe(struct platform_device *pdev) struct snd_hal2 *chip; int err; - err = snd_card_create(index, id, THIS_MODULE, 0, &card); + err = snd_card_new(&pdev->dev, index, id, THIS_MODULE, 0, &card); if (err < 0) return err; @@ -889,7 +889,6 @@ static int hal2_probe(struct platform_device *pdev) snd_card_free(card); return err; } - snd_card_set_dev(card, &pdev->dev); err = hal2_pcm_create(chip); if (err < 0) { diff --git a/sound/mips/sgio2audio.c b/sound/mips/sgio2audio.c index cfe99ae149f..04bb06c03ec 100644 --- a/sound/mips/sgio2audio.c +++ b/sound/mips/sgio2audio.c @@ -920,7 +920,7 @@ static int snd_sgio2audio_probe(struct platform_device *pdev) struct snd_sgio2audio *chip; int err; - err = snd_card_create(index, id, THIS_MODULE, 0, &card); + err = snd_card_new(&pdev->dev, index, id, THIS_MODULE, 0, &card); if (err < 0) return err; @@ -929,7 +929,6 @@ static int snd_sgio2audio_probe(struct platform_device *pdev) snd_card_free(card); return err; } - snd_card_set_dev(card, &pdev->dev); err = snd_sgio2audio_new_pcm(chip); if (err < 0) { diff --git a/sound/oss/pas2.h b/sound/oss/pas2.h index fa12c55f560..d19f757dbd7 100644 --- a/sound/oss/pas2.h +++ b/sound/oss/pas2.h @@ -15,3 +15,6 @@ int pas_init_mixer(void); /* From pas_midi.c */ void pas_midi_init(void); void pas_midi_interrupt(void); + +/* From pas2_mixer.c*/ +void mix_write(unsigned char data, int ioaddr); diff --git a/sound/oss/pas2_card.c b/sound/oss/pas2_card.c index 7004e24d209..b07954a7953 100644 --- a/sound/oss/pas2_card.c +++ b/sound/oss/pas2_card.c @@ -74,8 +74,6 @@ static char *pas_model_names[] = { * to support other than the default base address */ -extern void mix_write(unsigned char data, int ioaddr); - unsigned char pas_read(int ioaddr) { return inb(ioaddr + pas_translate_code); diff --git a/sound/parisc/harmony.c b/sound/parisc/harmony.c index 67f56a2cee6..4b20be79c1d 100644 --- a/sound/parisc/harmony.c +++ b/sound/parisc/harmony.c @@ -959,8 +959,6 @@ snd_harmony_create(struct snd_card *card, goto free_and_ret; } - snd_card_set_dev(card, &padev->dev); - *rchip = h; return 0; @@ -977,7 +975,7 @@ snd_harmony_probe(struct parisc_device *padev) struct snd_card *card; struct snd_harmony *h; - err = snd_card_create(index, id, THIS_MODULE, 0, &card); + err = snd_card_new(&padev->dev, index, id, THIS_MODULE, 0, &card); if (err < 0) return err; diff --git a/sound/pci/Kconfig b/sound/pci/Kconfig index 8756c8e3292..0b0c0cf13f7 100644 --- a/sound/pci/Kconfig +++ b/sound/pci/Kconfig @@ -276,7 +276,7 @@ config SND_CS46XX_NEW_DSP config SND_CS5530 tristate "CS5530 Audio" - depends on ISA_DMA_API + depends on ISA_DMA_API && (X86_32 || COMPILE_TEST) select SND_SB16_DSP help Say Y here to include support for audio on Cyrix/NatSemi CS5530 chips. @@ -286,6 +286,7 @@ config SND_CS5530 config SND_CS5535AUDIO tristate "CS5535/CS5536 Audio" + depends on X86_32 || MIPS || COMPILE_TEST select SND_PCM select SND_AC97_CODEC help @@ -578,8 +579,6 @@ config SND_FM801_TEA575X_BOOL FM801 chip with a TEA5757 tuner (MediaForte SF256-PCS, SF256-PCP and SF64-PCR) into the snd-fm801 driver. -source "sound/pci/hda/Kconfig" - config SND_HDSP tristate "RME Hammerfall DSP Audio" select FW_LOADER @@ -796,7 +795,7 @@ config SND_RME9652 config SND_SIS7019 tristate "SiS 7019 Audio Accelerator" - depends on X86 && !X86_64 + depends on X86_32 select SND_AC97_CODEC select ZONE_DMA help @@ -889,3 +888,5 @@ config SND_YMFPCI will be called snd-ymfpci. endif # SND_PCI + +source "sound/pci/hda/Kconfig" diff --git a/sound/pci/ac97/ac97_codec.c b/sound/pci/ac97/ac97_codec.c index bf578ba2677..14ad54b7928 100644 --- a/sound/pci/ac97/ac97_codec.c +++ b/sound/pci/ac97/ac97_codec.c @@ -214,6 +214,12 @@ static void update_power_regs(struct snd_ac97 *ac97); #define ac97_is_power_save_mode(ac97) 0 #endif +#define ac97_err(ac97, fmt, args...) \ + dev_err((ac97)->bus->card->dev, fmt, ##args) +#define ac97_warn(ac97, fmt, args...) \ + dev_warn((ac97)->bus->card->dev, fmt, ##args) +#define ac97_dbg(ac97, fmt, args...) \ + dev_dbg((ac97)->bus->card->dev, fmt, ##args) /* * I/O routines @@ -1673,7 +1679,7 @@ static int snd_ac97_modem_build(struct snd_card *card, struct snd_ac97 * ac97) int err, idx; /* - printk(KERN_DEBUG "AC97_GPIO_CFG = %x\n", + ac97_dbg(ac97, "AC97_GPIO_CFG = %x\n", snd_ac97_read(ac97,AC97_GPIO_CFG)); */ snd_ac97_write(ac97, AC97_GPIO_CFG, 0xffff & ~(AC97_GPIO_LINE1_OH)); @@ -1963,7 +1969,7 @@ static int snd_ac97_dev_register(struct snd_device *device) ac97->bus->card->number, ac97->num, snd_ac97_get_short_name(ac97)); if ((err = device_register(&ac97->dev)) < 0) { - snd_printk(KERN_ERR "Can't register ac97 bus\n"); + ac97_err(ac97, "Can't register ac97 bus\n"); ac97->dev.bus = NULL; return err; } @@ -2089,7 +2095,8 @@ int snd_ac97_mixer(struct snd_ac97_bus *bus, struct snd_ac97_template *template, msecs_to_jiffies(500), 1); } if (err < 0) { - snd_printk(KERN_WARNING "AC'97 %d does not respond - RESET\n", ac97->num); + ac97_warn(ac97, "AC'97 %d does not respond - RESET\n", + ac97->num); /* proceed anyway - it's often non-critical */ } } @@ -2098,7 +2105,9 @@ int snd_ac97_mixer(struct snd_ac97_bus *bus, struct snd_ac97_template *template, ac97->id |= snd_ac97_read(ac97, AC97_VENDOR_ID2); if (! (ac97->scaps & AC97_SCAP_DETECT_BY_VENDOR) && (ac97->id == 0x00000000 || ac97->id == 0xffffffff)) { - snd_printk(KERN_ERR "AC'97 %d access is not valid [0x%x], removing mixer.\n", ac97->num, ac97->id); + ac97_err(ac97, + "AC'97 %d access is not valid [0x%x], removing mixer.\n", + ac97->num, ac97->id); snd_ac97_free(ac97); return -EIO; } @@ -2131,7 +2140,9 @@ int snd_ac97_mixer(struct snd_ac97_bus *bus, struct snd_ac97_template *template, if (!ac97_is_audio(ac97) && !ac97_is_modem(ac97)) { if (!(ac97->scaps & (AC97_SCAP_SKIP_AUDIO|AC97_SCAP_SKIP_MODEM))) - snd_printk(KERN_ERR "AC'97 %d access error (not audio or modem codec)\n", ac97->num); + ac97_err(ac97, + "AC'97 %d access error (not audio or modem codec)\n", + ac97->num); snd_ac97_free(ac97); return -EACCES; } @@ -2156,7 +2167,8 @@ int snd_ac97_mixer(struct snd_ac97_bus *bus, struct snd_ac97_template *template, goto __ready_ok; schedule_timeout_uninterruptible(1); } while (time_after_eq(end_time, jiffies)); - snd_printk(KERN_WARNING "AC'97 %d analog subsections not ready\n", ac97->num); + ac97_warn(ac97, + "AC'97 %d analog subsections not ready\n", ac97->num); } /* FIXME: add powerdown control */ @@ -2188,7 +2200,10 @@ int snd_ac97_mixer(struct snd_ac97_bus *bus, struct snd_ac97_template *template, goto __ready_ok; schedule_timeout_uninterruptible(1); } while (time_after_eq(end_time, jiffies)); - snd_printk(KERN_WARNING "MC'97 %d converters and GPIO not ready (0x%x)\n", ac97->num, snd_ac97_read(ac97, AC97_EXTENDED_MSTATUS)); + ac97_warn(ac97, + "MC'97 %d converters and GPIO not ready (0x%x)\n", + ac97->num, + snd_ac97_read(ac97, AC97_EXTENDED_MSTATUS)); } __ready_ok: @@ -2723,7 +2738,7 @@ static int tune_ad_sharing(struct snd_ac97 *ac97) { unsigned short scfg; if ((ac97->id & 0xffffff00) != 0x41445300) { - snd_printk(KERN_ERR "ac97_quirk AD_SHARING is only for AD codecs\n"); + ac97_err(ac97, "ac97_quirk AD_SHARING is only for AD codecs\n"); return -EINVAL; } /* Turn on OMS bit to route microphone to back panel */ @@ -2739,7 +2754,8 @@ AC97_SINGLE("Jack Detect", AC97_ALC650_CLOCK, 5, 1, 0); static int tune_alc_jack(struct snd_ac97 *ac97) { if ((ac97->id & 0xffffff00) != 0x414c4700) { - snd_printk(KERN_ERR "ac97_quirk ALC_JACK is only for Realtek codecs\n"); + ac97_err(ac97, + "ac97_quirk ALC_JACK is only for Realtek codecs\n"); return -EINVAL; } snd_ac97_update_bits(ac97, 0x7a, 0x20, 0x20); /* select jack detect function */ @@ -2899,7 +2915,8 @@ int snd_ac97_tune_hardware(struct snd_ac97 *ac97, struct ac97_quirk *quirk, cons if (override && strcmp(override, "-1") && strcmp(override, "default")) { result = apply_quirk_str(ac97, override); if (result < 0) - snd_printk(KERN_ERR "applying quirk type %s failed (%d)\n", override, result); + ac97_err(ac97, "applying quirk type %s failed (%d)\n", + override, result); return result; } @@ -2913,10 +2930,14 @@ int snd_ac97_tune_hardware(struct snd_ac97 *ac97, struct ac97_quirk *quirk, cons quirk->subdevice == (quirk->mask & ac97->subsystem_device)) { if (quirk->codec_id && quirk->codec_id != ac97->id) continue; - snd_printdd("ac97 quirk for %s (%04x:%04x)\n", quirk->name, ac97->subsystem_vendor, ac97->subsystem_device); + ac97_dbg(ac97, "ac97 quirk for %s (%04x:%04x)\n", + quirk->name, ac97->subsystem_vendor, + ac97->subsystem_device); result = apply_quirk(ac97, quirk->type); if (result < 0) - snd_printk(KERN_ERR "applying quirk type %d for %s failed (%d)\n", quirk->type, quirk->name, result); + ac97_err(ac97, + "applying quirk type %d for %s failed (%d)\n", + quirk->type, quirk->name, result); return result; } } diff --git a/sound/pci/ac97/ac97_patch.c b/sound/pci/ac97/ac97_patch.c index 66a3bc95fb8..99176221541 100644 --- a/sound/pci/ac97/ac97_patch.c +++ b/sound/pci/ac97/ac97_patch.c @@ -3477,7 +3477,8 @@ static int snd_ac97_add_vmaster(struct snd_ac97 *ac97, char *name, sctl = snd_ac97_find_mixer_ctl(ac97, *s); if (!sctl) { - snd_printdd("Cannot find slave %s, skipped\n", *s); + dev_dbg(ac97->bus->card->dev, + "Cannot find slave %s, skipped\n", *s); continue; } err = snd_ctl_add_slave(kctl, sctl); diff --git a/sound/pci/ac97/ac97_pcm.c b/sound/pci/ac97/ac97_pcm.c index eab0fc9ff2e..d15297a6880 100644 --- a/sound/pci/ac97/ac97_pcm.c +++ b/sound/pci/ac97/ac97_pcm.c @@ -604,7 +604,9 @@ int snd_ac97_pcm_open(struct ac97_pcm *pcm, unsigned int rate, } if (!ok_flag) { spin_unlock_irq(&pcm->bus->bus_lock); - snd_printk(KERN_ERR "cannot find configuration for AC97 slot %i\n", i); + dev_err(bus->card->dev, + "cannot find configuration for AC97 slot %i\n", + i); err = -EAGAIN; goto error; } @@ -618,15 +620,20 @@ int snd_ac97_pcm_open(struct ac97_pcm *pcm, unsigned int rate, if (pcm->r[r].rslots[cidx] & (1 << i)) { reg = get_slot_reg(pcm, cidx, i, r); if (reg == 0xff) { - snd_printk(KERN_ERR "invalid AC97 slot %i?\n", i); + dev_err(bus->card->dev, + "invalid AC97 slot %i?\n", i); continue; } if (reg_ok[cidx] & (1 << (reg - AC97_PCM_FRONT_DAC_RATE))) continue; - //printk(KERN_DEBUG "setting ac97 reg 0x%x to rate %d\n", reg, rate); + dev_dbg(bus->card->dev, + "setting ac97 reg 0x%x to rate %d\n", + reg, rate); err = snd_ac97_set_rate(pcm->r[r].codec[cidx], reg, rate); if (err < 0) - snd_printk(KERN_ERR "error in snd_ac97_set_rate: cidx=%d, reg=0x%x, rate=%d, err=%d\n", cidx, reg, rate, err); + dev_err(bus->card->dev, + "error in snd_ac97_set_rate: cidx=%d, reg=0x%x, rate=%d, err=%d\n", + cidx, reg, rate, err); else reg_ok[cidx] |= (1 << (reg - AC97_PCM_FRONT_DAC_RATE)); } diff --git a/sound/pci/ad1889.c b/sound/pci/ad1889.c index b680d03e241..488f966adde 100644 --- a/sound/pci/ad1889.c +++ b/sound/pci/ad1889.c @@ -77,9 +77,6 @@ MODULE_PARM_DESC(ac97_quirk, "AC'97 workaround for strange hardware."); #define DEVNAME "ad1889" #define PFX DEVNAME ": " -/* let's use the global sound debug interfaces */ -#define ad1889_debug(fmt, arg...) snd_printd(KERN_DEBUG fmt, ## arg) - /* keep track of some hw registers */ struct ad1889_register_state { u16 reg; /* reg setup */ @@ -264,11 +261,11 @@ snd_ad1889_ac97_ready(struct snd_ad1889 *chip) && --retry) mdelay(1); if (!retry) { - snd_printk(KERN_ERR PFX "[%s] Link is not ready.\n", - __func__); + dev_err(chip->card->dev, "[%s] Link is not ready.\n", + __func__); return -EIO; } - ad1889_debug("[%s] ready after %d ms\n", __func__, 400 - retry); + dev_dbg(chip->card->dev, "[%s] ready after %d ms\n", __func__, 400 - retry); return 0; } @@ -405,9 +402,9 @@ snd_ad1889_playback_prepare(struct snd_pcm_substream *ss) spin_unlock_irq(&chip->lock); - ad1889_debug("prepare playback: addr = 0x%x, count = %u, " - "size = %u, reg = 0x%x, rate = %u\n", chip->wave.addr, - count, size, reg, rt->rate); + dev_dbg(chip->card->dev, + "prepare playback: addr = 0x%x, count = %u, size = %u, reg = 0x%x, rate = %u\n", + chip->wave.addr, count, size, reg, rt->rate); return 0; } @@ -452,9 +449,9 @@ snd_ad1889_capture_prepare(struct snd_pcm_substream *ss) spin_unlock_irq(&chip->lock); - ad1889_debug("prepare capture: addr = 0x%x, count = %u, " - "size = %u, reg = 0x%x, rate = %u\n", chip->ramc.addr, - count, size, reg, rt->rate); + dev_dbg(chip->card->dev, + "prepare capture: addr = 0x%x, count = %u, size = %u, reg = 0x%x, rate = %u\n", + chip->ramc.addr, count, size, reg, rt->rate); return 0; } @@ -614,7 +611,8 @@ snd_ad1889_interrupt(int irq, void *dev_id) return IRQ_NONE; if (st & (AD_DMA_DISR_PMAI|AD_DMA_DISR_PTAI)) - ad1889_debug("Unexpected master or target abort interrupt!\n"); + dev_dbg(chip->card->dev, + "Unexpected master or target abort interrupt!\n"); if ((st & AD_DMA_DISR_WAVI) && chip->psubs) snd_pcm_period_elapsed(chip->psubs); @@ -656,7 +654,7 @@ snd_ad1889_pcm_init(struct snd_ad1889 *chip, int device, struct snd_pcm **rpcm) BUFFER_BYTES_MAX); if (err < 0) { - snd_printk(KERN_ERR PFX "buffer allocation error: %d\n", err); + dev_err(chip->card->dev, "buffer allocation error: %d\n", err); return err; } @@ -912,7 +910,7 @@ snd_ad1889_create(struct snd_card *card, /* check PCI availability (32bit DMA) */ 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 PFX "error setting 32-bit DMA mask.\n"); + dev_err(card->dev, "error setting 32-bit DMA mask.\n"); pci_disable_device(pci); return -ENXIO; } @@ -935,7 +933,7 @@ snd_ad1889_create(struct snd_card *card, chip->bar = pci_resource_start(pci, 0); chip->iobase = pci_ioremap_bar(pci, 0); if (chip->iobase == NULL) { - printk(KERN_ERR PFX "unable to reserve region.\n"); + dev_err(card->dev, "unable to reserve region.\n"); err = -EBUSY; goto free_and_ret; } @@ -946,7 +944,7 @@ snd_ad1889_create(struct snd_card *card, if (request_irq(pci->irq, snd_ad1889_interrupt, IRQF_SHARED, KBUILD_MODNAME, chip)) { - printk(KERN_ERR PFX "cannot obtain IRQ %d\n", pci->irq); + dev_err(card->dev, "cannot obtain IRQ %d\n", pci->irq); snd_ad1889_free(chip); return -EBUSY; } @@ -965,8 +963,6 @@ snd_ad1889_create(struct snd_card *card, return err; } - snd_card_set_dev(card, &pci->dev); - *rchip = chip; return 0; @@ -996,7 +992,8 @@ snd_ad1889_probe(struct pci_dev *pci, } /* (2) */ - err = snd_card_create(index[devno], id[devno], THIS_MODULE, 0, &card); + err = snd_card_new(&pci->dev, index[devno], id[devno], THIS_MODULE, + 0, &card); /* XXX REVISIT: we can probably allocate chip in this call */ if (err < 0) return err; diff --git a/sound/pci/ali5451/ali5451.c b/sound/pci/ali5451/ali5451.c index c6835a3d64f..feb29c24cab 100644 --- a/sound/pci/ali5451/ali5451.c +++ b/sound/pci/ali5451/ali5451.c @@ -65,18 +65,6 @@ module_param(enable, bool, 0444); /* - * Debug part definitions - */ - -/* #define ALI_DEBUG */ - -#ifdef ALI_DEBUG -#define snd_ali_printk(format, args...) printk(KERN_DEBUG format, ##args); -#else -#define snd_ali_printk(format, args...) -#endif - -/* * Constants definition */ @@ -321,7 +309,7 @@ static int snd_ali_codec_ready(struct snd_ali *codec, } snd_ali_5451_poke(codec, port, res & ~0x8000); - snd_printdd("ali_codec_ready: codec is not ready.\n "); + dev_dbg(codec->card->dev, "ali_codec_ready: codec is not ready.\n "); return -EIO; } @@ -342,7 +330,7 @@ static int snd_ali_stimer_ready(struct snd_ali *codec) schedule_timeout_uninterruptible(1); } - snd_printk(KERN_ERR "ali_stimer_read: stimer is not ready.\n"); + dev_err(codec->card->dev, "ali_stimer_read: stimer is not ready.\n"); return -EIO; } @@ -354,7 +342,8 @@ static void snd_ali_codec_poke(struct snd_ali *codec,int secondary, unsigned int port; if (reg >= 0x80) { - snd_printk(KERN_ERR "ali_codec_poke: reg(%xh) invalid.\n", reg); + dev_err(codec->card->dev, + "ali_codec_poke: reg(%xh) invalid.\n", reg); return; } @@ -385,7 +374,8 @@ static unsigned short snd_ali_codec_peek(struct snd_ali *codec, unsigned int port; if (reg >= 0x80) { - snd_printk(KERN_ERR "ali_codec_peek: reg(%xh) invalid.\n", reg); + dev_err(codec->card->dev, + "ali_codec_peek: reg(%xh) invalid.\n", reg); return ~0; } @@ -417,7 +407,7 @@ static void snd_ali_codec_write(struct snd_ac97 *ac97, { struct snd_ali *codec = ac97->private_data; - snd_ali_printk("codec_write: reg=%xh data=%xh.\n", reg, val); + dev_dbg(codec->card->dev, "codec_write: reg=%xh data=%xh.\n", reg, val); if (reg == AC97_GPIO_STATUS) { outl((val << ALI_AC97_GPIO_DATA_SHIFT) | ALI_AC97_GPIO_ENABLE, ALI_REG(codec, ALI_AC97_GPIO)); @@ -433,7 +423,7 @@ static unsigned short snd_ali_codec_read(struct snd_ac97 *ac97, { struct snd_ali *codec = ac97->private_data; - snd_ali_printk("codec_read reg=%xh.\n", reg); + dev_dbg(codec->card->dev, "codec_read reg=%xh.\n", reg); return snd_ali_codec_peek(codec, ac97->num, reg); } @@ -474,7 +464,7 @@ static int snd_ali_reset_5451(struct snd_ali *codec) } /* non-fatal if you have a non PM capable codec */ - /* snd_printk(KERN_WARNING "ali5451: reset time out\n"); */ + /* dev_warn(codec->card->dev, "ali5451: reset time out\n"); */ return 0; } @@ -528,7 +518,7 @@ static void snd_ali_disable_voice_irq(struct snd_ali *codec, unsigned int mask; struct snd_ali_channel_control *pchregs = &(codec->chregs); - snd_ali_printk("disable_voice_irq channel=%d\n",channel); + dev_dbg(codec->card->dev, "disable_voice_irq channel=%d\n", channel); mask = 1 << (channel & 0x1f); pchregs->data.ainten = inl(ALI_REG(codec, pchregs->regs.ainten)); @@ -541,7 +531,7 @@ static int snd_ali_alloc_pcm_channel(struct snd_ali *codec, int channel) unsigned int idx = channel & 0x1f; if (codec->synth.chcnt >= ALI_CHANNELS){ - snd_printk(KERN_ERR + dev_err(codec->card->dev, "ali_alloc_pcm_channel: no free channels.\n"); return -1; } @@ -549,7 +539,7 @@ static int snd_ali_alloc_pcm_channel(struct snd_ali *codec, int channel) if (!(codec->synth.chmap & (1 << idx))) { codec->synth.chmap |= 1 << idx; codec->synth.chcnt++; - snd_ali_printk("alloc_pcm_channel no. %d.\n",idx); + dev_dbg(codec->card->dev, "alloc_pcm_channel no. %d.\n", idx); return idx; } return -1; @@ -560,7 +550,8 @@ static int snd_ali_find_free_channel(struct snd_ali * codec, int rec) int idx; int result = -1; - snd_ali_printk("find_free_channel: for %s\n",rec ? "rec" : "pcm"); + dev_dbg(codec->card->dev, + "find_free_channel: for %s\n", rec ? "rec" : "pcm"); /* recording */ if (rec) { @@ -575,8 +566,8 @@ static int snd_ali_find_free_channel(struct snd_ali * codec, int rec) if (result >= 0) return result; else { - snd_printk(KERN_ERR "ali_find_free_channel: " - "record channel is busy now.\n"); + dev_err(codec->card->dev, + "ali_find_free_channel: record channel is busy now.\n"); return -1; } } @@ -590,8 +581,8 @@ static int snd_ali_find_free_channel(struct snd_ali * codec, int rec) if (result >= 0) return result; else - snd_printk(KERN_ERR "ali_find_free_channel: " - "S/PDIF out channel is in busy now.\n"); + dev_err(codec->card->dev, + "ali_find_free_channel: S/PDIF out channel is in busy now.\n"); } for (idx = 0; idx < ALI_CHANNELS; idx++) { @@ -599,7 +590,7 @@ static int snd_ali_find_free_channel(struct snd_ali * codec, int rec) if (result >= 0) return result; } - snd_printk(KERN_ERR "ali_find_free_channel: no free channels.\n"); + dev_err(codec->card->dev, "ali_find_free_channel: no free channels.\n"); return -1; } @@ -607,14 +598,15 @@ static void snd_ali_free_channel_pcm(struct snd_ali *codec, int channel) { unsigned int idx = channel & 0x0000001f; - snd_ali_printk("free_channel_pcm channel=%d\n",channel); + dev_dbg(codec->card->dev, "free_channel_pcm channel=%d\n", channel); if (channel < 0 || channel >= ALI_CHANNELS) return; if (!(codec->synth.chmap & (1 << idx))) { - snd_printk(KERN_ERR "ali_free_channel_pcm: " - "channel %d is not in use.\n", channel); + dev_err(codec->card->dev, + "ali_free_channel_pcm: channel %d is not in use.\n", + channel); return; } else { codec->synth.chmap &= ~(1 << idx); @@ -626,7 +618,7 @@ static void snd_ali_stop_voice(struct snd_ali *codec, unsigned int channel) { unsigned int mask = 1 << (channel & 0x1f); - snd_ali_printk("stop_voice: channel=%d\n",channel); + dev_dbg(codec->card->dev, "stop_voice: channel=%d\n", channel); outl(mask, ALI_REG(codec, codec->chregs.regs.stop)); } @@ -667,7 +659,7 @@ static void snd_ali_detect_spdif_rate(struct snd_ali *codec) } if (count > 50000) { - snd_printk(KERN_ERR "ali_detect_spdif_rate: timeout!\n"); + dev_err(codec->card->dev, "ali_detect_spdif_rate: timeout!\n"); return; } @@ -682,7 +674,7 @@ static void snd_ali_detect_spdif_rate(struct snd_ali *codec) } if (count > 50000) { - snd_printk(KERN_ERR "ali_detect_spdif_rate: timeout!\n"); + dev_err(codec->card->dev, "ali_detect_spdif_rate: timeout!\n"); return; } @@ -857,9 +849,6 @@ static void snd_ali_update_ptr(struct snd_ali *codec, int channel) struct snd_ali_voice *pvoice; struct snd_ali_channel_control *pchregs; unsigned int old, mask; -#ifdef ALI_DEBUG - unsigned int temp, cspf; -#endif pchregs = &(codec->chregs); @@ -877,14 +866,11 @@ static void snd_ali_update_ptr(struct snd_ali *codec, int channel) if (pvoice->pcm && pvoice->substream) { /* pcm interrupt */ -#ifdef ALI_DEBUG - outb((u8)(pvoice->number), ALI_REG(codec, ALI_GC_CIR)); - temp = inw(ALI_REG(codec, ALI_CSO_ALPHA_FMS + 2)); - cspf = (inl(ALI_REG(codec, ALI_CSPF)) & mask) == mask; -#endif if (pvoice->running) { - snd_ali_printk("update_ptr: cso=%4.4x cspf=%d.\n", - (u16)temp, cspf); + dev_dbg(codec->card->dev, + "update_ptr: cso=%4.4x cspf=%d.\n", + inw(ALI_REG(codec, ALI_CSO_ALPHA_FMS + 2)), + (inl(ALI_REG(codec, ALI_CSPF)) & mask) == mask); spin_unlock(&codec->reg_lock); snd_pcm_period_elapsed(pvoice->substream); spin_lock(&codec->reg_lock); @@ -940,14 +926,14 @@ static struct snd_ali_voice *snd_ali_alloc_voice(struct snd_ali * codec, struct snd_ali_voice *pvoice; int idx; - snd_ali_printk("alloc_voice: type=%d rec=%d\n", type, rec); + dev_dbg(codec->card->dev, "alloc_voice: type=%d rec=%d\n", type, rec); spin_lock_irq(&codec->voice_alloc); if (type == SNDRV_ALI_VOICE_TYPE_PCM) { idx = channel > 0 ? snd_ali_alloc_pcm_channel(codec, channel) : snd_ali_find_free_channel(codec,rec); if (idx < 0) { - snd_printk(KERN_ERR "ali_alloc_voice: err.\n"); + dev_err(codec->card->dev, "ali_alloc_voice: err.\n"); spin_unlock_irq(&codec->voice_alloc); return NULL; } @@ -970,7 +956,7 @@ static void snd_ali_free_voice(struct snd_ali * codec, void (*private_free)(void *); void *private_data; - snd_ali_printk("free_voice: channel=%d\n",pvoice->number); + dev_dbg(codec->card->dev, "free_voice: channel=%d\n", pvoice->number); if (!pvoice->use) return; snd_ali_clear_voices(codec, pvoice->number, pvoice->number); @@ -1153,7 +1139,7 @@ static int snd_ali_trigger(struct snd_pcm_substream *substream, outl(val, ALI_REG(codec, ALI_AINTEN)); if (do_start) outl(what, ALI_REG(codec, ALI_START)); - snd_ali_printk("trigger: what=%xh whati=%xh\n", what, whati); + dev_dbg(codec->card->dev, "trigger: what=%xh whati=%xh\n", what, whati); spin_unlock(&codec->reg_lock); return 0; @@ -1239,7 +1225,7 @@ static int snd_ali_playback_prepare(struct snd_pcm_substream *substream) unsigned int VOL; unsigned int EC; - snd_ali_printk("playback_prepare ...\n"); + dev_dbg(codec->card->dev, "playback_prepare ...\n"); spin_lock_irq(&codec->reg_lock); @@ -1266,7 +1252,7 @@ static int snd_ali_playback_prepare(struct snd_pcm_substream *substream) /* set target ESO for channel */ pvoice->eso = runtime->buffer_size; - snd_ali_printk("playback_prepare: eso=%xh count=%xh\n", + dev_dbg(codec->card->dev, "playback_prepare: eso=%xh count=%xh\n", pvoice->eso, pvoice->count); /* set ESO to capture first MIDLP interrupt */ @@ -1278,8 +1264,9 @@ static int snd_ali_playback_prepare(struct snd_pcm_substream *substream) PAN = 0; VOL = 0; EC = 0; - snd_ali_printk("playback_prepare:\n"); - snd_ali_printk("ch=%d, Rate=%d Delta=%xh,GVSEL=%xh,PAN=%xh,CTRL=%xh\n", + dev_dbg(codec->card->dev, "playback_prepare:\n"); + dev_dbg(codec->card->dev, + "ch=%d, Rate=%d Delta=%xh,GVSEL=%xh,PAN=%xh,CTRL=%xh\n", pvoice->number,runtime->rate,Delta,GVSEL,PAN,CTRL); snd_ali_write_voice_regs(codec, pvoice->number, @@ -1332,7 +1319,7 @@ static int snd_ali_prepare(struct snd_pcm_substream *substream) spin_lock_irq(&codec->reg_lock); - snd_ali_printk("ali_prepare...\n"); + dev_dbg(codec->card->dev, "ali_prepare...\n"); snd_ali_enable_special_channel(codec,pvoice->number); @@ -1351,15 +1338,16 @@ static int snd_ali_prepare(struct snd_pcm_substream *substream) rate = snd_ali_get_spdif_in_rate(codec); if (rate == 0) { - snd_printk(KERN_WARNING "ali_capture_preapre: " - "spdif rate detect err!\n"); + dev_warn(codec->card->dev, + "ali_capture_preapre: spdif rate detect err!\n"); rate = 48000; } spin_lock_irq(&codec->reg_lock); bValue = inb(ALI_REG(codec,ALI_SPDIF_CTRL)); if (bValue & 0x10) { outb(bValue,ALI_REG(codec,ALI_SPDIF_CTRL)); - printk(KERN_WARNING "clear SPDIF parity error flag.\n"); + dev_warn(codec->card->dev, + "clear SPDIF parity error flag.\n"); } if (rate != 48000) @@ -1418,7 +1406,7 @@ snd_ali_playback_pointer(struct snd_pcm_substream *substream) outb(pvoice->number, ALI_REG(codec, ALI_GC_CIR)); cso = inw(ALI_REG(codec, ALI_CSO_ALPHA_FMS + 2)); spin_unlock(&codec->reg_lock); - snd_ali_printk("playback pointer returned cso=%xh.\n", cso); + dev_dbg(codec->card->dev, "playback pointer returned cso=%xh.\n", cso); return cso; } @@ -1685,7 +1673,8 @@ static int snd_ali_pcm(struct snd_ali *codec, int device, err = snd_pcm_new(codec->card, desc->name, device, desc->playback_num, desc->capture_num, &pcm); if (err < 0) { - snd_printk(KERN_ERR "snd_ali_pcm: err called snd_pcm_new.\n"); + dev_err(codec->card->dev, + "snd_ali_pcm: err called snd_pcm_new.\n"); return err; } pcm->private_data = codec; @@ -1861,7 +1850,7 @@ static int snd_ali_mixer(struct snd_ali *codec) ac97.num = i; err = snd_ac97_mixer(codec->ac97_bus, &ac97, &codec->ac97[i]); if (err < 0) { - snd_printk(KERN_ERR + dev_err(codec->card->dev, "ali mixer %d creating error.\n", i); if (i == 0) return err; @@ -1947,8 +1936,7 @@ static int ali_resume(struct device *dev) pci_set_power_state(pci, PCI_D0); pci_restore_state(pci); if (pci_enable_device(pci) < 0) { - printk(KERN_ERR "ali5451: pci_enable_device failed, " - "disabling device\n"); + dev_err(dev, "pci_enable_device failed, disabling device\n"); snd_card_disconnect(card); return -EIO; } @@ -2013,10 +2001,10 @@ static int snd_ali_chip_init(struct snd_ali *codec) unsigned char temp; struct pci_dev *pci_dev; - snd_ali_printk("chip initializing ... \n"); + dev_dbg(codec->card->dev, "chip initializing ...\n"); if (snd_ali_reset_5451(codec)) { - snd_printk(KERN_ERR "ali_chip_init: reset 5451 error.\n"); + dev_err(codec->card->dev, "ali_chip_init: reset 5451 error.\n"); return -1; } @@ -2062,7 +2050,7 @@ static int snd_ali_chip_init(struct snd_ali *codec) ALI_REG(codec, ALI_SCTRL)); } - snd_ali_printk("chip initialize succeed.\n"); + dev_dbg(codec->card->dev, "chip initialize succeed.\n"); return 0; } @@ -2088,7 +2076,7 @@ static int snd_ali_resources(struct snd_ali *codec) { int err; - snd_ali_printk("resources allocation ...\n"); + dev_dbg(codec->card->dev, "resources allocation ...\n"); err = pci_request_regions(codec->pci, "ALI 5451"); if (err < 0) return err; @@ -2096,11 +2084,11 @@ static int snd_ali_resources(struct snd_ali *codec) if (request_irq(codec->pci->irq, snd_ali_card_interrupt, IRQF_SHARED, KBUILD_MODNAME, codec)) { - snd_printk(KERN_ERR "Unable to request irq.\n"); + dev_err(codec->card->dev, "Unable to request irq.\n"); return -EBUSY; } codec->irq = codec->pci->irq; - snd_ali_printk("resources allocated.\n"); + dev_dbg(codec->card->dev, "resources allocated.\n"); return 0; } static int snd_ali_dev_free(struct snd_device *device) @@ -2125,7 +2113,7 @@ static int snd_ali_create(struct snd_card *card, *r_ali = NULL; - snd_ali_printk("creating ...\n"); + dev_dbg(card->dev, "creating ...\n"); /* enable PCI device */ err = pci_enable_device(pci); @@ -2134,8 +2122,8 @@ static int snd_ali_create(struct snd_card *card, /* check, if we can restrict PCI DMA transfers to 31 bits */ if (pci_set_dma_mask(pci, DMA_BIT_MASK(31)) < 0 || pci_set_consistent_dma_mask(pci, DMA_BIT_MASK(31)) < 0) { - snd_printk(KERN_ERR "architecture does not support " - "31bit PCI busmaster DMA\n"); + dev_err(card->dev, + "architecture does not support 31bit PCI busmaster DMA\n"); pci_disable_device(pci); return -ENXIO; } @@ -2199,48 +2187,46 @@ static int snd_ali_create(struct snd_card *card, /* M1533: southbridge */ codec->pci_m1533 = pci_get_device(0x10b9, 0x1533, NULL); if (!codec->pci_m1533) { - snd_printk(KERN_ERR "ali5451: cannot find ALi 1533 chip.\n"); + dev_err(card->dev, "cannot find ALi 1533 chip.\n"); snd_ali_free(codec); return -ENODEV; } /* M7101: power management */ codec->pci_m7101 = pci_get_device(0x10b9, 0x7101, NULL); if (!codec->pci_m7101 && codec->revision == ALI_5451_V02) { - snd_printk(KERN_ERR "ali5451: cannot find ALi 7101 chip.\n"); + dev_err(card->dev, "cannot find ALi 7101 chip.\n"); snd_ali_free(codec); return -ENODEV; } - snd_ali_printk("snd_device_new is called.\n"); + dev_dbg(card->dev, "snd_device_new is called.\n"); err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, codec, &ops); if (err < 0) { snd_ali_free(codec); return err; } - snd_card_set_dev(card, &pci->dev); - /* initialise synth voices*/ for (i = 0; i < ALI_CHANNELS; i++) codec->synth.voices[i].number = i; err = snd_ali_chip_init(codec); if (err < 0) { - snd_printk(KERN_ERR "ali create: chip init error.\n"); + dev_err(card->dev, "ali create: chip init error.\n"); return err; } #ifdef CONFIG_PM_SLEEP codec->image = kmalloc(sizeof(*codec->image), GFP_KERNEL); if (!codec->image) - snd_printk(KERN_WARNING "can't allocate apm buffer\n"); + dev_warn(card->dev, "can't allocate apm buffer\n"); #endif snd_ali_enable_address_interrupt(codec); codec->hw_initialized = 1; *r_ali = codec; - snd_ali_printk("created.\n"); + dev_dbg(card->dev, "created.\n"); return 0; } @@ -2251,9 +2237,9 @@ static int snd_ali_probe(struct pci_dev *pci, struct snd_ali *codec; int err; - snd_ali_printk("probe ...\n"); + dev_dbg(&pci->dev, "probe ...\n"); - err = snd_card_create(index, id, THIS_MODULE, 0, &card); + err = snd_card_new(&pci->dev, index, id, THIS_MODULE, 0, &card); if (err < 0) return err; @@ -2262,12 +2248,12 @@ static int snd_ali_probe(struct pci_dev *pci, goto error; card->private_data = codec; - snd_ali_printk("mixer building ...\n"); + dev_dbg(&pci->dev, "mixer building ...\n"); err = snd_ali_mixer(codec); if (err < 0) goto error; - snd_ali_printk("pcm building ...\n"); + dev_dbg(&pci->dev, "pcm building ...\n"); err = snd_ali_build_pcms(codec); if (err < 0) goto error; @@ -2280,7 +2266,7 @@ static int snd_ali_probe(struct pci_dev *pci, sprintf(card->longname, "%s at 0x%lx, irq %i", card->shortname, codec->port, codec->irq); - snd_ali_printk("register card.\n"); + dev_dbg(&pci->dev, "register card.\n"); err = snd_card_register(card); if (err < 0) goto error; diff --git a/sound/pci/als300.c b/sound/pci/als300.c index 591efb6eef0..cc9a15a1304 100644 --- a/sound/pci/als300.c +++ b/sound/pci/als300.c @@ -87,19 +87,8 @@ #define PLAYBACK_BLOCK_COUNTER 0x9A #define RECORD_BLOCK_COUNTER 0x9B -#define DEBUG_CALLS 0 #define DEBUG_PLAY_REC 0 -#if DEBUG_CALLS -#define snd_als300_dbgcalls(format, args...) printk(KERN_DEBUG format, ##args) -#define snd_als300_dbgcallenter() printk(KERN_ERR "--> %s\n", __func__) -#define snd_als300_dbgcallleave() printk(KERN_ERR "<-- %s\n", __func__) -#else -#define snd_als300_dbgcalls(format, args...) -#define snd_als300_dbgcallenter() -#define snd_als300_dbgcallleave() -#endif - #if DEBUG_PLAY_REC #define snd_als300_dbgplay(format, args...) printk(KERN_ERR format, ##args) #else @@ -177,7 +166,6 @@ static inline void snd_als300_gcr_write(unsigned long port, static void snd_als300_set_irq_flag(struct snd_als300 *chip, int cmd) { u32 tmp = snd_als300_gcr_read(chip->port, MISC_CONTROL); - snd_als300_dbgcallenter(); /* boolean XOR check, since old vs. new hardware have directly reversed bit setting for ENABLE and DISABLE. @@ -188,19 +176,16 @@ static void snd_als300_set_irq_flag(struct snd_als300 *chip, int cmd) else tmp &= ~IRQ_SET_BIT; snd_als300_gcr_write(chip->port, MISC_CONTROL, tmp); - snd_als300_dbgcallleave(); } static int snd_als300_free(struct snd_als300 *chip) { - snd_als300_dbgcallenter(); snd_als300_set_irq_flag(chip, IRQ_DISABLE); if (chip->irq >= 0) free_irq(chip->irq, chip); pci_release_regions(chip->pci); pci_disable_device(chip->pci); kfree(chip); - snd_als300_dbgcallleave(); return 0; } @@ -280,9 +265,7 @@ static irqreturn_t snd_als300plus_interrupt(int irq, void *dev_id) static void snd_als300_remove(struct pci_dev *pci) { - snd_als300_dbgcallenter(); snd_card_free(pci_get_drvdata(pci)); - snd_als300_dbgcallleave(); } static unsigned short snd_als300_ac97_read(struct snd_ac97 *ac97, @@ -330,14 +313,12 @@ static int snd_als300_ac97(struct snd_als300 *chip) .read = snd_als300_ac97_read, }; - snd_als300_dbgcallenter(); if ((err = snd_ac97_bus(chip->card, 0, &ops, NULL, &bus)) < 0) return err; memset(&ac97, 0, sizeof(ac97)); ac97.private_data = chip; - snd_als300_dbgcallleave(); return snd_ac97_mixer(bus, &ac97, &chip->ac97); } @@ -395,13 +376,11 @@ static int snd_als300_playback_open(struct snd_pcm_substream *substream) if (!data) return -ENOMEM; - snd_als300_dbgcallenter(); chip->playback_substream = substream; runtime->hw = snd_als300_playback_hw; runtime->private_data = data; data->control_register = PLAYBACK_CONTROL; data->block_counter_register = PLAYBACK_BLOCK_COUNTER; - snd_als300_dbgcallleave(); return 0; } @@ -411,11 +390,9 @@ static int snd_als300_playback_close(struct snd_pcm_substream *substream) struct snd_als300_substream_data *data; data = substream->runtime->private_data; - snd_als300_dbgcallenter(); kfree(data); chip->playback_substream = NULL; snd_pcm_lib_free_pages(substream); - snd_als300_dbgcallleave(); return 0; } @@ -428,13 +405,11 @@ static int snd_als300_capture_open(struct snd_pcm_substream *substream) if (!data) return -ENOMEM; - snd_als300_dbgcallenter(); chip->capture_substream = substream; runtime->hw = snd_als300_capture_hw; runtime->private_data = data; data->control_register = RECORD_CONTROL; data->block_counter_register = RECORD_BLOCK_COUNTER; - snd_als300_dbgcallleave(); return 0; } @@ -444,11 +419,9 @@ static int snd_als300_capture_close(struct snd_pcm_substream *substream) struct snd_als300_substream_data *data; data = substream->runtime->private_data; - snd_als300_dbgcallenter(); kfree(data); chip->capture_substream = NULL; snd_pcm_lib_free_pages(substream); - snd_als300_dbgcallleave(); return 0; } @@ -472,7 +445,6 @@ static int snd_als300_playback_prepare(struct snd_pcm_substream *substream) unsigned short period_bytes = snd_pcm_lib_period_bytes(substream); unsigned short buffer_bytes = snd_pcm_lib_buffer_bytes(substream); - snd_als300_dbgcallenter(); spin_lock_irq(&chip->reg_lock); tmp = snd_als300_gcr_read(chip->port, PLAYBACK_CONTROL); tmp &= ~TRANSFER_START; @@ -491,7 +463,6 @@ static int snd_als300_playback_prepare(struct snd_pcm_substream *substream) snd_als300_gcr_write(chip->port, PLAYBACK_END, runtime->dma_addr + buffer_bytes - 1); spin_unlock_irq(&chip->reg_lock); - snd_als300_dbgcallleave(); return 0; } @@ -503,7 +474,6 @@ static int snd_als300_capture_prepare(struct snd_pcm_substream *substream) unsigned short period_bytes = snd_pcm_lib_period_bytes(substream); unsigned short buffer_bytes = snd_pcm_lib_buffer_bytes(substream); - snd_als300_dbgcallenter(); spin_lock_irq(&chip->reg_lock); tmp = snd_als300_gcr_read(chip->port, RECORD_CONTROL); tmp &= ~TRANSFER_START; @@ -522,7 +492,6 @@ static int snd_als300_capture_prepare(struct snd_pcm_substream *substream) snd_als300_gcr_write(chip->port, RECORD_END, runtime->dma_addr + buffer_bytes - 1); spin_unlock_irq(&chip->reg_lock); - snd_als300_dbgcallleave(); return 0; } @@ -537,7 +506,6 @@ static int snd_als300_trigger(struct snd_pcm_substream *substream, int cmd) data = substream->runtime->private_data; reg = data->control_register; - snd_als300_dbgcallenter(); spin_lock(&chip->reg_lock); switch (cmd) { case SNDRV_PCM_TRIGGER_START: @@ -568,7 +536,6 @@ static int snd_als300_trigger(struct snd_pcm_substream *substream, int cmd) ret = -EINVAL; } spin_unlock(&chip->reg_lock); - snd_als300_dbgcallleave(); return ret; } @@ -582,7 +549,6 @@ static snd_pcm_uframes_t snd_als300_pointer(struct snd_pcm_substream *substream) data = substream->runtime->private_data; period_bytes = snd_pcm_lib_period_bytes(substream); - snd_als300_dbgcallenter(); spin_lock(&chip->reg_lock); current_ptr = (u16) snd_als300_gcr_read(chip->port, data->block_counter_register) + 4; @@ -595,7 +561,6 @@ static snd_pcm_uframes_t snd_als300_pointer(struct snd_pcm_substream *substream) if (data->period_flipflop == 0) current_ptr += period_bytes; snd_als300_dbgplay("Pointer (bytes): %d\n", current_ptr); - snd_als300_dbgcallleave(); return bytes_to_frames(substream->runtime, current_ptr); } @@ -626,7 +591,6 @@ static int snd_als300_new_pcm(struct snd_als300 *chip) struct snd_pcm *pcm; int err; - snd_als300_dbgcallenter(); err = snd_pcm_new(chip->card, "ALS300", 0, 1, 1, &pcm); if (err < 0) return err; @@ -643,7 +607,6 @@ static int snd_als300_new_pcm(struct snd_als300 *chip) /* pre-allocation of buffers */ snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(chip->pci), 64*1024, 64*1024); - snd_als300_dbgcallleave(); return 0; } @@ -652,7 +615,6 @@ static void snd_als300_init(struct snd_als300 *chip) unsigned long flags; u32 tmp; - snd_als300_dbgcallenter(); spin_lock_irqsave(&chip->reg_lock, flags); chip->revision = (snd_als300_gcr_read(chip->port, MISC_CONTROL) >> 16) & 0x0000000F; @@ -679,7 +641,6 @@ static void snd_als300_init(struct snd_als300 *chip) snd_als300_gcr_write(chip->port, PLAYBACK_CONTROL, tmp & ~TRANSFER_START); spin_unlock_irqrestore(&chip->reg_lock, flags); - snd_als300_dbgcallleave(); } static int snd_als300_create(struct snd_card *card, @@ -695,13 +656,12 @@ static int snd_als300_create(struct snd_card *card, }; *rchip = NULL; - snd_als300_dbgcallenter(); if ((err = pci_enable_device(pci)) < 0) return err; if (pci_set_dma_mask(pci, DMA_BIT_MASK(28)) < 0 || pci_set_consistent_dma_mask(pci, DMA_BIT_MASK(28)) < 0) { - printk(KERN_ERR "error setting 28bit DMA mask\n"); + dev_err(card->dev, "error setting 28bit DMA mask\n"); pci_disable_device(pci); return -ENXIO; } @@ -733,7 +693,7 @@ static int snd_als300_create(struct snd_card *card, if (request_irq(pci->irq, irq_handler, IRQF_SHARED, KBUILD_MODNAME, chip)) { - snd_printk(KERN_ERR "unable to grab IRQ %d\n", pci->irq); + dev_err(card->dev, "unable to grab IRQ %d\n", pci->irq); snd_als300_free(chip); return -EBUSY; } @@ -744,13 +704,13 @@ static int snd_als300_create(struct snd_card *card, err = snd_als300_ac97(chip); if (err < 0) { - snd_printk(KERN_WARNING "Could not create ac97\n"); + dev_err(card->dev, "Could not create ac97\n"); snd_als300_free(chip); return err; } if ((err = snd_als300_new_pcm(chip)) < 0) { - snd_printk(KERN_WARNING "Could not create PCM\n"); + dev_err(card->dev, "Could not create PCM\n"); snd_als300_free(chip); return err; } @@ -761,10 +721,7 @@ static int snd_als300_create(struct snd_card *card, return err; } - snd_card_set_dev(card, &pci->dev); - *rchip = chip; - snd_als300_dbgcallleave(); return 0; } @@ -794,8 +751,7 @@ static int snd_als300_resume(struct device *dev) pci_set_power_state(pci, PCI_D0); pci_restore_state(pci); if (pci_enable_device(pci) < 0) { - printk(KERN_ERR "als300: pci_enable_device failed, " - "disabling device\n"); + dev_err(dev, "pci_enable_device failed, disabling device\n"); snd_card_disconnect(card); return -EIO; } @@ -829,7 +785,8 @@ static int snd_als300_probe(struct pci_dev *pci, return -ENOENT; } - err = snd_card_create(index[dev], id[dev], THIS_MODULE, 0, &card); + err = snd_card_new(&pci->dev, index[dev], id[dev], THIS_MODULE, + 0, &card); if (err < 0) return err; diff --git a/sound/pci/als4000.c b/sound/pci/als4000.c index ffc821b0139..b751c381d25 100644 --- a/sound/pci/als4000.c +++ b/sound/pci/als4000.c @@ -578,7 +578,7 @@ static irqreturn_t snd_als4000_interrupt(int irq, void *dev_id) snd_als4k_iobase_readb(chip->alt_port, ALS4K_IOB_16_ACK_FOR_CR1E); - /* printk(KERN_INFO "als4000: irq 0x%04x 0x%04x\n", + /* dev_dbg(chip->card->dev, "als4000: irq 0x%04x 0x%04x\n", pci_irqstatus, sb_irqstatus); */ /* only ack the things we actually handled above */ @@ -791,13 +791,13 @@ static int snd_als4000_create_gameport(struct snd_card_als4000 *acard, int dev) } if (!r) { - printk(KERN_WARNING "als4000: cannot reserve joystick ports\n"); + dev_warn(&acard->pci->dev, "cannot reserve joystick ports\n"); return -EBUSY; } acard->gameport = gp = gameport_allocate_port(); if (!gp) { - printk(KERN_ERR "als4000: cannot allocate memory for gameport\n"); + dev_err(&acard->pci->dev, "cannot allocate memory for gameport\n"); release_and_free_resource(r); return -ENOMEM; } @@ -873,7 +873,7 @@ static int snd_card_als4000_probe(struct pci_dev *pci, /* check, if we can restrict PCI DMA transfers to 24 bits */ if (pci_set_dma_mask(pci, DMA_BIT_MASK(24)) < 0 || pci_set_consistent_dma_mask(pci, DMA_BIT_MASK(24)) < 0) { - snd_printk(KERN_ERR "architecture does not support 24bit PCI busmaster DMA\n"); + dev_err(&pci->dev, "architecture does not support 24bit PCI busmaster DMA\n"); pci_disable_device(pci); return -ENXIO; } @@ -888,9 +888,9 @@ static int snd_card_als4000_probe(struct pci_dev *pci, pci_write_config_word(pci, PCI_COMMAND, word | PCI_COMMAND_IO); pci_set_master(pci); - err = snd_card_create(index[dev], id[dev], THIS_MODULE, - sizeof(*acard) /* private_data: acard */, - &card); + err = snd_card_new(&pci->dev, index[dev], id[dev], THIS_MODULE, + sizeof(*acard) /* private_data: acard */, + &card); if (err < 0) { pci_release_regions(pci); pci_disable_device(pci); @@ -920,7 +920,6 @@ static int snd_card_als4000_probe(struct pci_dev *pci, chip->pci = pci; chip->alt_port = iobase; - snd_card_set_dev(card, &pci->dev); snd_als4000_configure(chip); @@ -934,7 +933,7 @@ static int snd_card_als4000_probe(struct pci_dev *pci, MPU401_INFO_INTEGRATED | MPU401_INFO_IRQ_HOOK, -1, &chip->rmidi)) < 0) { - printk(KERN_ERR "als4000: no MPU-401 device at 0x%lx?\n", + dev_err(&pci->dev, "no MPU-401 device at 0x%lx?\n", iobase + ALS4K_IOB_30_MIDI_DATA); goto out_err; } @@ -955,7 +954,7 @@ static int snd_card_als4000_probe(struct pci_dev *pci, iobase + ALS4K_IOB_10_ADLIB_ADDR0, iobase + ALS4K_IOB_12_ADLIB_ADDR2, OPL3_HW_AUTO, 1, &opl3) < 0) { - printk(KERN_ERR "als4000: no OPL device at 0x%lx-0x%lx?\n", + dev_err(&pci->dev, "no OPL device at 0x%lx-0x%lx?\n", iobase + ALS4K_IOB_10_ADLIB_ADDR0, iobase + ALS4K_IOB_12_ADLIB_ADDR2); } else { @@ -1015,8 +1014,7 @@ static int snd_als4000_resume(struct device *dev) pci_set_power_state(pci, PCI_D0); pci_restore_state(pci); if (pci_enable_device(pci) < 0) { - printk(KERN_ERR "als4000: pci_enable_device failed, " - "disabling device\n"); + dev_err(dev, "pci_enable_device failed, disabling device\n"); snd_card_disconnect(card); return -EIO; } diff --git a/sound/pci/asihpi/asihpi.c b/sound/pci/asihpi/asihpi.c index 5f2acd35dcb..901c9490398 100644 --- a/sound/pci/asihpi/asihpi.c +++ b/sound/pci/asihpi/asihpi.c @@ -1253,11 +1253,12 @@ static int snd_card_asihpi_pcm_new(struct snd_card_asihpi *asihpi, int device) num_outstreams, num_instreams, &pcm); if (err < 0) return err; + /* pointer to ops struct is stored, dont change ops afterwards! */ - snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, - &snd_card_asihpi_playback_mmap_ops); - snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, - &snd_card_asihpi_capture_mmap_ops); + snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, + &snd_card_asihpi_playback_mmap_ops); + snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, + &snd_card_asihpi_capture_mmap_ops); pcm->private_data = asihpi; pcm->info_flags = 0; @@ -2827,17 +2828,13 @@ static int snd_asihpi_probe(struct pci_dev *pci_dev, hpi = pci_get_drvdata(pci_dev); adapter_index = hpi->adapter->index; /* first try to give the card the same index as its hardware index */ - err = snd_card_create(adapter_index, - id[adapter_index], THIS_MODULE, - sizeof(struct snd_card_asihpi), - &card); + err = snd_card_new(&pci_dev->dev, adapter_index, id[adapter_index], + THIS_MODULE, sizeof(struct snd_card_asihpi), &card); if (err < 0) { /* if that fails, try the default index==next available */ - err = - snd_card_create(index[dev], id[dev], - THIS_MODULE, - sizeof(struct snd_card_asihpi), - &card); + err = snd_card_new(&pci_dev->dev, index[dev], id[dev], + THIS_MODULE, sizeof(struct snd_card_asihpi), + &card); if (err < 0) return err; snd_printk(KERN_WARNING @@ -2845,8 +2842,6 @@ static int snd_asihpi_probe(struct pci_dev *pci_dev, adapter_index, card->number); } - snd_card_set_dev(card, &pci_dev->dev); - asihpi = card->private_data; asihpi->card = card; asihpi->pci = pci_dev; diff --git a/sound/pci/atiixp.c b/sound/pci/atiixp.c index f6dec3ea371..ae07b4926dc 100644 --- a/sound/pci/atiixp.c +++ b/sound/pci/atiixp.c @@ -432,7 +432,7 @@ static int snd_atiixp_acquire_codec(struct atiixp *chip) while (atiixp_read(chip, PHYS_OUT_ADDR) & ATI_REG_PHYS_OUT_ADDR_EN) { if (! timeout--) { - snd_printk(KERN_WARNING "atiixp: codec acquire timeout\n"); + dev_warn(chip->card->dev, "codec acquire timeout\n"); return -EBUSY; } udelay(1); @@ -463,7 +463,7 @@ static unsigned short snd_atiixp_codec_read(struct atiixp *chip, unsigned short } while (--timeout); /* time out may happen during reset */ if (reg < 0x7c) - snd_printk(KERN_WARNING "atiixp: codec read timeout (reg %x)\n", reg); + dev_warn(chip->card->dev, "codec read timeout (reg %x)\n", reg); return 0xffff; } @@ -523,7 +523,7 @@ static int snd_atiixp_aclink_reset(struct atiixp *chip) mdelay(1); atiixp_update(chip, CMD, ATI_REG_CMD_AC_RESET, ATI_REG_CMD_AC_RESET); if (!--timeout) { - snd_printk(KERN_ERR "atiixp: codec reset timeout\n"); + dev_err(chip->card->dev, "codec reset timeout\n"); break; } } @@ -567,9 +567,8 @@ static int ac97_probing_bugs(struct pci_dev *pci) q = snd_pci_quirk_lookup(pci, atiixp_quirks); if (q) { - snd_printdd(KERN_INFO - "Atiixp quirk for %s. Forcing codec %d\n", - snd_pci_quirk_name(q), q->value); + dev_dbg(&pci->dev, "atiixp quirk for %s. Forcing codec %d\n", + snd_pci_quirk_name(q), q->value); return q->value; } /* this hardware doesn't need workarounds. Probe for codec */ @@ -600,7 +599,7 @@ static int snd_atiixp_codec_detect(struct atiixp *chip) atiixp_write(chip, IER, 0); /* disable irqs */ if ((chip->codec_not_ready_bits & ALL_CODEC_NOT_READY) == ALL_CODEC_NOT_READY) { - snd_printk(KERN_ERR "atiixp: no codec detected!\n"); + dev_err(chip->card->dev, "no codec detected!\n"); return -ENXIO; } return 0; @@ -676,7 +675,7 @@ static snd_pcm_uframes_t snd_atiixp_pcm_pointer(struct snd_pcm_substream *substr continue; return bytes_to_frames(runtime, curptr); } - snd_printd("atiixp: invalid DMA pointer read 0x%x (buf=%x)\n", + dev_dbg(chip->card->dev, "invalid DMA pointer read 0x%x (buf=%x)\n", readl(chip->remap_addr + dma->ops->dt_cur), dma->buf_addr); return 0; } @@ -688,7 +687,7 @@ static void snd_atiixp_xrun_dma(struct atiixp *chip, struct atiixp_dma *dma) { if (! dma->substream || ! dma->running) return; - snd_printdd("atiixp: XRUN detected (DMA %d)\n", dma->ops->type); + dev_dbg(chip->card->dev, "XRUN detected (DMA %d)\n", dma->ops->type); snd_pcm_stream_lock(dma->substream); snd_pcm_stop(dma->substream, SNDRV_PCM_STATE_XRUN); snd_pcm_stream_unlock(dma->substream); @@ -1453,14 +1452,15 @@ static int snd_atiixp_mixer_new(struct atiixp *chip, int clock, ac97.scaps |= AC97_SCAP_NO_SPDIF; if ((err = snd_ac97_mixer(pbus, &ac97, &chip->ac97[i])) < 0) { chip->ac97[i] = NULL; /* to be sure */ - snd_printdd("atiixp: codec %d not available for audio\n", i); + dev_dbg(chip->card->dev, + "codec %d not available for audio\n", i); continue; } codec_count++; } if (! codec_count) { - snd_printk(KERN_ERR "atiixp: no codec available\n"); + dev_err(chip->card->dev, "no codec available\n"); return -ENODEV; } @@ -1511,8 +1511,7 @@ static int snd_atiixp_resume(struct device *dev) pci_set_power_state(pci, PCI_D0); pci_restore_state(pci); if (pci_enable_device(pci) < 0) { - printk(KERN_ERR "atiixp: pci_enable_device failed, " - "disabling device\n"); + dev_err(dev, "pci_enable_device failed, disabling device\n"); snd_card_disconnect(card); return -EIO; } @@ -1637,14 +1636,14 @@ static int snd_atiixp_create(struct snd_card *card, chip->addr = pci_resource_start(pci, 0); chip->remap_addr = pci_ioremap_bar(pci, 0); if (chip->remap_addr == NULL) { - snd_printk(KERN_ERR "AC'97 space ioremap problem\n"); + dev_err(card->dev, "AC'97 space ioremap problem\n"); snd_atiixp_free(chip); return -EIO; } if (request_irq(pci->irq, snd_atiixp_interrupt, IRQF_SHARED, KBUILD_MODNAME, chip)) { - snd_printk(KERN_ERR "unable to grab IRQ %d\n", pci->irq); + dev_err(card->dev, "unable to grab IRQ %d\n", pci->irq); snd_atiixp_free(chip); return -EBUSY; } @@ -1657,8 +1656,6 @@ static int snd_atiixp_create(struct snd_card *card, return err; } - snd_card_set_dev(card, &pci->dev); - *r_chip = chip; return 0; } @@ -1671,7 +1668,7 @@ static int snd_atiixp_probe(struct pci_dev *pci, struct atiixp *chip; int err; - err = snd_card_create(index, id, THIS_MODULE, 0, &card); + err = snd_card_new(&pci->dev, index, id, THIS_MODULE, 0, &card); if (err < 0) return err; diff --git a/sound/pci/atiixp_modem.c b/sound/pci/atiixp_modem.c index 289563ecb6d..b9dc96c5d21 100644 --- a/sound/pci/atiixp_modem.c +++ b/sound/pci/atiixp_modem.c @@ -400,7 +400,7 @@ static int snd_atiixp_acquire_codec(struct atiixp_modem *chip) while (atiixp_read(chip, PHYS_OUT_ADDR) & ATI_REG_PHYS_OUT_ADDR_EN) { if (! timeout--) { - snd_printk(KERN_WARNING "atiixp-modem: codec acquire timeout\n"); + dev_warn(chip->card->dev, "codec acquire timeout\n"); return -EBUSY; } udelay(1); @@ -433,7 +433,7 @@ static unsigned short snd_atiixp_codec_read(struct atiixp_modem *chip, } while (--timeout); /* time out may happen during reset */ if (reg < 0x7c) - snd_printk(KERN_WARNING "atiixp-modem: codec read timeout (reg %x)\n", reg); + dev_warn(chip->card->dev, "codec read timeout (reg %x)\n", reg); return 0xffff; } @@ -499,7 +499,7 @@ static int snd_atiixp_aclink_reset(struct atiixp_modem *chip) msleep(1); atiixp_update(chip, CMD, ATI_REG_CMD_AC_RESET, ATI_REG_CMD_AC_RESET); if (!--timeout) { - snd_printk(KERN_ERR "atiixp-modem: codec reset timeout\n"); + dev_err(chip->card->dev, "codec reset timeout\n"); break; } } @@ -553,7 +553,7 @@ static int snd_atiixp_codec_detect(struct atiixp_modem *chip) atiixp_write(chip, IER, 0); /* disable irqs */ if ((chip->codec_not_ready_bits & ALL_CODEC_NOT_READY) == ALL_CODEC_NOT_READY) { - snd_printk(KERN_ERR "atiixp-modem: no codec detected!\n"); + dev_err(chip->card->dev, "no codec detected!\n"); return -ENXIO; } return 0; @@ -624,7 +624,7 @@ static snd_pcm_uframes_t snd_atiixp_pcm_pointer(struct snd_pcm_substream *substr continue; return bytes_to_frames(runtime, curptr); } - snd_printd("atiixp-modem: invalid DMA pointer read 0x%x (buf=%x)\n", + dev_dbg(chip->card->dev, "invalid DMA pointer read 0x%x (buf=%x)\n", readl(chip->remap_addr + dma->ops->dt_cur), dma->buf_addr); return 0; } @@ -637,7 +637,7 @@ static void snd_atiixp_xrun_dma(struct atiixp_modem *chip, { if (! dma->substream || ! dma->running) return; - snd_printdd("atiixp-modem: XRUN detected (DMA %d)\n", dma->ops->type); + dev_dbg(chip->card->dev, "XRUN detected (DMA %d)\n", dma->ops->type); snd_pcm_stream_lock(dma->substream); snd_pcm_stop(dma->substream, SNDRV_PCM_STATE_XRUN); snd_pcm_stream_unlock(dma->substream); @@ -1098,14 +1098,15 @@ static int snd_atiixp_mixer_new(struct atiixp_modem *chip, int clock) ac97.scaps = AC97_SCAP_SKIP_AUDIO | AC97_SCAP_POWER_SAVE; if ((err = snd_ac97_mixer(pbus, &ac97, &chip->ac97[i])) < 0) { chip->ac97[i] = NULL; /* to be sure */ - snd_printdd("atiixp-modem: codec %d not available for modem\n", i); + dev_dbg(chip->card->dev, + "codec %d not available for modem\n", i); continue; } codec_count++; } if (! codec_count) { - snd_printk(KERN_ERR "atiixp-modem: no codec available\n"); + dev_err(chip->card->dev, "no codec available\n"); return -ENODEV; } @@ -1150,8 +1151,7 @@ static int snd_atiixp_resume(struct device *dev) pci_set_power_state(pci, PCI_D0); pci_restore_state(pci); if (pci_enable_device(pci) < 0) { - printk(KERN_ERR "atiixp-modem: pci_enable_device failed, " - "disabling device\n"); + dev_err(dev, "pci_enable_device failed, disabling device\n"); snd_card_disconnect(card); return -EIO; } @@ -1262,14 +1262,14 @@ static int snd_atiixp_create(struct snd_card *card, chip->addr = pci_resource_start(pci, 0); chip->remap_addr = pci_ioremap_bar(pci, 0); if (chip->remap_addr == NULL) { - snd_printk(KERN_ERR "AC'97 space ioremap problem\n"); + dev_err(card->dev, "AC'97 space ioremap problem\n"); snd_atiixp_free(chip); return -EIO; } if (request_irq(pci->irq, snd_atiixp_interrupt, IRQF_SHARED, KBUILD_MODNAME, chip)) { - snd_printk(KERN_ERR "unable to grab IRQ %d\n", pci->irq); + dev_err(card->dev, "unable to grab IRQ %d\n", pci->irq); snd_atiixp_free(chip); return -EBUSY; } @@ -1282,8 +1282,6 @@ static int snd_atiixp_create(struct snd_card *card, return err; } - snd_card_set_dev(card, &pci->dev); - *r_chip = chip; return 0; } @@ -1296,7 +1294,7 @@ static int snd_atiixp_probe(struct pci_dev *pci, struct atiixp_modem *chip; int err; - err = snd_card_create(index, id, THIS_MODULE, 0, &card); + err = snd_card_new(&pci->dev, index, id, THIS_MODULE, 0, &card); if (err < 0) return err; diff --git a/sound/pci/au88x0/au88x0.c b/sound/pci/au88x0/au88x0.c index 7059dd69e5e..afb1b44b741 100644 --- a/sound/pci/au88x0/au88x0.c +++ b/sound/pci/au88x0/au88x0.c @@ -211,8 +211,6 @@ snd_vortex_create(struct snd_card *card, struct pci_dev *pci, vortex_t ** rchip) goto alloc_out; } - snd_card_set_dev(card, &pci->dev); - *rchip = chip; return 0; @@ -250,7 +248,8 @@ snd_vortex_probe(struct pci_dev *pci, const struct pci_device_id *pci_id) return -ENOENT; } // (2) - err = snd_card_create(index[dev], id[dev], THIS_MODULE, 0, &card); + err = snd_card_new(&pci->dev, index[dev], id[dev], THIS_MODULE, + 0, &card); if (err < 0) return err; diff --git a/sound/pci/aw2/aw2-alsa.c b/sound/pci/aw2/aw2-alsa.c index 2925220d3fc..120d0d320a6 100644 --- a/sound/pci/aw2/aw2-alsa.c +++ b/sound/pci/aw2/aw2-alsa.c @@ -262,7 +262,7 @@ static int snd_aw2_create(struct snd_card *card, /* check PCI availability (32bit DMA) */ 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 "aw2: Impossible to set 32bit mask DMA\n"); + dev_err(card->dev, "Impossible to set 32bit mask DMA\n"); pci_disable_device(pci); return -ENXIO; } @@ -290,7 +290,7 @@ static int snd_aw2_create(struct snd_card *card, pci_resource_len(pci, 0)); if (chip->iobase_virt == NULL) { - printk(KERN_ERR "aw2: unable to remap memory region"); + dev_err(card->dev, "unable to remap memory region"); pci_release_regions(pci); pci_disable_device(pci); kfree(chip); @@ -302,7 +302,7 @@ static int snd_aw2_create(struct snd_card *card, if (request_irq(pci->irq, snd_aw2_saa7146_interrupt, IRQF_SHARED, KBUILD_MODNAME, chip)) { - printk(KERN_ERR "aw2: Cannot grab irq %d\n", pci->irq); + dev_err(card->dev, "Cannot grab irq %d\n", pci->irq); iounmap(chip->iobase_virt); pci_release_regions(chip->pci); @@ -322,12 +322,10 @@ static int snd_aw2_create(struct snd_card *card, return err; } - snd_card_set_dev(card, &pci->dev); *rchip = chip; - printk(KERN_INFO - "Audiowerk 2 sound card (saa7146 chipset) detected and " - "managed\n"); + dev_info(card->dev, + "Audiowerk 2 sound card (saa7146 chipset) detected and managed\n"); return 0; } @@ -349,7 +347,8 @@ static int snd_aw2_probe(struct pci_dev *pci, } /* (2) Create card instance */ - err = snd_card_create(index[dev], id[dev], THIS_MODULE, 0, &card); + err = snd_card_new(&pci->dev, index[dev], id[dev], THIS_MODULE, + 0, &card); if (err < 0) return err; @@ -399,7 +398,7 @@ static int snd_aw2_pcm_playback_open(struct snd_pcm_substream *substream) { struct snd_pcm_runtime *runtime = substream->runtime; - snd_printdd(KERN_DEBUG "aw2: Playback_open\n"); + dev_dbg(substream->pcm->card->dev, "Playback_open\n"); runtime->hw = snd_aw2_playback_hw; return 0; } @@ -415,7 +414,7 @@ static int snd_aw2_pcm_capture_open(struct snd_pcm_substream *substream) { struct snd_pcm_runtime *runtime = substream->runtime; - snd_printdd(KERN_DEBUG "aw2: Capture_open\n"); + dev_dbg(substream->pcm->card->dev, "Capture_open\n"); runtime->hw = snd_aw2_capture_hw; return 0; } @@ -603,7 +602,7 @@ static int snd_aw2_new_pcm(struct aw2 *chip) err = snd_pcm_new(chip->card, "Audiowerk2 analog playback", 0, 1, 0, &pcm_playback_ana); if (err < 0) { - printk(KERN_ERR "aw2: snd_pcm_new error (0x%X)\n", err); + dev_err(chip->card->dev, "snd_pcm_new error (0x%X)\n", err); return err; } @@ -633,14 +632,15 @@ static int snd_aw2_new_pcm(struct aw2 *chip) (chip->pci), 64 * 1024, 64 * 1024); if (err) - printk(KERN_ERR "aw2: snd_pcm_lib_preallocate_pages_for_all " - "error (0x%X)\n", err); + dev_err(chip->card->dev, + "snd_pcm_lib_preallocate_pages_for_all error (0x%X)\n", + err); err = snd_pcm_new(chip->card, "Audiowerk2 digital playback", 1, 1, 0, &pcm_playback_num); if (err < 0) { - printk(KERN_ERR "aw2: snd_pcm_new error (0x%X)\n", err); + dev_err(chip->card->dev, "snd_pcm_new error (0x%X)\n", err); return err; } /* Creation ok */ @@ -669,17 +669,15 @@ static int snd_aw2_new_pcm(struct aw2 *chip) (chip->pci), 64 * 1024, 64 * 1024); if (err) - printk(KERN_ERR - "aw2: snd_pcm_lib_preallocate_pages_for_all error " - "(0x%X)\n", err); - - + dev_err(chip->card->dev, + "snd_pcm_lib_preallocate_pages_for_all error (0x%X)\n", + err); err = snd_pcm_new(chip->card, "Audiowerk2 capture", 2, 0, 1, &pcm_capture); if (err < 0) { - printk(KERN_ERR "aw2: snd_pcm_new error (0x%X)\n", err); + dev_err(chip->card->dev, "snd_pcm_new error (0x%X)\n", err); return err; } @@ -709,15 +707,15 @@ static int snd_aw2_new_pcm(struct aw2 *chip) (chip->pci), 64 * 1024, 64 * 1024); if (err) - printk(KERN_ERR - "aw2: snd_pcm_lib_preallocate_pages_for_all error " - "(0x%X)\n", err); + dev_err(chip->card->dev, + "snd_pcm_lib_preallocate_pages_for_all error (0x%X)\n", + err); /* Create control */ err = snd_ctl_add(chip->card, snd_ctl_new1(&aw2_control, chip)); if (err < 0) { - printk(KERN_ERR "aw2: snd_ctl_add error (0x%X)\n", err); + dev_err(chip->card->dev, "snd_ctl_add error (0x%X)\n", err); return err; } diff --git a/sound/pci/aw2/aw2-saa7146.c b/sound/pci/aw2/aw2-saa7146.c index 4439636971e..6d24e953677 100644 --- a/sound/pci/aw2/aw2-saa7146.c +++ b/sound/pci/aw2/aw2-saa7146.c @@ -204,8 +204,7 @@ void snd_aw2_saa7146_pcm_init_playback(struct snd_aw2_saa7146 *chip, /* Define upper limit for DMA access */ WRITEREG(dma_addr + buffer_size, ProtA1_out); } else { - printk(KERN_ERR - "aw2: snd_aw2_saa7146_pcm_init_playback: " + pr_err("aw2: snd_aw2_saa7146_pcm_init_playback: " "Substream number is not 0 or 1 -> not managed\n"); } } @@ -251,8 +250,7 @@ void snd_aw2_saa7146_pcm_init_capture(struct snd_aw2_saa7146 *chip, /* Define upper limit for DMA access */ WRITEREG(dma_addr + buffer_size, ProtA1_in); } else { - printk(KERN_ERR - "aw2: snd_aw2_saa7146_pcm_init_capture: " + pr_err("aw2: snd_aw2_saa7146_pcm_init_capture: " "Substream number is not 0 -> not managed\n"); } } diff --git a/sound/pci/azt3328.c b/sound/pci/azt3328.c index 1aef7128f7c..c9216c0a9c8 100644 --- a/sound/pci/azt3328.c +++ b/sound/pci/azt3328.c @@ -238,61 +238,6 @@ MODULE_SUPPORTED_DEVICE("{{Aztech,AZF3328}}"); 2>/dev/null */ -#define DEBUG_MISC 0 -#define DEBUG_CALLS 0 -#define DEBUG_MIXER 0 -#define DEBUG_CODEC 0 -#define DEBUG_TIMER 0 -#define DEBUG_GAME 0 -#define DEBUG_PM 0 -#define MIXER_TESTING 0 - -#if DEBUG_MISC -#define snd_azf3328_dbgmisc(format, args...) printk(KERN_DEBUG format, ##args) -#else -#define snd_azf3328_dbgmisc(format, args...) -#endif - -#if DEBUG_CALLS -#define snd_azf3328_dbgcalls(format, args...) printk(format, ##args) -#define snd_azf3328_dbgcallenter() printk(KERN_DEBUG "--> %s\n", __func__) -#define snd_azf3328_dbgcallleave() printk(KERN_DEBUG "<-- %s\n", __func__) -#else -#define snd_azf3328_dbgcalls(format, args...) -#define snd_azf3328_dbgcallenter() -#define snd_azf3328_dbgcallleave() -#endif - -#if DEBUG_MIXER -#define snd_azf3328_dbgmixer(format, args...) printk(KERN_DEBUG format, ##args) -#else -#define snd_azf3328_dbgmixer(format, args...) -#endif - -#if DEBUG_CODEC -#define snd_azf3328_dbgcodec(format, args...) printk(KERN_DEBUG format, ##args) -#else -#define snd_azf3328_dbgcodec(format, args...) -#endif - -#if DEBUG_MISC -#define snd_azf3328_dbgtimer(format, args...) printk(KERN_DEBUG format, ##args) -#else -#define snd_azf3328_dbgtimer(format, args...) -#endif - -#if DEBUG_GAME -#define snd_azf3328_dbggame(format, args...) printk(KERN_DEBUG format, ##args) -#else -#define snd_azf3328_dbggame(format, args...) -#endif - -#if DEBUG_PM -#define snd_azf3328_dbgpm(format, args...) printk(KERN_DEBUG format, ##args) -#else -#define snd_azf3328_dbgpm(format, args...) -#endif - static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */ module_param_array(index, int, NULL, 0444); MODULE_PARM_DESC(index, "Index value for AZF3328 soundcard."); @@ -475,6 +420,12 @@ snd_azf3328_ctrl_inb(const struct snd_azf3328 *chip, unsigned reg) return inb(chip->ctrl_io + reg); } +static inline u16 +snd_azf3328_ctrl_inw(const struct snd_azf3328 *chip, unsigned reg) +{ + return inw(chip->ctrl_io + reg); +} + static inline void snd_azf3328_ctrl_outw(const struct snd_azf3328 *chip, unsigned reg, u16 value) { @@ -578,11 +529,12 @@ snd_azf3328_mixer_reset(const struct snd_azf3328 *chip) #ifdef AZF_USE_AC97_LAYER static inline void -snd_azf3328_mixer_ac97_map_unsupported(unsigned short reg, const char *mode) +snd_azf3328_mixer_ac97_map_unsupported(const struct snd_azf3328 *chip, + unsigned short reg, const char *mode) { /* need to add some more or less clever emulation? */ - printk(KERN_WARNING - "azt3328: missing %s emulation for AC97 register 0x%02x!\n", + dev_warn(chip->card->dev, + "missing %s emulation for AC97 register 0x%02x!\n", mode, reg); } @@ -717,10 +669,8 @@ snd_azf3328_mixer_ac97_read(struct snd_ac97 *ac97, unsigned short reg_ac97) unsigned short reg_val = 0; bool unsupported = false; - snd_azf3328_dbgmixer( - "snd_azf3328_mixer_ac97_read reg_ac97 %u\n", - reg_ac97 - ); + dev_dbg(chip->card->dev, "snd_azf3328_mixer_ac97_read reg_ac97 %u\n", + reg_ac97); if (reg_azf & AZF_AC97_REG_UNSUPPORTED) unsupported = true; else { @@ -765,7 +715,7 @@ snd_azf3328_mixer_ac97_read(struct snd_ac97 *ac97, unsigned short reg_ac97) } } if (unsupported) - snd_azf3328_mixer_ac97_map_unsupported(reg_ac97, "read"); + snd_azf3328_mixer_ac97_map_unsupported(chip, reg_ac97, "read"); return reg_val; } @@ -778,10 +728,9 @@ snd_azf3328_mixer_ac97_write(struct snd_ac97 *ac97, unsigned short reg_azf = snd_azf3328_mixer_ac97_map_reg_idx(reg_ac97); bool unsupported = false; - snd_azf3328_dbgmixer( + dev_dbg(chip->card->dev, "snd_azf3328_mixer_ac97_write reg_ac97 %u val %u\n", - reg_ac97, val - ); + reg_ac97, val); if (reg_azf & AZF_AC97_REG_UNSUPPORTED) unsupported = true; else { @@ -814,7 +763,7 @@ snd_azf3328_mixer_ac97_write(struct snd_ac97 *ac97, } } if (unsupported) - snd_azf3328_mixer_ac97_map_unsupported(reg_ac97, "write"); + snd_azf3328_mixer_ac97_map_unsupported(chip, reg_ac97, "write"); } static int @@ -850,7 +799,7 @@ snd_azf3328_mixer_new(struct snd_azf3328 *chip) * due to this card being a very quirky AC97 "lookalike". */ if (rc) - printk(KERN_ERR "azt3328: AC97 init failed, err %d!\n", rc); + dev_err(chip->card->dev, "AC97 init failed, err %d!\n", rc); /* If we return an error here, then snd_card_free() should * free up any ac97 codecs that got created, as well as the bus. @@ -870,8 +819,6 @@ snd_azf3328_mixer_write_volume_gradually(const struct snd_azf3328 *chip, unsigned char curr_vol_left = 0, curr_vol_right = 0; int left_change = 0, right_change = 0; - snd_azf3328_dbgcallenter(); - if (chan_sel & SET_CHAN_LEFT) { curr_vol_left = inb(portbase + 1); @@ -912,7 +859,6 @@ snd_azf3328_mixer_write_volume_gradually(const struct snd_azf3328 *chip, if (delay) mdelay(delay); } while ((left_change) || (right_change)); - snd_azf3328_dbgcallleave(); } /* @@ -990,14 +936,12 @@ snd_azf3328_info_mixer(struct snd_kcontrol *kcontrol, { struct azf3328_mixer_reg reg; - snd_azf3328_dbgcallenter(); snd_azf3328_mixer_reg_decode(®, kcontrol->private_value); uinfo->type = reg.mask == 1 ? SNDRV_CTL_ELEM_TYPE_BOOLEAN : SNDRV_CTL_ELEM_TYPE_INTEGER; uinfo->count = reg.stereo + 1; uinfo->value.integer.min = 0; uinfo->value.integer.max = reg.mask; - snd_azf3328_dbgcallleave(); return 0; } @@ -1009,7 +953,6 @@ snd_azf3328_get_mixer(struct snd_kcontrol *kcontrol, struct azf3328_mixer_reg reg; u16 oreg, val; - snd_azf3328_dbgcallenter(); snd_azf3328_mixer_reg_decode(®, kcontrol->private_value); oreg = snd_azf3328_mixer_inw(chip, reg.reg); @@ -1023,12 +966,11 @@ snd_azf3328_get_mixer(struct snd_kcontrol *kcontrol, val = reg.mask - val; ucontrol->value.integer.value[1] = val; } - snd_azf3328_dbgmixer("get: %02x is %04x -> vol %02lx|%02lx " - "(shift %02d|%02d, mask %02x, inv. %d, stereo %d)\n", + dev_dbg(chip->card->dev, + "get: %02x is %04x -> vol %02lx|%02lx (shift %02d|%02d, mask %02x, inv. %d, stereo %d)\n", reg.reg, oreg, ucontrol->value.integer.value[0], ucontrol->value.integer.value[1], reg.lchan_shift, reg.rchan_shift, reg.mask, reg.invert, reg.stereo); - snd_azf3328_dbgcallleave(); return 0; } @@ -1040,7 +982,6 @@ snd_azf3328_put_mixer(struct snd_kcontrol *kcontrol, struct azf3328_mixer_reg reg; u16 oreg, nreg, val; - snd_azf3328_dbgcallenter(); snd_azf3328_mixer_reg_decode(®, kcontrol->private_value); oreg = snd_azf3328_mixer_inw(chip, reg.reg); val = ucontrol->value.integer.value[0] & reg.mask; @@ -1064,12 +1005,11 @@ snd_azf3328_put_mixer(struct snd_kcontrol *kcontrol, else snd_azf3328_mixer_outw(chip, reg.reg, nreg); - snd_azf3328_dbgmixer("put: %02x to %02lx|%02lx, " - "oreg %04x; shift %02d|%02d -> nreg %04x; after: %04x\n", + dev_dbg(chip->card->dev, + "put: %02x to %02lx|%02lx, oreg %04x; shift %02d|%02d -> nreg %04x; after: %04x\n", reg.reg, ucontrol->value.integer.value[0], ucontrol->value.integer.value[1], oreg, reg.lchan_shift, reg.rchan_shift, nreg, snd_azf3328_mixer_inw(chip, reg.reg)); - snd_azf3328_dbgcallleave(); return (nreg != oreg); } @@ -1135,7 +1075,8 @@ snd_azf3328_get_mixer_enum(struct snd_kcontrol *kcontrol, } else ucontrol->value.enumerated.item[0] = (val >> reg.lchan_shift) & (reg.enum_c - 1); - snd_azf3328_dbgmixer("get_enum: %02x is %04x -> %d|%d (shift %02d, enum_c %d)\n", + dev_dbg(chip->card->dev, + "get_enum: %02x is %04x -> %d|%d (shift %02d, enum_c %d)\n", reg.reg, val, ucontrol->value.enumerated.item[0], ucontrol->value.enumerated.item[1], reg.lchan_shift, reg.enum_c); return 0; @@ -1167,7 +1108,8 @@ snd_azf3328_put_mixer_enum(struct snd_kcontrol *kcontrol, snd_azf3328_mixer_outw(chip, reg.reg, val); nreg = val; - snd_azf3328_dbgmixer("put_enum: %02x to %04x, oreg %04x\n", reg.reg, val, oreg); + dev_dbg(chip->card->dev, + "put_enum: %02x to %04x, oreg %04x\n", reg.reg, val, oreg); return (nreg != oreg); } @@ -1253,7 +1195,6 @@ snd_azf3328_mixer_new(struct snd_azf3328 *chip) unsigned int idx; int err; - snd_azf3328_dbgcallenter(); if (snd_BUG_ON(!chip || !chip->card)) return -EINVAL; @@ -1279,7 +1220,6 @@ snd_azf3328_mixer_new(struct snd_azf3328 *chip) snd_component_add(card, "AZF3328 mixer"); strcpy(card->mixername, "AZF3328 mixer"); - snd_azf3328_dbgcallleave(); return 0; } #endif /* AZF_USE_AC97_LAYER */ @@ -1288,19 +1228,13 @@ static int snd_azf3328_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *hw_params) { - int res; - snd_azf3328_dbgcallenter(); - res = snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params)); - snd_azf3328_dbgcallleave(); - return res; + return snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params)); } static int snd_azf3328_hw_free(struct snd_pcm_substream *substream) { - snd_azf3328_dbgcallenter(); snd_pcm_lib_free_pages(substream); - snd_azf3328_dbgcallleave(); return 0; } @@ -1315,7 +1249,6 @@ snd_azf3328_codec_setfmt(struct snd_azf3328_codec_data *codec, u16 val = 0xff00; u8 freq = 0; - snd_azf3328_dbgcallenter(); switch (bitrate) { case AZF_FREQ_4000: freq = SOUNDFORMAT_FREQ_SUSPECTED_4000; break; case AZF_FREQ_4800: freq = SOUNDFORMAT_FREQ_SUSPECTED_4800; break; @@ -1379,7 +1312,6 @@ snd_azf3328_codec_setfmt(struct snd_azf3328_codec_data *codec, ); spin_unlock_irqrestore(codec->lock, flags); - snd_azf3328_dbgcallleave(); } static inline void @@ -1404,15 +1336,16 @@ snd_azf3328_ctrl_reg_6AH_update(struct snd_azf3328 *chip, chip->shadow_reg_ctrl_6AH |= bitmask; else chip->shadow_reg_ctrl_6AH &= ~bitmask; - snd_azf3328_dbgcodec("6AH_update mask 0x%04x do_mask %d: val 0x%04x\n", - bitmask, do_mask, chip->shadow_reg_ctrl_6AH); + dev_dbg(chip->card->dev, + "6AH_update mask 0x%04x do_mask %d: val 0x%04x\n", + bitmask, do_mask, chip->shadow_reg_ctrl_6AH); snd_azf3328_ctrl_outw(chip, IDX_IO_6AH, chip->shadow_reg_ctrl_6AH); } static inline void snd_azf3328_ctrl_enable_codecs(struct snd_azf3328 *chip, bool enable) { - snd_azf3328_dbgcodec("codec_enable %d\n", enable); + dev_dbg(chip->card->dev, "codec_enable %d\n", enable); /* no idea what exactly is being done here, but I strongly assume it's * PM related */ snd_azf3328_ctrl_reg_6AH_update( @@ -1429,7 +1362,7 @@ snd_azf3328_ctrl_codec_activity(struct snd_azf3328 *chip, struct snd_azf3328_codec_data *codec = &chip->codecs[codec_type]; bool need_change = (codec->running != enable); - snd_azf3328_dbgcodec( + dev_dbg(chip->card->dev, "codec_activity: %s codec, enable %d, need_change %d\n", codec->name, enable, need_change ); @@ -1470,13 +1403,13 @@ snd_azf3328_ctrl_codec_activity(struct snd_azf3328 *chip, } static void -snd_azf3328_codec_setdmaa(struct snd_azf3328_codec_data *codec, - unsigned long addr, - unsigned int period_bytes, - unsigned int buffer_bytes +snd_azf3328_codec_setdmaa(struct snd_azf3328 *chip, + struct snd_azf3328_codec_data *codec, + unsigned long addr, + unsigned int period_bytes, + unsigned int buffer_bytes ) { - snd_azf3328_dbgcallenter(); WARN_ONCE(period_bytes & 1, "odd period length!?\n"); WARN_ONCE(buffer_bytes != 2 * period_bytes, "missed our input expectations! %u vs. %u\n", @@ -1499,7 +1432,7 @@ snd_azf3328_codec_setdmaa(struct snd_azf3328_codec_data *codec, setup_io.dma_start_1 = addr; setup_io.dma_start_2 = addr+area_length; - snd_azf3328_dbgcodec( + dev_dbg(chip->card->dev, "setdma: buffers %08x[%u] / %08x[%u], %u, %u\n", setup_io.dma_start_1, area_length, setup_io.dma_start_2, area_length, @@ -1522,7 +1455,6 @@ snd_azf3328_codec_setdmaa(struct snd_azf3328_codec_data *codec, ); spin_unlock_irqrestore(codec->lock, flags); } - snd_azf3328_dbgcallleave(); } static int @@ -1535,8 +1467,6 @@ snd_azf3328_pcm_prepare(struct snd_pcm_substream *substream) unsigned int count = snd_pcm_lib_period_bytes(substream); #endif - snd_azf3328_dbgcallenter(); - codec->dma_base = runtime->dma_addr; #if 0 @@ -1544,10 +1474,9 @@ snd_azf3328_pcm_prepare(struct snd_pcm_substream *substream) runtime->rate, snd_pcm_format_width(runtime->format), runtime->channels); - snd_azf3328_codec_setdmaa(codec, + snd_azf3328_codec_setdmaa(chip, codec, runtime->dma_addr, count, size); #endif - snd_azf3328_dbgcallleave(); return 0; } @@ -1562,11 +1491,9 @@ snd_azf3328_pcm_trigger(struct snd_pcm_substream *substream, int cmd) bool previously_muted = false; bool is_main_mixer_playback_codec = (AZF_CODEC_PLAYBACK == codec->type); - snd_azf3328_dbgcalls("snd_azf3328_pcm_trigger cmd %d\n", cmd); - switch (cmd) { case SNDRV_PCM_TRIGGER_START: - snd_azf3328_dbgcodec("START %s\n", codec->name); + dev_dbg(chip->card->dev, "START PCM %s\n", codec->name); if (is_main_mixer_playback_codec) { /* mute WaveOut (avoid clicking during setup) */ @@ -1593,7 +1520,7 @@ snd_azf3328_pcm_trigger(struct snd_pcm_substream *substream, int cmd) snd_azf3328_codec_outw(codec, IDX_IO_CODEC_IRQTYPE, 0xffff); spin_unlock(codec->lock); - snd_azf3328_codec_setdmaa(codec, runtime->dma_addr, + snd_azf3328_codec_setdmaa(chip, codec, runtime->dma_addr, snd_pcm_lib_period_bytes(substream), snd_pcm_lib_buffer_bytes(substream) ); @@ -1633,10 +1560,10 @@ snd_azf3328_pcm_trigger(struct snd_pcm_substream *substream, int cmd) ); } - snd_azf3328_dbgcodec("STARTED %s\n", codec->name); + dev_dbg(chip->card->dev, "PCM STARTED %s\n", codec->name); break; case SNDRV_PCM_TRIGGER_RESUME: - snd_azf3328_dbgcodec("RESUME %s\n", codec->name); + dev_dbg(chip->card->dev, "PCM RESUME %s\n", codec->name); /* resume codec if we were active */ spin_lock(codec->lock); if (codec->running) @@ -1648,7 +1575,7 @@ snd_azf3328_pcm_trigger(struct snd_pcm_substream *substream, int cmd) spin_unlock(codec->lock); break; case SNDRV_PCM_TRIGGER_STOP: - snd_azf3328_dbgcodec("STOP %s\n", codec->name); + dev_dbg(chip->card->dev, "PCM STOP %s\n", codec->name); if (is_main_mixer_playback_codec) { /* mute WaveOut (avoid clicking during setup) */ @@ -1684,10 +1611,10 @@ snd_azf3328_pcm_trigger(struct snd_pcm_substream *substream, int cmd) ); } - snd_azf3328_dbgcodec("STOPPED %s\n", codec->name); + dev_dbg(chip->card->dev, "PCM STOPPED %s\n", codec->name); break; case SNDRV_PCM_TRIGGER_SUSPEND: - snd_azf3328_dbgcodec("SUSPEND %s\n", codec->name); + dev_dbg(chip->card->dev, "PCM SUSPEND %s\n", codec->name); /* make sure codec is stopped */ snd_azf3328_codec_outw(codec, IDX_IO_CODEC_DMA_FLAGS, snd_azf3328_codec_inw( @@ -1696,17 +1623,16 @@ snd_azf3328_pcm_trigger(struct snd_pcm_substream *substream, int cmd) ); break; case SNDRV_PCM_TRIGGER_PAUSE_PUSH: - snd_printk(KERN_ERR "FIXME: SNDRV_PCM_TRIGGER_PAUSE_PUSH NIY!\n"); + WARN(1, "FIXME: SNDRV_PCM_TRIGGER_PAUSE_PUSH NIY!\n"); break; case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: - snd_printk(KERN_ERR "FIXME: SNDRV_PCM_TRIGGER_PAUSE_RELEASE NIY!\n"); + WARN(1, "FIXME: SNDRV_PCM_TRIGGER_PAUSE_RELEASE NIY!\n"); break; default: - snd_printk(KERN_ERR "FIXME: unknown trigger mode!\n"); + WARN(1, "FIXME: unknown trigger mode!\n"); return -EINVAL; } - snd_azf3328_dbgcallleave(); return result; } @@ -1728,8 +1654,8 @@ snd_azf3328_pcm_pointer(struct snd_pcm_substream *substream result -= codec->dma_base; #endif frmres = bytes_to_frames( substream->runtime, result); - snd_azf3328_dbgcodec("%08li %s @ 0x%8lx, frames %8ld\n", - jiffies, codec->name, result, frmres); + dev_dbg(substream->pcm->card->dev, "%08li %s @ 0x%8lx, frames %8ld\n", + jiffies, codec->name, result, frmres); return frmres; } @@ -1792,7 +1718,7 @@ snd_azf3328_gameport_interrupt(struct snd_azf3328 *chip) * skeleton handler only * (we do not want axis reading in interrupt handler - too much load!) */ - snd_azf3328_dbggame("gameport irq\n"); + dev_dbg(chip->card->dev, "gameport irq\n"); /* this should ACK the gameport IRQ properly, hopefully. */ snd_azf3328_game_inw(chip, IDX_GAME_AXIS_VALUE); @@ -1804,7 +1730,7 @@ snd_azf3328_gameport_open(struct gameport *gameport, int mode) struct snd_azf3328 *chip = gameport_get_port_data(gameport); int res; - snd_azf3328_dbggame("gameport_open, mode %d\n", mode); + dev_dbg(chip->card->dev, "gameport_open, mode %d\n", mode); switch (mode) { case GAMEPORT_MODE_COOKED: case GAMEPORT_MODE_RAW: @@ -1827,7 +1753,7 @@ snd_azf3328_gameport_close(struct gameport *gameport) { struct snd_azf3328 *chip = gameport_get_port_data(gameport); - snd_azf3328_dbggame("gameport_close\n"); + dev_dbg(chip->card->dev, "gameport_close\n"); snd_azf3328_gameport_set_counter_frequency(chip, GAME_HWCFG_ADC_COUNTER_FREQ_1_200); snd_azf3328_gameport_axis_circuit_enable(chip, 0); @@ -1892,9 +1818,8 @@ snd_azf3328_gameport_cooked_read(struct gameport *gameport, axes[i] = -1; } - snd_azf3328_dbggame("cooked_read: axes %d %d %d %d buttons %d\n", - axes[0], axes[1], axes[2], axes[3], *buttons - ); + dev_dbg(chip->card->dev, "cooked_read: axes %d %d %d %d buttons %d\n", + axes[0], axes[1], axes[2], axes[3], *buttons); return 0; } @@ -1906,7 +1831,7 @@ snd_azf3328_gameport(struct snd_azf3328 *chip, int dev) chip->gameport = gp = gameport_allocate_port(); if (!gp) { - printk(KERN_ERR "azt3328: cannot alloc memory for gameport\n"); + dev_err(chip->card->dev, "cannot alloc memory for gameport\n"); return -ENOMEM; } @@ -1950,23 +1875,23 @@ snd_azf3328_gameport_free(struct snd_azf3328 *chip) { } static inline void snd_azf3328_gameport_interrupt(struct snd_azf3328 *chip) { - printk(KERN_WARNING "huh, game port IRQ occurred!?\n"); + dev_warn(chip->card->dev, "huh, game port IRQ occurred!?\n"); } #endif /* SUPPORT_GAMEPORT */ /******************************************************************/ static inline void -snd_azf3328_irq_log_unknown_type(u8 which) +snd_azf3328_irq_log_unknown_type(struct snd_azf3328 *chip, u8 which) { - snd_azf3328_dbgcodec( - "azt3328: unknown IRQ type (%x) occurred, please report!\n", - which - ); + dev_dbg(chip->card->dev, + "unknown IRQ type (%x) occurred, please report!\n", + which); } static inline void -snd_azf3328_pcm_interrupt(const struct snd_azf3328_codec_data *first_codec, +snd_azf3328_pcm_interrupt(struct snd_azf3328 *chip, + const struct snd_azf3328_codec_data *first_codec, u8 status ) { @@ -1990,17 +1915,15 @@ snd_azf3328_pcm_interrupt(const struct snd_azf3328_codec_data *first_codec, if (codec->substream) { snd_pcm_period_elapsed(codec->substream); - snd_azf3328_dbgcodec("%s period done (#%x), @ %x\n", + dev_dbg(chip->card->dev, "%s period done (#%x), @ %x\n", codec->name, which, snd_azf3328_codec_inl( - codec, IDX_IO_CODEC_DMA_CURRPOS - ) - ); + codec, IDX_IO_CODEC_DMA_CURRPOS)); } else - printk(KERN_WARNING "azt3328: irq handler problem!\n"); + dev_warn(chip->card->dev, "irq handler problem!\n"); if (which & IRQ_SOMETHING) - snd_azf3328_irq_log_unknown_type(which); + snd_azf3328_irq_log_unknown_type(chip, which); } } @@ -2009,9 +1932,7 @@ snd_azf3328_interrupt(int irq, void *dev_id) { struct snd_azf3328 *chip = dev_id; u8 status; -#if DEBUG_CODEC static unsigned long irq_count; -#endif status = snd_azf3328_ctrl_inb(chip, IDX_IO_IRQSTATUS); @@ -2022,14 +1943,13 @@ snd_azf3328_interrupt(int irq, void *dev_id) )) return IRQ_NONE; /* must be interrupt for another device */ - snd_azf3328_dbgcodec( + dev_dbg(chip->card->dev, "irq_count %ld! IDX_IO_IRQSTATUS %04x\n", irq_count++ /* debug-only */, - status - ); + status); if (status & IRQ_TIMER) { - /* snd_azf3328_dbgcodec("timer %ld\n", + /* dev_dbg(chip->card->dev, "timer %ld\n", snd_azf3328_codec_inl(chip, IDX_IO_TIMER_VALUE) & TIMER_VALUE_MASK ); */ @@ -2039,11 +1959,11 @@ snd_azf3328_interrupt(int irq, void *dev_id) spin_lock(&chip->reg_lock); snd_azf3328_ctrl_outb(chip, IDX_IO_TIMER_VALUE + 3, 0x07); spin_unlock(&chip->reg_lock); - snd_azf3328_dbgcodec("azt3328: timer IRQ\n"); + dev_dbg(chip->card->dev, "timer IRQ\n"); } if (status & (IRQ_PLAYBACK|IRQ_RECORDING|IRQ_I2S_OUT)) - snd_azf3328_pcm_interrupt(chip->codecs, status); + snd_azf3328_pcm_interrupt(chip, chip->codecs, status); if (status & IRQ_GAMEPORT) snd_azf3328_gameport_interrupt(chip); @@ -2055,7 +1975,7 @@ snd_azf3328_interrupt(int irq, void *dev_id) /* hmm, do we have to ack the IRQ here somehow? * If so, then I don't know how yet... */ - snd_azf3328_dbgcodec("azt3328: MPU401 IRQ\n"); + dev_dbg(chip->card->dev, "MPU401 IRQ\n"); } return IRQ_HANDLED; } @@ -2133,7 +2053,6 @@ snd_azf3328_pcm_open(struct snd_pcm_substream *substream, struct snd_pcm_runtime *runtime = substream->runtime; struct snd_azf3328_codec_data *codec = &chip->codecs[codec_type]; - snd_azf3328_dbgcallenter(); codec->substream = substream; /* same parameters for all our codecs - at least we think so... */ @@ -2142,7 +2061,6 @@ snd_azf3328_pcm_open(struct snd_pcm_substream *substream, snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, &snd_azf3328_hw_constraints_rates); runtime->private_data = codec; - snd_azf3328_dbgcallleave(); return 0; } @@ -2171,9 +2089,7 @@ snd_azf3328_pcm_close(struct snd_pcm_substream *substream struct snd_azf3328_codec_data *codec = substream->runtime->private_data; - snd_azf3328_dbgcallenter(); codec->substream = NULL; - snd_azf3328_dbgcallleave(); return 0; } @@ -2220,8 +2136,6 @@ enum { AZF_PCMDEV_STD, AZF_PCMDEV_I2S_OUT, NUM_AZF_PCMDEVS }; /* pcm devices */ struct snd_pcm *pcm; int err; - snd_azf3328_dbgcallenter(); - err = snd_pcm_new(chip->card, "AZF3328 DSP", AZF_PCMDEV_STD, 1, 1, &pcm); if (err < 0) @@ -2258,7 +2172,6 @@ enum { AZF_PCMDEV_STD, AZF_PCMDEV_I2S_OUT, NUM_AZF_PCMDEVS }; /* pcm devices */ snd_dma_pci_data(chip->pci), 64*1024, 64*1024); - snd_azf3328_dbgcallleave(); return 0; } @@ -2281,7 +2194,6 @@ snd_azf3328_timer_start(struct snd_timer *timer) unsigned long flags; unsigned int delay; - snd_azf3328_dbgcallenter(); chip = snd_timer_chip(timer); delay = ((timer->sticks * seqtimer_scaling) - 1) & TIMER_VALUE_MASK; if (delay < 49) { @@ -2289,15 +2201,14 @@ snd_azf3328_timer_start(struct snd_timer *timer) * this timing tweak * (we need to do it to avoid a lockup, though) */ - snd_azf3328_dbgtimer("delay was too low (%d)!\n", delay); + dev_dbg(chip->card->dev, "delay was too low (%d)!\n", delay); delay = 49; /* minimum time is 49 ticks */ } - snd_azf3328_dbgtimer("setting timer countdown value %d\n", delay); + dev_dbg(chip->card->dev, "setting timer countdown value %d\n", delay); delay |= TIMER_COUNTDOWN_ENABLE | TIMER_IRQ_ENABLE; spin_lock_irqsave(&chip->reg_lock, flags); snd_azf3328_ctrl_outl(chip, IDX_IO_TIMER_VALUE, delay); spin_unlock_irqrestore(&chip->reg_lock, flags); - snd_azf3328_dbgcallleave(); return 0; } @@ -2307,7 +2218,6 @@ snd_azf3328_timer_stop(struct snd_timer *timer) struct snd_azf3328 *chip; unsigned long flags; - snd_azf3328_dbgcallenter(); chip = snd_timer_chip(timer); spin_lock_irqsave(&chip->reg_lock, flags); /* disable timer countdown and interrupt */ @@ -2319,7 +2229,6 @@ snd_azf3328_timer_stop(struct snd_timer *timer) the hardware/ALSA interrupt activity. */ snd_azf3328_ctrl_outb(chip, IDX_IO_TIMER_VALUE + 3, 0x04); spin_unlock_irqrestore(&chip->reg_lock, flags); - snd_azf3328_dbgcallleave(); return 0; } @@ -2328,10 +2237,8 @@ static int snd_azf3328_timer_precise_resolution(struct snd_timer *timer, unsigned long *num, unsigned long *den) { - snd_azf3328_dbgcallenter(); *num = 1; *den = 1024000 / seqtimer_scaling; - snd_azf3328_dbgcallleave(); return 0; } @@ -2351,7 +2258,6 @@ snd_azf3328_timer(struct snd_azf3328 *chip, int device) struct snd_timer_id tid; int err; - snd_azf3328_dbgcallenter(); tid.dev_class = SNDRV_TIMER_CLASS_CARD; tid.dev_sclass = SNDRV_TIMER_SCLASS_NONE; tid.card = chip->card->number; @@ -2376,7 +2282,6 @@ snd_azf3328_timer(struct snd_azf3328 *chip, int device) err = 0; out: - snd_azf3328_dbgcallleave(); return err; } @@ -2438,34 +2343,34 @@ snd_azf3328_test_bit(unsigned unsigned reg, int bit) static inline void snd_azf3328_debug_show_ports(const struct snd_azf3328 *chip) { -#if DEBUG_MISC u16 tmp; - snd_azf3328_dbgmisc( + dev_dbg(chip->card->dev, "ctrl_io 0x%lx, game_io 0x%lx, mpu_io 0x%lx, " "opl3_io 0x%lx, mixer_io 0x%lx, irq %d\n", chip->ctrl_io, chip->game_io, chip->mpu_io, - chip->opl3_io, chip->mixer_io, chip->irq - ); + chip->opl3_io, chip->mixer_io, chip->irq); - snd_azf3328_dbgmisc("game %02x %02x %02x %02x %02x %02x\n", + dev_dbg(chip->card->dev, + "game %02x %02x %02x %02x %02x %02x\n", snd_azf3328_game_inb(chip, 0), snd_azf3328_game_inb(chip, 1), snd_azf3328_game_inb(chip, 2), snd_azf3328_game_inb(chip, 3), snd_azf3328_game_inb(chip, 4), - snd_azf3328_game_inb(chip, 5) - ); + snd_azf3328_game_inb(chip, 5)); for (tmp = 0; tmp < 0x07; tmp += 1) - snd_azf3328_dbgmisc("mpu_io 0x%04x\n", inb(chip->mpu_io + tmp)); + dev_dbg(chip->card->dev, + "mpu_io 0x%04x\n", inb(chip->mpu_io + tmp)); for (tmp = 0; tmp <= 0x07; tmp += 1) - snd_azf3328_dbgmisc("0x%02x: game200 0x%04x, game208 0x%04x\n", + dev_dbg(chip->card->dev, + "0x%02x: game200 0x%04x, game208 0x%04x\n", tmp, inb(0x200 + tmp), inb(0x208 + tmp)); for (tmp = 0; tmp <= 0x01; tmp += 1) - snd_azf3328_dbgmisc( + dev_dbg(chip->card->dev, "0x%02x: mpu300 0x%04x, mpu310 0x%04x, mpu320 0x%04x, " "mpu330 0x%04x opl388 0x%04x opl38c 0x%04x\n", tmp, @@ -2474,19 +2379,17 @@ snd_azf3328_debug_show_ports(const struct snd_azf3328 *chip) inb(0x320 + tmp), inb(0x330 + tmp), inb(0x388 + tmp), - inb(0x38c + tmp) - ); + inb(0x38c + tmp)); for (tmp = 0; tmp < AZF_IO_SIZE_CTRL; tmp += 2) - snd_azf3328_dbgmisc("ctrl 0x%02x: 0x%04x\n", - tmp, snd_azf3328_ctrl_inw(chip, tmp) - ); + dev_dbg(chip->card->dev, + "ctrl 0x%02x: 0x%04x\n", + tmp, snd_azf3328_ctrl_inw(chip, tmp)); for (tmp = 0; tmp < AZF_IO_SIZE_MIXER; tmp += 2) - snd_azf3328_dbgmisc("mixer 0x%02x: 0x%04x\n", - tmp, snd_azf3328_mixer_inw(chip, tmp) - ); -#endif /* DEBUG_MISC */ + dev_dbg(chip->card->dev, + "mixer 0x%02x: 0x%04x\n", + tmp, snd_azf3328_mixer_inw(chip, tmp)); } static int @@ -2523,8 +2426,8 @@ snd_azf3328_create(struct snd_card *card, /* check if we can restrict PCI DMA transfers to 24 bits */ if (pci_set_dma_mask(pci, DMA_BIT_MASK(24)) < 0 || pci_set_consistent_dma_mask(pci, DMA_BIT_MASK(24)) < 0) { - snd_printk(KERN_ERR "architecture does not support " - "24bit PCI busmaster DMA\n" + dev_err(card->dev, + "architecture does not support 24bit PCI busmaster DMA\n" ); err = -ENXIO; goto out_err; @@ -2560,7 +2463,7 @@ snd_azf3328_create(struct snd_card *card, if (request_irq(pci->irq, snd_azf3328_interrupt, IRQF_SHARED, KBUILD_MODNAME, chip)) { - snd_printk(KERN_ERR "unable to grab IRQ %d\n", pci->irq); + dev_err(card->dev, "unable to grab IRQ %d\n", pci->irq); err = -EBUSY; goto out_err; } @@ -2599,8 +2502,6 @@ snd_azf3328_create(struct snd_card *card, spin_unlock_irq(codec->lock); } - snd_card_set_dev(card, &pci->dev); - *rchip = chip; err = 0; @@ -2624,7 +2525,6 @@ snd_azf3328_probe(struct pci_dev *pci, const struct pci_device_id *pci_id) struct snd_opl3 *opl3; int err; - snd_azf3328_dbgcallenter(); if (dev >= SNDRV_CARDS) { err = -ENODEV; goto out; @@ -2635,7 +2535,8 @@ snd_azf3328_probe(struct pci_dev *pci, const struct pci_device_id *pci_id) goto out; } - err = snd_card_create(index[dev], id[dev], THIS_MODULE, 0, &card); + err = snd_card_new(&pci->dev, index[dev], id[dev], THIS_MODULE, + 0, &card); if (err < 0) goto out; @@ -2657,7 +2558,7 @@ snd_azf3328_probe(struct pci_dev *pci, const struct pci_device_id *pci_id) -1, &chip->rmidi ); if (err < 0) { - snd_printk(KERN_ERR "azf3328: no MPU-401 device at 0x%lx?\n", + dev_err(card->dev, "no MPU-401 device at 0x%lx?\n", chip->mpu_io ); goto out_err; @@ -2673,7 +2574,7 @@ snd_azf3328_probe(struct pci_dev *pci, const struct pci_device_id *pci_id) if (snd_opl3_create(card, chip->opl3_io, chip->opl3_io+2, OPL3_HW_AUTO, 1, &opl3) < 0) { - snd_printk(KERN_ERR "azf3328: no OPL3 device at 0x%lx-0x%lx?\n", + dev_err(card->dev, "no OPL3 device at 0x%lx-0x%lx?\n", chip->opl3_io, chip->opl3_io+2 ); } else { @@ -2695,12 +2596,15 @@ snd_azf3328_probe(struct pci_dev *pci, const struct pci_device_id *pci_id) goto out_err; #ifdef MODULE - printk(KERN_INFO -"azt3328: Sound driver for Aztech AZF3328-based soundcards such as PCI168.\n" -"azt3328: Hardware was completely undocumented, unfortunately.\n" -"azt3328: Feel free to contact andi AT lisas.de for bug reports etc.!\n" -"azt3328: User-scalable sequencer timer set to %dHz (1024000Hz / %d).\n", - 1024000 / seqtimer_scaling, seqtimer_scaling); + dev_info(card->dev, + "Sound driver for Aztech AZF3328-based soundcards such as PCI168.\n"); + dev_info(card->dev, + "Hardware was completely undocumented, unfortunately.\n"); + dev_info(card->dev, + "Feel free to contact andi AT lisas.de for bug reports etc.!\n"); + dev_info(card->dev, + "User-scalable sequencer timer set to %dHz (1024000Hz / %d).\n", + 1024000 / seqtimer_scaling, seqtimer_scaling); #endif snd_azf3328_gameport(chip, dev); @@ -2712,31 +2616,29 @@ snd_azf3328_probe(struct pci_dev *pci, const struct pci_device_id *pci_id) goto out; out_err: - snd_printk(KERN_ERR "azf3328: something failed, exiting\n"); + dev_err(card->dev, "something failed, exiting\n"); snd_card_free(card); out: - snd_azf3328_dbgcallleave(); return err; } static void snd_azf3328_remove(struct pci_dev *pci) { - snd_azf3328_dbgcallenter(); snd_card_free(pci_get_drvdata(pci)); - snd_azf3328_dbgcallleave(); } #ifdef CONFIG_PM_SLEEP static inline void -snd_azf3328_suspend_regs(unsigned long io_addr, unsigned count, u32 *saved_regs) +snd_azf3328_suspend_regs(const struct snd_azf3328 *chip, + unsigned long io_addr, unsigned count, u32 *saved_regs) { unsigned reg; for (reg = 0; reg < count; ++reg) { *saved_regs = inl(io_addr); - snd_azf3328_dbgpm("suspend: io 0x%04lx: 0x%08x\n", + dev_dbg(chip->card->dev, "suspend: io 0x%04lx: 0x%08x\n", io_addr, *saved_regs); ++saved_regs; io_addr += sizeof(*saved_regs); @@ -2744,7 +2646,8 @@ snd_azf3328_suspend_regs(unsigned long io_addr, unsigned count, u32 *saved_regs) } static inline void -snd_azf3328_resume_regs(const u32 *saved_regs, +snd_azf3328_resume_regs(const struct snd_azf3328 *chip, + const u32 *saved_regs, unsigned long io_addr, unsigned count ) @@ -2753,7 +2656,8 @@ snd_azf3328_resume_regs(const u32 *saved_regs, for (reg = 0; reg < count; ++reg) { outl(*saved_regs, io_addr); - snd_azf3328_dbgpm("resume: io 0x%04lx: 0x%08x --> 0x%08x\n", + dev_dbg(chip->card->dev, + "resume: io 0x%04lx: 0x%08x --> 0x%08x\n", io_addr, *saved_regs, inl(io_addr)); ++saved_regs; io_addr += sizeof(*saved_regs); @@ -2766,7 +2670,7 @@ snd_azf3328_suspend_ac97(struct snd_azf3328 *chip) #ifdef AZF_USE_AC97_LAYER snd_ac97_suspend(chip->ac97); #else - snd_azf3328_suspend_regs(chip->mixer_io, + snd_azf3328_suspend_regs(chip, chip->mixer_io, ARRAY_SIZE(chip->saved_regs_mixer), chip->saved_regs_mixer); /* make sure to disable master volume etc. to prevent looping sound */ @@ -2781,7 +2685,7 @@ snd_azf3328_resume_ac97(const struct snd_azf3328 *chip) #ifdef AZF_USE_AC97_LAYER snd_ac97_resume(chip->ac97); #else - snd_azf3328_resume_regs(chip->saved_regs_mixer, chip->mixer_io, + snd_azf3328_resume_regs(chip, chip->saved_regs_mixer, chip->mixer_io, ARRAY_SIZE(chip->saved_regs_mixer)); /* unfortunately with 32bit transfers, IDX_MIXER_PLAY_MASTER (0x02) @@ -2808,18 +2712,18 @@ snd_azf3328_suspend(struct device *dev) snd_azf3328_suspend_ac97(chip); - snd_azf3328_suspend_regs(chip->ctrl_io, + snd_azf3328_suspend_regs(chip, chip->ctrl_io, ARRAY_SIZE(chip->saved_regs_ctrl), chip->saved_regs_ctrl); /* manually store the one currently relevant write-only reg, too */ saved_regs_ctrl_u16 = (u16 *)chip->saved_regs_ctrl; saved_regs_ctrl_u16[IDX_IO_6AH / 2] = chip->shadow_reg_ctrl_6AH; - snd_azf3328_suspend_regs(chip->game_io, + snd_azf3328_suspend_regs(chip, chip->game_io, ARRAY_SIZE(chip->saved_regs_game), chip->saved_regs_game); - snd_azf3328_suspend_regs(chip->mpu_io, + snd_azf3328_suspend_regs(chip, chip->mpu_io, ARRAY_SIZE(chip->saved_regs_mpu), chip->saved_regs_mpu); - snd_azf3328_suspend_regs(chip->opl3_io, + snd_azf3328_suspend_regs(chip, chip->opl3_io, ARRAY_SIZE(chip->saved_regs_opl3), chip->saved_regs_opl3); pci_disable_device(pci); @@ -2838,23 +2742,22 @@ snd_azf3328_resume(struct device *dev) pci_set_power_state(pci, PCI_D0); pci_restore_state(pci); if (pci_enable_device(pci) < 0) { - printk(KERN_ERR "azt3328: pci_enable_device failed, " - "disabling device\n"); + dev_err(dev, "pci_enable_device failed, disabling device\n"); snd_card_disconnect(card); return -EIO; } pci_set_master(pci); - snd_azf3328_resume_regs(chip->saved_regs_game, chip->game_io, + snd_azf3328_resume_regs(chip, chip->saved_regs_game, chip->game_io, ARRAY_SIZE(chip->saved_regs_game)); - snd_azf3328_resume_regs(chip->saved_regs_mpu, chip->mpu_io, + snd_azf3328_resume_regs(chip, chip->saved_regs_mpu, chip->mpu_io, ARRAY_SIZE(chip->saved_regs_mpu)); - snd_azf3328_resume_regs(chip->saved_regs_opl3, chip->opl3_io, + snd_azf3328_resume_regs(chip, chip->saved_regs_opl3, chip->opl3_io, ARRAY_SIZE(chip->saved_regs_opl3)); snd_azf3328_resume_ac97(chip); - snd_azf3328_resume_regs(chip->saved_regs_ctrl, chip->ctrl_io, + snd_azf3328_resume_regs(chip, chip->saved_regs_ctrl, chip->ctrl_io, ARRAY_SIZE(chip->saved_regs_ctrl)); snd_power_change_state(card, SNDRV_CTL_POWER_D0); diff --git a/sound/pci/bt87x.c b/sound/pci/bt87x.c index 18802039497..8546711d12f 100644 --- a/sound/pci/bt87x.c +++ b/sound/pci/bt87x.c @@ -293,17 +293,23 @@ static void snd_bt87x_pci_error(struct snd_bt87x *chip, unsigned int status) PCI_STATUS_SIG_SYSTEM_ERROR | PCI_STATUS_DETECTED_PARITY; pci_write_config_word(chip->pci, PCI_STATUS, pci_status); if (pci_status != PCI_STATUS_DETECTED_PARITY) - snd_printk(KERN_ERR "Aieee - PCI error! status %#08x, PCI status %#04x\n", + dev_err(chip->card->dev, + "Aieee - PCI error! status %#08x, PCI status %#04x\n", status & ERROR_INTERRUPTS, pci_status); else { - snd_printk(KERN_ERR "Aieee - PCI parity error detected!\n"); + dev_err(chip->card->dev, + "Aieee - PCI parity error detected!\n"); /* error 'handling' similar to aic7xxx_pci.c: */ chip->pci_parity_errors++; if (chip->pci_parity_errors > 20) { - snd_printk(KERN_ERR "Too many PCI parity errors observed.\n"); - snd_printk(KERN_ERR "Some device on this bus is generating bad parity.\n"); - snd_printk(KERN_ERR "This is an error *observed by*, not *generated by*, this card.\n"); - snd_printk(KERN_ERR "PCI parity error checking has been disabled.\n"); + dev_err(chip->card->dev, + "Too many PCI parity errors observed.\n"); + dev_err(chip->card->dev, + "Some device on this bus is generating bad parity.\n"); + dev_err(chip->card->dev, + "This is an error *observed by*, not *generated by*, this card.\n"); + dev_err(chip->card->dev, + "PCI parity error checking has been disabled.\n"); chip->interrupt_mask &= ~(INT_PPERR | INT_RIPERR); snd_bt87x_writel(chip, REG_INT_MASK, chip->interrupt_mask); } @@ -323,9 +329,11 @@ static irqreturn_t snd_bt87x_interrupt(int irq, void *dev_id) if (irq_status & ERROR_INTERRUPTS) { if (irq_status & (INT_FBUS | INT_FTRGT)) - snd_printk(KERN_WARNING "FIFO overrun, status %#08x\n", status); + dev_warn(chip->card->dev, + "FIFO overrun, status %#08x\n", status); if (irq_status & INT_OCERR) - snd_printk(KERN_ERR "internal RISC error, status %#08x\n", status); + dev_err(chip->card->dev, + "internal RISC error, status %#08x\n", status); if (irq_status & (INT_PPERR | INT_RIPERR | INT_PABORT)) snd_bt87x_pci_error(chip, irq_status); } @@ -747,7 +755,7 @@ static int snd_bt87x_create(struct snd_card *card, } chip->mmio = pci_ioremap_bar(pci, 0); if (!chip->mmio) { - snd_printk(KERN_ERR "cannot remap io memory\n"); + dev_err(card->dev, "cannot remap io memory\n"); err = -ENOMEM; goto fail; } @@ -762,7 +770,7 @@ static int snd_bt87x_create(struct snd_card *card, err = request_irq(pci->irq, snd_bt87x_interrupt, IRQF_SHARED, KBUILD_MODNAME, chip); if (err < 0) { - snd_printk(KERN_ERR "cannot grab irq %d\n", pci->irq); + dev_err(card->dev, "cannot grab irq %d\n", pci->irq); goto fail; } chip->irq = pci->irq; @@ -773,7 +781,6 @@ static int snd_bt87x_create(struct snd_card *card, if (err < 0) goto fail; - snd_card_set_dev(card, &pci->dev); *rchip = chip; return 0; @@ -851,14 +858,15 @@ static int snd_bt87x_detect_card(struct pci_dev *pci) for (i = 0; i < ARRAY_SIZE(blacklist); ++i) if (blacklist[i].subvendor == pci->subsystem_vendor && blacklist[i].subdevice == pci->subsystem_device) { - snd_printdd(KERN_INFO "card %#04x-%#04x:%#04x has no audio\n", + dev_dbg(&pci->dev, + "card %#04x-%#04x:%#04x has no audio\n", pci->device, pci->subsystem_vendor, pci->subsystem_device); return -EBUSY; } - snd_printk(KERN_INFO "unknown card %#04x-%#04x:%#04x\n", + dev_info(&pci->dev, "unknown card %#04x-%#04x:%#04x\n", pci->device, pci->subsystem_vendor, pci->subsystem_device); - snd_printk(KERN_DEBUG "please mail id, board name, and, " + dev_info(&pci->dev, "please mail id, board name, and, " "if it works, the correct digital_rate option to " "<alsa-devel@alsa-project.org>\n"); return SND_BT87X_BOARD_UNKNOWN; @@ -888,7 +896,8 @@ static int snd_bt87x_probe(struct pci_dev *pci, return -ENOENT; } - err = snd_card_create(index[dev], id[dev], THIS_MODULE, 0, &card); + err = snd_card_new(&pci->dev, index[dev], id[dev], THIS_MODULE, + 0, &card); if (err < 0) return err; @@ -925,7 +934,7 @@ static int snd_bt87x_probe(struct pci_dev *pci, if (err < 0) goto _error; } - snd_printk(KERN_INFO "bt87x%d: Using board %d, %sanalog, %sdigital " + dev_info(card->dev, "bt87x%d: Using board %d, %sanalog, %sdigital " "(rate %d Hz)\n", dev, boardid, chip->board.no_analog ? "no " : "", chip->board.no_digital ? "no " : "", chip->board.dig_rate); diff --git a/sound/pci/ca0106/ca0106_main.c b/sound/pci/ca0106/ca0106_main.c index f4db5587e86..f94cc6e97d4 100644 --- a/sound/pci/ca0106/ca0106_main.c +++ b/sound/pci/ca0106/ca0106_main.c @@ -417,13 +417,13 @@ int snd_ca0106_i2c_write(struct snd_ca0106 *emu, int status; int retry; if ((reg > 0x7f) || (value > 0x1ff)) { - snd_printk(KERN_ERR "i2c_write: invalid values.\n"); + dev_err(emu->card->dev, "i2c_write: invalid values.\n"); return -EINVAL; } tmp = reg << 25 | value << 16; /* - snd_printk(KERN_DEBUG "I2C-write:reg=0x%x, value=0x%x\n", reg, value); + dev_dbg(emu->card->dev, "I2C-write:reg=0x%x, value=0x%x\n", reg, value); */ /* Not sure what this I2C channel controls. */ /* snd_ca0106_ptr_write(emu, I2C_D0, 0, tmp); */ @@ -442,7 +442,7 @@ int snd_ca0106_i2c_write(struct snd_ca0106 *emu, /* Wait till the transaction ends */ while (1) { status = snd_ca0106_ptr_read(emu, I2C_A, 0); - /*snd_printk(KERN_DEBUG "I2C:status=0x%x\n", status);*/ + /*dev_dbg(emu->card->dev, "I2C:status=0x%x\n", status);*/ timeout++; if ((status & I2C_A_ADC_START) == 0) break; @@ -456,7 +456,7 @@ int snd_ca0106_i2c_write(struct snd_ca0106 *emu, } if (retry == 10) { - snd_printk(KERN_ERR "Writing to ADC failed!\n"); + dev_err(emu->card->dev, "Writing to ADC failed!\n"); return -EINVAL; } @@ -516,7 +516,8 @@ static void restore_spdif_bits(struct snd_ca0106 *chip, int idx) } } -static int snd_ca0106_channel_dac(struct snd_ca0106_details *details, +static int snd_ca0106_channel_dac(struct snd_ca0106 *chip, + struct snd_ca0106_details *details, int channel_id) { switch (channel_id) { @@ -529,7 +530,7 @@ static int snd_ca0106_channel_dac(struct snd_ca0106_details *details, case PCM_UNKNOWN_CHANNEL: return (details->spi_dac & 0x000f) >> (4 * 0); default: - snd_printk(KERN_DEBUG "ca0106: unknown channel_id %d\n", + dev_dbg(chip->card->dev, "ca0106: unknown channel_id %d\n", channel_id); } return 0; @@ -539,7 +540,7 @@ static int snd_ca0106_pcm_power_dac(struct snd_ca0106 *chip, int channel_id, int power) { if (chip->details->spi_dac) { - const int dac = snd_ca0106_channel_dac(chip->details, + const int dac = snd_ca0106_channel_dac(chip, chip->details, channel_id); const int reg = spi_dacd_reg[dac]; const int bit = spi_dacd_bit[dac]; @@ -583,7 +584,7 @@ static int snd_ca0106_pcm_open_playback_channel(struct snd_pcm_substream *substr channel->use = 1; /* - printk(KERN_DEBUG "open:channel_id=%d, chip=%p, channel=%p\n", + dev_dbg(chip->card->dev, "open:channel_id=%d, chip=%p, channel=%p\n", channel_id, chip, channel); */ //channel->interrupt = snd_ca0106_pcm_channel_interrupt; @@ -660,7 +661,8 @@ static int snd_ca0106_pcm_open_capture_channel(struct snd_pcm_substream *substre epcm = kzalloc(sizeof(*epcm), GFP_KERNEL); if (epcm == NULL) { - snd_printk(KERN_ERR "open_capture_channel: failed epcm alloc\n"); + dev_err(chip->card->dev, + "open_capture_channel: failed epcm alloc\n"); return -ENOMEM; } epcm->emu = chip; @@ -677,7 +679,7 @@ static int snd_ca0106_pcm_open_capture_channel(struct snd_pcm_substream *substre channel->use = 1; /* - printk(KERN_DEBUG "open:channel_id=%d, chip=%p, channel=%p\n", + dev_dbg(chip->card->dev, "open:channel_id=%d, chip=%p, channel=%p\n", channel_id, chip, channel); */ //channel->interrupt = snd_ca0106_pcm_channel_interrupt; @@ -771,7 +773,7 @@ static int snd_ca0106_pcm_prepare_playback(struct snd_pcm_substream *substream) int i; #if 0 /* debug */ - snd_printk(KERN_DEBUG + dev_dbg(emu->card->dev, "prepare:channel_number=%d, rate=%d, format=0x%x, " "channels=%d, buffer_size=%ld, period_size=%ld, " "periods=%u, frames_to_bytes=%d\n", @@ -779,9 +781,11 @@ static int snd_ca0106_pcm_prepare_playback(struct snd_pcm_substream *substream) runtime->channels, runtime->buffer_size, runtime->period_size, runtime->periods, frames_to_bytes(runtime, 1)); - snd_printk(KERN_DEBUG "dma_addr=%x, dma_area=%p, table_base=%p\n", + dev_dbg(emu->card->dev, + "dma_addr=%x, dma_area=%p, table_base=%p\n", runtime->dma_addr, runtime->dma_area, table_base); - snd_printk(KERN_DEBUG "dma_addr=%x, dma_area=%p, dma_bytes(size)=%x\n", + dev_dbg(emu->card->dev, + "dma_addr=%x, dma_area=%p, dma_bytes(size)=%x\n", emu->buffer.addr, emu->buffer.area, emu->buffer.bytes); #endif /* debug */ /* Rate can be set per channel. */ @@ -876,7 +880,7 @@ static int snd_ca0106_pcm_prepare_capture(struct snd_pcm_substream *substream) u32 reg71; #if 0 /* debug */ - snd_printk(KERN_DEBUG + dev_dbg(emu->card->dev, "prepare:channel_number=%d, rate=%d, format=0x%x, " "channels=%d, buffer_size=%ld, period_size=%ld, " "periods=%u, frames_to_bytes=%d\n", @@ -884,9 +888,11 @@ static int snd_ca0106_pcm_prepare_capture(struct snd_pcm_substream *substream) runtime->channels, runtime->buffer_size, runtime->period_size, runtime->periods, frames_to_bytes(runtime, 1)); - snd_printk(KERN_DEBUG "dma_addr=%x, dma_area=%p, table_base=%p\n", + dev_dbg(emu->card->dev, + "dma_addr=%x, dma_area=%p, table_base=%p\n", runtime->dma_addr, runtime->dma_area, table_base); - snd_printk(KERN_DEBUG "dma_addr=%x, dma_area=%p, dma_bytes(size)=%x\n", + dev_dbg(emu->card->dev, + "dma_addr=%x, dma_area=%p, dma_bytes(size)=%x\n", emu->buffer.addr, emu->buffer.area, emu->buffer.bytes); #endif /* debug */ /* reg71 controls ADC rate. */ @@ -934,7 +940,7 @@ static int snd_ca0106_pcm_prepare_capture(struct snd_pcm_substream *substream) /* - printk(KERN_DEBUG + dev_dbg(emu->card->dev, "prepare:channel_number=%d, rate=%d, format=0x%x, channels=%d, " "buffer_size=%ld, period_size=%ld, frames_to_bytes=%d\n", channel, runtime->rate, runtime->format, runtime->channels, @@ -982,13 +988,13 @@ static int snd_ca0106_pcm_trigger_playback(struct snd_pcm_substream *substream, runtime = s->runtime; epcm = runtime->private_data; channel = epcm->channel_id; - /* snd_printk(KERN_DEBUG "channel=%d\n", channel); */ + /* dev_dbg(emu->card->dev, "channel=%d\n", channel); */ epcm->running = running; basic |= (0x1 << channel); extended |= (0x10 << channel); snd_pcm_trigger_done(s, substream); } - /* snd_printk(KERN_DEBUG "basic=0x%x, extended=0x%x\n",basic, extended); */ + /* dev_dbg(emu->card->dev, "basic=0x%x, extended=0x%x\n",basic, extended); */ switch (cmd) { case SNDRV_PCM_TRIGGER_START: @@ -1070,7 +1076,7 @@ snd_ca0106_pcm_pointer_playback(struct snd_pcm_substream *substream) return ptr; prev_ptr = ptr; } while (--timeout); - snd_printk(KERN_WARNING "ca0106: unstable DMA pointer!\n"); + dev_warn(emu->card->dev, "ca0106: unstable DMA pointer!\n"); return 0; } @@ -1093,7 +1099,7 @@ snd_ca0106_pcm_pointer_capture(struct snd_pcm_substream *substream) if (ptr >= runtime->buffer_size) ptr -= runtime->buffer_size; /* - printk(KERN_DEBUG "ptr1 = 0x%lx, ptr2=0x%lx, ptr=0x%lx, " + dev_dbg(emu->card->dev, "ptr1 = 0x%lx, ptr2=0x%lx, ptr=0x%lx, " "buffer_size = 0x%x, period_size = 0x%x, bits=%d, rate=%d\n", ptr1, ptr2, ptr, (int)runtime->buffer_size, (int)runtime->period_size, (int)runtime->frame_bits, @@ -1284,9 +1290,9 @@ static irqreturn_t snd_ca0106_interrupt(int irq, void *dev_id) stat76 = snd_ca0106_ptr_read(chip, EXTENDED_INT, 0); /* - snd_printk(KERN_DEBUG "interrupt status = 0x%08x, stat76=0x%08x\n", + dev_dbg(emu->card->dev, "interrupt status = 0x%08x, stat76=0x%08x\n", status, stat76); - snd_printk(KERN_DEBUG "ptr=0x%08x\n", + dev_dbg(emu->card->dev, "ptr=0x%08x\n", snd_ca0106_ptr_read(chip, PLAYBACK_POINTER, 0)); */ mask = 0x11; /* 0x1 for one half, 0x10 for the other half period. */ @@ -1296,11 +1302,13 @@ static irqreturn_t snd_ca0106_interrupt(int irq, void *dev_id) /* FIXME: Select the correct substream for period elapsed */ if(pchannel->use) { snd_pcm_period_elapsed(pchannel->epcm->substream); - //printk(KERN_INFO "interrupt [%d] used\n", i); + /* dev_dbg(emu->card->dev, "interrupt [%d] used\n", i); */ } } - //printk(KERN_INFO "channel=%p\n",pchannel); - //printk(KERN_INFO "interrupt stat76[%d] = %08x, use=%d, channel=%d\n", i, stat76, pchannel->use, pchannel->number); + /* + dev_dbg(emu->card->dev, "channel=%p\n", pchannel); + dev_dbg(emu->card->dev, "interrupt stat76[%d] = %08x, use=%d, channel=%d\n", i, stat76, pchannel->use, pchannel->number); + */ mask <<= 1; } mask = 0x110000; /* 0x1 for one half, 0x10 for the other half period. */ @@ -1310,11 +1318,13 @@ static irqreturn_t snd_ca0106_interrupt(int irq, void *dev_id) /* FIXME: Select the correct substream for period elapsed */ if(pchannel->use) { snd_pcm_period_elapsed(pchannel->epcm->substream); - //printk(KERN_INFO "interrupt [%d] used\n", i); + /* dev_dbg(emu->card->dev, "interrupt [%d] used\n", i); */ } } - //printk(KERN_INFO "channel=%p\n",pchannel); - //printk(KERN_INFO "interrupt stat76[%d] = %08x, use=%d, channel=%d\n", i, stat76, pchannel->use, pchannel->number); + /* + dev_dbg(emu->card->dev, "channel=%p\n", pchannel); + dev_dbg(emu->card->dev, "interrupt stat76[%d] = %08x, use=%d, channel=%d\n", i, stat76, pchannel->use, pchannel->number); + */ mask <<= 1; } @@ -1603,7 +1613,7 @@ static void ca0106_init_chip(struct snd_ca0106 *chip, int resume) int size, n; size = ARRAY_SIZE(i2c_adc_init); - /* snd_printk(KERN_DEBUG "I2C:array size=0x%x\n", size); */ + /* dev_dbg(emu->card->dev, "I2C:array size=0x%x\n", size); */ for (n = 0; n < size; n++) snd_ca0106_i2c_write(chip, i2c_adc_init[n][0], i2c_adc_init[n][1]); @@ -1668,7 +1678,7 @@ static int snd_ca0106_create(int dev, struct snd_card *card, 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 32bit mask DMA\n"); + dev_err(card->dev, "error to set 32bit mask DMA\n"); pci_disable_device(pci); return -ENXIO; } @@ -1689,14 +1699,14 @@ static int snd_ca0106_create(int dev, struct snd_card *card, chip->res_port = request_region(chip->port, 0x20, "snd_ca0106"); if (!chip->res_port) { snd_ca0106_free(chip); - printk(KERN_ERR "cannot allocate the port\n"); + dev_err(card->dev, "cannot allocate the port\n"); return -EBUSY; } if (request_irq(pci->irq, snd_ca0106_interrupt, IRQF_SHARED, KBUILD_MODNAME, chip)) { snd_ca0106_free(chip); - printk(KERN_ERR "cannot grab irq\n"); + dev_err(card->dev, "cannot grab irq\n"); return -EBUSY; } chip->irq = pci->irq; @@ -1712,7 +1722,7 @@ static int snd_ca0106_create(int dev, struct snd_card *card, /* read serial */ pci_read_config_dword(pci, PCI_SUBSYSTEM_VENDOR_ID, &chip->serial); pci_read_config_word(pci, PCI_SUBSYSTEM_ID, &chip->model); - printk(KERN_INFO "snd-ca0106: Model %04x Rev %08x Serial %08x\n", + dev_info(card->dev, "Model %04x Rev %08x Serial %08x\n", chip->model, pci->revision, chip->serial); strcpy(card->driver, "CA0106"); strcpy(card->shortname, "CA0106"); @@ -1726,7 +1736,7 @@ static int snd_ca0106_create(int dev, struct snd_card *card, } chip->details = c; if (subsystem[dev]) { - printk(KERN_INFO "snd-ca0106: Sound card name=%s, " + dev_info(card->dev, "Sound card name=%s, " "subsystem=0x%x. Forced to subsystem=0x%x\n", c->name, chip->serial, subsystem[dev]); } @@ -1843,7 +1853,8 @@ static int snd_ca0106_probe(struct pci_dev *pci, return -ENOENT; } - err = snd_card_create(index[dev], id[dev], THIS_MODULE, 0, &card); + err = snd_card_new(&pci->dev, index[dev], id[dev], THIS_MODULE, + 0, &card); if (err < 0) return err; @@ -1868,18 +1879,16 @@ static int snd_ca0106_probe(struct pci_dev *pci, if (err < 0) goto error; - snd_printdd("ca0106: probe for MIDI channel A ..."); + dev_dbg(card->dev, "probe for MIDI channel A ..."); err = snd_ca0106_midi(chip, CA0106_MIDI_CHAN_A); if (err < 0) goto error; - snd_printdd(" done.\n"); + dev_dbg(card->dev, " done.\n"); #ifdef CONFIG_PROC_FS snd_ca0106_proc_init(chip); #endif - snd_card_set_dev(card, &pci->dev); - err = snd_card_register(card); if (err < 0) goto error; diff --git a/sound/pci/ca0106/ca_midi.c b/sound/pci/ca0106/ca_midi.c index 8bbdf265d11..b91c7f6d19f 100644 --- a/sound/pci/ca0106/ca_midi.c +++ b/sound/pci/ca0106/ca_midi.c @@ -46,7 +46,7 @@ static void ca_midi_clear_rx(struct snd_ca_midi *midi) ca_midi_read_data(midi); #ifdef CONFIG_SND_DEBUG if (timeout <= 0) - snd_printk(KERN_ERR "ca_midi_clear_rx: timeout (status = 0x%x)\n", + pr_err("ca_midi_clear_rx: timeout (status = 0x%x)\n", ca_midi_read_stat(midi)); #endif } @@ -113,7 +113,7 @@ static void ca_midi_cmd(struct snd_ca_midi *midi, unsigned char cmd, int ack) } spin_unlock_irqrestore(&midi->input_lock, flags); if (!ok) - snd_printk(KERN_ERR "ca_midi_cmd: 0x%x failed at 0x%x (status = 0x%x, data = 0x%x)!!!\n", + pr_err("ca_midi_cmd: 0x%x failed at 0x%x (status = 0x%x, data = 0x%x)!!!\n", cmd, midi->get_dev_id_port(midi->dev_id), ca_midi_read_stat(midi), diff --git a/sound/pci/cmipci.c b/sound/pci/cmipci.c index 2755ec5bcc2..12c318e175f 100644 --- a/sound/pci/cmipci.c +++ b/sound/pci/cmipci.c @@ -796,7 +796,7 @@ static int snd_cmipci_pcm_prepare(struct cmipci *cm, struct cmipci_pcm *rec, if (runtime->channels > 1) rec->fmt |= 0x01; if (rec->is_dac && set_dac_channels(cm, rec, runtime->channels) < 0) { - snd_printd("cannot set dac channels\n"); + dev_dbg(cm->card->dev, "cannot set dac channels\n"); return -EINVAL; } @@ -827,7 +827,7 @@ static int snd_cmipci_pcm_prepare(struct cmipci *cm, struct cmipci_pcm *rec, else cm->ctrl |= val; snd_cmipci_write(cm, CM_REG_FUNCTRL0, cm->ctrl); - //snd_printd("cmipci: functrl0 = %08x\n", cm->ctrl); + /* dev_dbg(cm->card->dev, "functrl0 = %08x\n", cm->ctrl); */ /* set sample rate */ freq = 0; @@ -850,7 +850,7 @@ static int snd_cmipci_pcm_prepare(struct cmipci *cm, struct cmipci_pcm *rec, val |= (freq << CM_ASFC_SHIFT) & CM_ASFC_MASK; } snd_cmipci_write(cm, CM_REG_FUNCTRL1, val); - //snd_printd("cmipci: functrl1 = %08x\n", val); + dev_dbg(cm->card->dev, "functrl1 = %08x\n", val); /* set format */ val = snd_cmipci_read(cm, CM_REG_CHFORMAT); @@ -866,7 +866,7 @@ static int snd_cmipci_pcm_prepare(struct cmipci *cm, struct cmipci_pcm *rec, val |= freq_ext << (rec->ch * 2); } snd_cmipci_write(cm, CM_REG_CHFORMAT, val); - //snd_printd("cmipci: chformat = %08x\n", val); + dev_dbg(cm->card->dev, "chformat = %08x\n", val); if (!rec->is_dac && cm->chip_version) { if (runtime->rate > 44100) @@ -904,7 +904,7 @@ static int snd_cmipci_pcm_trigger(struct cmipci *cm, struct cmipci_pcm *rec, cm->ctrl |= chen; /* enable channel */ snd_cmipci_write(cm, CM_REG_FUNCTRL0, cm->ctrl); - //snd_printd("cmipci: functrl0 = %08x\n", cm->ctrl); + dev_dbg(cm->card->dev, "functrl0 = %08x\n", cm->ctrl); break; case SNDRV_PCM_TRIGGER_STOP: rec->running = 0; @@ -952,7 +952,7 @@ static snd_pcm_uframes_t snd_cmipci_pcm_pointer(struct cmipci *cm, struct cmipci if (rem < rec->dma_size) goto ok; } - printk(KERN_ERR "cmipci: invalid PCM pointer: %#x\n", rem); + dev_err(cm->card->dev, "invalid PCM pointer: %#x\n", rem); return SNDRV_PCM_POS_XRUN; ok: ptr = (rec->dma_size - (rem + 1)) >> rec->shift; @@ -2889,13 +2889,13 @@ static int snd_cmipci_create_gameport(struct cmipci *cm, int dev) } if (!r) { - printk(KERN_WARNING "cmipci: cannot reserve joystick ports\n"); + dev_warn(cm->card->dev, "cannot reserve joystick ports\n"); return -EBUSY; } cm->gameport = gp = gameport_allocate_port(); if (!gp) { - printk(KERN_ERR "cmipci: cannot allocate memory for gameport\n"); + dev_err(cm->card->dev, "cannot allocate memory for gameport\n"); release_and_free_resource(r); return -ENOMEM; } @@ -2995,13 +2995,14 @@ static int snd_cmipci_create_fm(struct cmipci *cm, long fm_port) if (snd_opl3_create(cm->card, iosynth, iosynth + 2, OPL3_HW_OPL3, 0, &opl3) < 0) { - printk(KERN_ERR "cmipci: no OPL device at %#lx, " - "skipping...\n", iosynth); + dev_err(cm->card->dev, + "no OPL device at %#lx, skipping...\n", + iosynth); goto disable_fm; } } if ((err = snd_opl3_hwdep_new(opl3, 0, 1, NULL)) < 0) { - printk(KERN_ERR "cmipci: cannot create OPL3 hwdep\n"); + dev_err(cm->card->dev, "cannot create OPL3 hwdep\n"); return err; } return 0; @@ -3060,7 +3061,7 @@ static int snd_cmipci_create(struct snd_card *card, struct pci_dev *pci, if (request_irq(pci->irq, snd_cmipci_interrupt, IRQF_SHARED, KBUILD_MODNAME, cm)) { - snd_printk(KERN_ERR "unable to grab IRQ %d\n", pci->irq); + dev_err(card->dev, "unable to grab IRQ %d\n", pci->irq); snd_cmipci_free(cm); return -EBUSY; } @@ -3192,8 +3193,9 @@ static int snd_cmipci_create(struct snd_card *card, struct pci_dev *pci, /* enable UART */ snd_cmipci_set_bit(cm, CM_REG_FUNCTRL1, CM_UART_EN); if (inb(iomidi + 1) == 0xff) { - snd_printk(KERN_ERR "cannot enable MPU-401 port" - " at %#lx\n", iomidi); + dev_err(cm->card->dev, + "cannot enable MPU-401 port at %#lx\n", + iomidi); snd_cmipci_clear_bit(cm, CM_REG_FUNCTRL1, CM_UART_EN); iomidi = 0; @@ -3237,7 +3239,8 @@ static int snd_cmipci_create(struct snd_card *card, struct pci_dev *pci, MPU401_INFO_INTEGRATED : 0) | MPU401_INFO_IRQ_HOOK, -1, &cm->rmidi)) < 0) { - printk(KERN_ERR "cmipci: no UART401 device at 0x%lx\n", iomidi); + dev_err(cm->card->dev, + "no UART401 device at 0x%lx\n", iomidi); } } @@ -3254,8 +3257,6 @@ static int snd_cmipci_create(struct snd_card *card, struct pci_dev *pci, if (snd_cmipci_create_gameport(cm, dev) < 0) snd_cmipci_clear_bit(cm, CM_REG_FUNCTRL1, CM_JYSTK_EN); - snd_card_set_dev(card, &pci->dev); - *rcmipci = cm; return 0; } @@ -3280,7 +3281,8 @@ static int snd_cmipci_probe(struct pci_dev *pci, return -ENOENT; } - err = snd_card_create(index[dev], id[dev], THIS_MODULE, 0, &card); + err = snd_card_new(&pci->dev, index[dev], id[dev], THIS_MODULE, + 0, &card); if (err < 0) return err; @@ -3381,8 +3383,7 @@ static int snd_cmipci_resume(struct device *dev) pci_set_power_state(pci, PCI_D0); pci_restore_state(pci); if (pci_enable_device(pci) < 0) { - printk(KERN_ERR "cmipci: pci_enable_device failed, " - "disabling device\n"); + dev_err(dev, "pci_enable_device failed, disabling device\n"); snd_card_disconnect(card); return -EIO; } diff --git a/sound/pci/cs4281.c b/sound/pci/cs4281.c index 1dc793e742d..43d1f912c64 100644 --- a/sound/pci/cs4281.c +++ b/sound/pci/cs4281.c @@ -564,7 +564,8 @@ static void snd_cs4281_ac97_write(struct snd_ac97 *ac97, return; } } - snd_printk(KERN_ERR "AC'97 write problem, reg = 0x%x, val = 0x%x\n", reg, val); + dev_err(chip->card->dev, + "AC'97 write problem, reg = 0x%x, val = 0x%x\n", reg, val); } static unsigned short snd_cs4281_ac97_read(struct snd_ac97 *ac97, @@ -624,7 +625,8 @@ static unsigned short snd_cs4281_ac97_read(struct snd_ac97 *ac97, goto __ok1; } - snd_printk(KERN_ERR "AC'97 read problem (ACCTL_DCV), reg = 0x%x\n", reg); + dev_err(chip->card->dev, + "AC'97 read problem (ACCTL_DCV), reg = 0x%x\n", reg); result = 0xffff; goto __end; @@ -643,7 +645,8 @@ static unsigned short snd_cs4281_ac97_read(struct snd_ac97 *ac97, udelay(10); } - snd_printk(KERN_ERR "AC'97 read problem (ACSTS_VSTS), reg = 0x%x\n", reg); + dev_err(chip->card->dev, + "AC'97 read problem (ACSTS_VSTS), reg = 0x%x\n", reg); result = 0xffff; goto __end; @@ -835,8 +838,9 @@ static snd_pcm_uframes_t snd_cs4281_pointer(struct snd_pcm_substream *substream) struct cs4281 *chip = snd_pcm_substream_chip(substream); /* - printk(KERN_DEBUG "DCC = 0x%x, buffer_size = 0x%x, jiffies = %li\n", - snd_cs4281_peekBA0(chip, dma->regDCC), runtime->buffer_size, + dev_dbg(chip->card->dev, + "DCC = 0x%x, buffer_size = 0x%x, jiffies = %li\n", + snd_cs4281_peekBA0(chip, dma->regDCC), runtime->buffer_size, jiffies); */ return runtime->buffer_size - @@ -1265,7 +1269,8 @@ static int snd_cs4281_create_gameport(struct cs4281 *chip) chip->gameport = gp = gameport_allocate_port(); if (!gp) { - printk(KERN_ERR "cs4281: cannot allocate memory for gameport\n"); + dev_err(chip->card->dev, + "cannot allocate memory for gameport\n"); return -ENOMEM; } @@ -1361,7 +1366,7 @@ static int snd_cs4281_create(struct snd_card *card, chip->irq = -1; pci_set_master(pci); if (dual_codec < 0 || dual_codec > 3) { - snd_printk(KERN_ERR "invalid dual_codec option %d\n", dual_codec); + dev_err(card->dev, "invalid dual_codec option %d\n", dual_codec); dual_codec = 0; } chip->dual_codec = dual_codec; @@ -1383,7 +1388,7 @@ static int snd_cs4281_create(struct snd_card *card, if (request_irq(pci->irq, snd_cs4281_interrupt, IRQF_SHARED, KBUILD_MODNAME, chip)) { - snd_printk(KERN_ERR "unable to grab IRQ %d\n", pci->irq); + dev_err(card->dev, "unable to grab IRQ %d\n", pci->irq); snd_cs4281_free(chip); return -ENOMEM; } @@ -1402,8 +1407,6 @@ static int snd_cs4281_create(struct snd_card *card, snd_cs4281_proc_init(chip); - snd_card_set_dev(card, &pci->dev); - *rchip = chip; return 0; } @@ -1425,7 +1428,8 @@ static int snd_cs4281_chip_init(struct cs4281 *chip) snd_cs4281_pokeBA0(chip, BA0_CFLR, BA0_CFLR_DEFAULT); tmp = snd_cs4281_peekBA0(chip, BA0_CFLR); if (tmp != BA0_CFLR_DEFAULT) { - snd_printk(KERN_ERR "CFLR setup failed (0x%x)\n", tmp); + dev_err(chip->card->dev, + "CFLR setup failed (0x%x)\n", tmp); return -EIO; } } @@ -1436,11 +1440,13 @@ static int snd_cs4281_chip_init(struct cs4281 *chip) snd_cs4281_pokeBA0(chip, BA0_CWPR, 0x4281); if ((tmp = snd_cs4281_peekBA0(chip, BA0_SERC1)) != (BA0_SERC1_SO1EN | BA0_SERC1_AC97)) { - snd_printk(KERN_ERR "SERC1 AC'97 check failed (0x%x)\n", tmp); + dev_err(chip->card->dev, + "SERC1 AC'97 check failed (0x%x)\n", tmp); return -EIO; } if ((tmp = snd_cs4281_peekBA0(chip, BA0_SERC2)) != (BA0_SERC2_SI1EN | BA0_SERC2_AC97)) { - snd_printk(KERN_ERR "SERC2 AC'97 check failed (0x%x)\n", tmp); + dev_err(chip->card->dev, + "SERC2 AC'97 check failed (0x%x)\n", tmp); return -EIO; } @@ -1502,7 +1508,7 @@ static int snd_cs4281_chip_init(struct cs4281 *chip) schedule_timeout_uninterruptible(1); } while (time_after_eq(end_time, jiffies)); - snd_printk(KERN_ERR "DLLRDY not seen\n"); + dev_err(chip->card->dev, "DLLRDY not seen\n"); return -EIO; __ok0: @@ -1528,7 +1534,9 @@ static int snd_cs4281_chip_init(struct cs4281 *chip) schedule_timeout_uninterruptible(1); } while (time_after_eq(end_time, jiffies)); - snd_printk(KERN_ERR "never read codec ready from AC'97 (0x%x)\n", snd_cs4281_peekBA0(chip, BA0_ACSTS)); + dev_err(chip->card->dev, + "never read codec ready from AC'97 (0x%x)\n", + snd_cs4281_peekBA0(chip, BA0_ACSTS)); return -EIO; __ok1: @@ -1539,7 +1547,8 @@ static int snd_cs4281_chip_init(struct cs4281 *chip) goto __codec2_ok; schedule_timeout_uninterruptible(1); } while (time_after_eq(end_time, jiffies)); - snd_printk(KERN_INFO "secondary codec doesn't respond. disable it...\n"); + dev_info(chip->card->dev, + "secondary codec doesn't respond. disable it...\n"); chip->dual_codec = 0; __codec2_ok: ; } @@ -1569,7 +1578,7 @@ static int snd_cs4281_chip_init(struct cs4281 *chip) if (--retry_count > 0) goto __retry; - snd_printk(KERN_ERR "never read ISV3 and ISV4 from AC'97\n"); + dev_err(chip->card->dev, "never read ISV3 and ISV4 from AC'97\n"); return -EIO; __ok2: @@ -1917,7 +1926,8 @@ static int snd_cs4281_probe(struct pci_dev *pci, return -ENOENT; } - err = snd_card_create(index[dev], id[dev], THIS_MODULE, 0, &card); + err = snd_card_new(&pci->dev, index[dev], id[dev], THIS_MODULE, + 0, &card); if (err < 0) return err; @@ -2055,8 +2065,7 @@ static int cs4281_resume(struct device *dev) pci_set_power_state(pci, PCI_D0); pci_restore_state(pci); if (pci_enable_device(pci) < 0) { - printk(KERN_ERR "cs4281: pci_enable_device failed, " - "disabling device\n"); + dev_err(dev, "pci_enable_device failed, disabling device\n"); snd_card_disconnect(card); return -EIO; } diff --git a/sound/pci/cs46xx/cs46xx.c b/sound/pci/cs46xx/cs46xx.c index b03498325d6..af0eacbc8bd 100644 --- a/sound/pci/cs46xx/cs46xx.c +++ b/sound/pci/cs46xx/cs46xx.c @@ -88,7 +88,8 @@ static int snd_card_cs46xx_probe(struct pci_dev *pci, return -ENOENT; } - err = snd_card_create(index[dev], id[dev], THIS_MODULE, 0, &card); + err = snd_card_new(&pci->dev, index[dev], id[dev], THIS_MODULE, + 0, &card); if (err < 0) return err; if ((err = snd_cs46xx_create(card, pci, diff --git a/sound/pci/cs46xx/cs46xx_lib.c b/sound/pci/cs46xx/cs46xx_lib.c index 062398ec533..32b44f25b5c 100644 --- a/sound/pci/cs46xx/cs46xx_lib.c +++ b/sound/pci/cs46xx/cs46xx_lib.c @@ -116,7 +116,7 @@ static unsigned short snd_cs46xx_codec_read(struct snd_cs46xx *chip, tmp = snd_cs46xx_peekBA0(chip, BA0_ACCTL); if ((tmp & ACCTL_VFRM) == 0) { - snd_printk(KERN_WARNING "cs46xx: ACCTL_VFRM not set 0x%x\n",tmp); + dev_warn(chip->card->dev, "ACCTL_VFRM not set 0x%x\n", tmp); snd_cs46xx_pokeBA0(chip, BA0_ACCTL, (tmp & (~ACCTL_ESYN)) | ACCTL_VFRM ); msleep(50); tmp = snd_cs46xx_peekBA0(chip, BA0_ACCTL + offset); @@ -168,7 +168,8 @@ static unsigned short snd_cs46xx_codec_read(struct snd_cs46xx *chip, goto ok1; } - snd_printk(KERN_ERR "AC'97 read problem (ACCTL_DCV), reg = 0x%x\n", reg); + dev_err(chip->card->dev, + "AC'97 read problem (ACCTL_DCV), reg = 0x%x\n", reg); result = 0xffff; goto end; @@ -187,7 +188,9 @@ static unsigned short snd_cs46xx_codec_read(struct snd_cs46xx *chip, udelay(10); } - snd_printk(KERN_ERR "AC'97 read problem (ACSTS_VSTS), codec_index %d, reg = 0x%x\n", codec_index, reg); + dev_err(chip->card->dev, + "AC'97 read problem (ACSTS_VSTS), codec_index %d, reg = 0x%x\n", + codec_index, reg); result = 0xffff; goto end; @@ -197,7 +200,8 @@ static unsigned short snd_cs46xx_codec_read(struct snd_cs46xx *chip, * ACSDA = Status Data Register = 474h */ #if 0 - printk(KERN_DEBUG "e) reg = 0x%x, val = 0x%x, BA0_ACCAD = 0x%x\n", reg, + dev_dbg(chip->card->dev, + "e) reg = 0x%x, val = 0x%x, BA0_ACCAD = 0x%x\n", reg, snd_cs46xx_peekBA0(chip, BA0_ACSDA), snd_cs46xx_peekBA0(chip, BA0_ACCAD)); #endif @@ -286,7 +290,9 @@ static void snd_cs46xx_codec_write(struct snd_cs46xx *chip, goto end; } } - snd_printk(KERN_ERR "AC'97 write problem, codec_index = %d, reg = 0x%x, val = 0x%x\n", codec_index, reg, val); + dev_err(chip->card->dev, + "AC'97 write problem, codec_index = %d, reg = 0x%x, val = 0x%x\n", + codec_index, reg, val); end: chip->active_ctrl(chip, -1); } @@ -608,8 +614,8 @@ static int cs46xx_wait_for_fifo(struct snd_cs46xx * chip,int retry_timeout) } if(status & SERBST_WBSY) { - snd_printk(KERN_ERR "cs46xx: failure waiting for " - "FIFO command to complete\n"); + dev_err(chip->card->dev, + "failure waiting for FIFO command to complete\n"); return -EINVAL; } @@ -646,7 +652,9 @@ static void snd_cs46xx_clear_serial_FIFOs(struct snd_cs46xx *chip) * Make sure the previous FIFO write operation has completed. */ if (cs46xx_wait_for_fifo(chip,1)) { - snd_printdd ("failed waiting for FIFO at addr (%02X)\n",idx); + dev_dbg(chip->card->dev, + "failed waiting for FIFO at addr (%02X)\n", + idx); if (powerdown) snd_cs46xx_pokeBA0(chip, BA0_CLKCR1, tmp); @@ -694,7 +702,7 @@ static void snd_cs46xx_proc_start(struct snd_cs46xx *chip) } if (snd_cs46xx_peek(chip, BA1_SPCR) & SPCR_RUNFR) - snd_printk(KERN_ERR "SPCR_RUNFR never reset\n"); + dev_err(chip->card->dev, "SPCR_RUNFR never reset\n"); } static void snd_cs46xx_proc_stop(struct snd_cs46xx *chip) @@ -1054,7 +1062,8 @@ static int _cs46xx_adjust_sample_rate (struct snd_cs46xx *chip, struct snd_cs46x cpcm->pcm_channel = cs46xx_dsp_create_pcm_channel (chip, sample_rate, cpcm, cpcm->hw_buf.addr,cpcm->pcm_channel_id); if (cpcm->pcm_channel == NULL) { - snd_printk(KERN_ERR "cs46xx: failed to create virtual PCM channel\n"); + dev_err(chip->card->dev, + "failed to create virtual PCM channel\n"); return -ENOMEM; } cpcm->pcm_channel->sample_rate = sample_rate; @@ -1067,7 +1076,8 @@ static int _cs46xx_adjust_sample_rate (struct snd_cs46xx *chip, struct snd_cs46x if ( (cpcm->pcm_channel = cs46xx_dsp_create_pcm_channel (chip, sample_rate, cpcm, cpcm->hw_buf.addr, cpcm->pcm_channel_id)) == NULL) { - snd_printk(KERN_ERR "cs46xx: failed to re-create virtual PCM channel\n"); + dev_err(chip->card->dev, + "failed to re-create virtual PCM channel\n"); return -ENOMEM; } @@ -1116,7 +1126,8 @@ static int snd_cs46xx_playback_hw_params(struct snd_pcm_substream *substream, return -EINVAL; } - snd_printdd ("period_size (%d), periods (%d) buffer_size(%d)\n", + dev_dbg(chip->card->dev, + "period_size (%d), periods (%d) buffer_size(%d)\n", period_size, params_periods(hw_params), params_buffer_bytes(hw_params)); #endif @@ -1531,22 +1542,20 @@ static int _cs46xx_playback_open_channel (struct snd_pcm_substream *substream,in static int snd_cs46xx_playback_open(struct snd_pcm_substream *substream) { - snd_printdd("open front channel\n"); + dev_dbg(substream->pcm->card->dev, "open front channel\n"); return _cs46xx_playback_open_channel(substream,DSP_PCM_MAIN_CHANNEL); } #ifdef CONFIG_SND_CS46XX_NEW_DSP static int snd_cs46xx_playback_open_rear(struct snd_pcm_substream *substream) { - snd_printdd("open rear channel\n"); - + dev_dbg(substream->pcm->card->dev, "open rear channel\n"); return _cs46xx_playback_open_channel(substream,DSP_PCM_REAR_CHANNEL); } static int snd_cs46xx_playback_open_clfe(struct snd_pcm_substream *substream) { - snd_printdd("open center - LFE channel\n"); - + dev_dbg(substream->pcm->card->dev, "open center - LFE channel\n"); return _cs46xx_playback_open_channel(substream,DSP_PCM_CENTER_LFE_CHANNEL); } @@ -1554,7 +1563,7 @@ static int snd_cs46xx_playback_open_iec958(struct snd_pcm_substream *substream) { struct snd_cs46xx *chip = snd_pcm_substream_chip(substream); - snd_printdd("open raw iec958 channel\n"); + dev_dbg(chip->card->dev, "open raw iec958 channel\n"); mutex_lock(&chip->spos_mutex); cs46xx_iec958_pre_open (chip); @@ -1570,7 +1579,7 @@ static int snd_cs46xx_playback_close_iec958(struct snd_pcm_substream *substream) int err; struct snd_cs46xx *chip = snd_pcm_substream_chip(substream); - snd_printdd("close raw iec958 channel\n"); + dev_dbg(chip->card->dev, "close raw iec958 channel\n"); err = snd_cs46xx_playback_close(substream); @@ -2421,10 +2430,10 @@ static void snd_cs46xx_codec_reset (struct snd_ac97 * ac97) /* set the desired CODEC mode */ if (ac97->num == CS46XX_PRIMARY_CODEC_INDEX) { - snd_printdd("cs46xx: CODEC1 mode %04x\n", 0x0); + dev_dbg(ac97->bus->card->dev, "CODEC1 mode %04x\n", 0x0); snd_cs46xx_ac97_write(ac97, AC97_CSR_ACMODE, 0x0); } else if (ac97->num == CS46XX_SECONDARY_CODEC_INDEX) { - snd_printdd("cs46xx: CODEC2 mode %04x\n", 0x3); + dev_dbg(ac97->bus->card->dev, "CODEC2 mode %04x\n", 0x3); snd_cs46xx_ac97_write(ac97, AC97_CSR_ACMODE, 0x3); } else { snd_BUG(); /* should never happen ... */ @@ -2456,7 +2465,8 @@ static void snd_cs46xx_codec_reset (struct snd_ac97 * ac97) msleep(10); } while (time_after_eq(end_time, jiffies)); - snd_printk(KERN_ERR "CS46xx secondary codec doesn't respond!\n"); + dev_err(ac97->bus->card->dev, + "CS46xx secondary codec doesn't respond!\n"); } #endif @@ -2476,7 +2486,8 @@ static int cs46xx_detect_codec(struct snd_cs46xx *chip, int codec) snd_cs46xx_codec_write(chip, AC97_RESET, 0, codec); udelay(10); if (snd_cs46xx_codec_read(chip, AC97_RESET, codec) & 0x8000) { - snd_printdd("snd_cs46xx: seconadry codec not present\n"); + dev_dbg(chip->card->dev, + "seconadry codec not present\n"); return -ENXIO; } } @@ -2489,7 +2500,7 @@ static int cs46xx_detect_codec(struct snd_cs46xx *chip, int codec) } msleep(10); } - snd_printdd("snd_cs46xx: codec %d detection timeout\n", codec); + dev_dbg(chip->card->dev, "codec %d detection timeout\n", codec); return -ENXIO; } @@ -2509,7 +2520,7 @@ int snd_cs46xx_mixer(struct snd_cs46xx *chip, int spdif_device) /* detect primary codec */ chip->nr_ac97_codecs = 0; - snd_printdd("snd_cs46xx: detecting primary codec\n"); + dev_dbg(chip->card->dev, "detecting primary codec\n"); if ((err = snd_ac97_bus(card, 0, &ops, chip, &chip->ac97_bus)) < 0) return err; chip->ac97_bus->private_free = snd_cs46xx_mixer_free_ac97_bus; @@ -2519,7 +2530,7 @@ int snd_cs46xx_mixer(struct snd_cs46xx *chip, int spdif_device) chip->nr_ac97_codecs = 1; #ifdef CONFIG_SND_CS46XX_NEW_DSP - snd_printdd("snd_cs46xx: detecting seconadry codec\n"); + dev_dbg(chip->card->dev, "detecting seconadry codec\n"); /* try detect a secondary codec */ if (! cs46xx_detect_codec(chip, CS46XX_SECONDARY_CODEC_INDEX)) chip->nr_ac97_codecs = 2; @@ -2554,7 +2565,7 @@ int snd_cs46xx_mixer(struct snd_cs46xx *chip, int spdif_device) } /* do soundcard specific mixer setup */ if (chip->mixer_init) { - snd_printdd ("calling chip->mixer_init(chip);\n"); + dev_dbg(chip->card->dev, "calling chip->mixer_init(chip);\n"); chip->mixer_init(chip); } #endif @@ -2801,7 +2812,8 @@ int snd_cs46xx_gameport(struct snd_cs46xx *chip) chip->gameport = gp = gameport_allocate_port(); if (!gp) { - printk(KERN_ERR "cs46xx: cannot allocate memory for gameport\n"); + dev_err(chip->card->dev, + "cannot allocate memory for gameport\n"); return -ENOMEM; } @@ -3138,8 +3150,10 @@ static int snd_cs46xx_chip_init(struct snd_cs46xx *chip) } - snd_printk(KERN_ERR "create - never read codec ready from AC'97\n"); - snd_printk(KERN_ERR "it is not probably bug, try to use CS4236 driver\n"); + dev_err(chip->card->dev, + "create - never read codec ready from AC'97\n"); + dev_err(chip->card->dev, + "it is not probably bug, try to use CS4236 driver\n"); return -EIO; ok1: #ifdef CONFIG_SND_CS46XX_NEW_DSP @@ -3157,7 +3171,8 @@ static int snd_cs46xx_chip_init(struct snd_cs46xx *chip) * Make sure CODEC is READY. */ if (!(snd_cs46xx_peekBA0(chip, BA0_ACSTS2) & ACSTS_CRDY)) - snd_printdd("cs46xx: never read card ready from secondary AC'97\n"); + dev_dbg(chip->card->dev, + "never read card ready from secondary AC'97\n"); } #endif @@ -3187,17 +3202,21 @@ static int snd_cs46xx_chip_init(struct snd_cs46xx *chip) } #ifndef CONFIG_SND_CS46XX_NEW_DSP - snd_printk(KERN_ERR "create - never read ISV3 & ISV4 from AC'97\n"); + dev_err(chip->card->dev, + "create - never read ISV3 & ISV4 from AC'97\n"); return -EIO; #else /* This may happen on a cold boot with a Terratec SiXPack 5.1. Reloading the driver may help, if there's other soundcards with the same problem I would like to know. (Benny) */ - snd_printk(KERN_ERR "ERROR: snd-cs46xx: never read ISV3 & ISV4 from AC'97\n"); - snd_printk(KERN_ERR " Try reloading the ALSA driver, if you find something\n"); - snd_printk(KERN_ERR " broken or not working on your soundcard upon\n"); - snd_printk(KERN_ERR " this message please report to alsa-devel@alsa-project.org\n"); + dev_err(chip->card->dev, "never read ISV3 & ISV4 from AC'97\n"); + dev_err(chip->card->dev, + "Try reloading the ALSA driver, if you find something\n"); + dev_err(chip->card->dev, + "broken or not working on your soundcard upon\n"); + dev_err(chip->card->dev, + "this message please report to alsa-devel@alsa-project.org\n"); return -EIO; #endif @@ -3266,13 +3285,13 @@ int snd_cs46xx_start_dsp(struct snd_cs46xx *chip) for (i = 0; i < CS46XX_DSP_MODULES; i++) { err = load_firmware(chip, &chip->modules[i], module_names[i]); if (err < 0) { - snd_printk(KERN_ERR "firmware load error [%s]\n", + dev_err(chip->card->dev, "firmware load error [%s]\n", module_names[i]); return err; } err = cs46xx_dsp_load_module(chip, chip->modules[i]); if (err < 0) { - snd_printk(KERN_ERR "image download error [%s]\n", + dev_err(chip->card->dev, "image download error [%s]\n", module_names[i]); return err; } @@ -3288,7 +3307,7 @@ int snd_cs46xx_start_dsp(struct snd_cs46xx *chip) /* old image */ err = snd_cs46xx_download_image(chip); if (err < 0) { - snd_printk(KERN_ERR "image download error\n"); + dev_err(chip->card->dev, "image download error\n"); return err; } @@ -3341,7 +3360,7 @@ static int voyetra_setup_eapd_slot(struct snd_cs46xx *chip) u32 idx, valid_slots,tmp,powerdown = 0; u16 modem_power,pin_config,logic_type; - snd_printdd ("cs46xx: cs46xx_setup_eapd_slot()+\n"); + dev_dbg(chip->card->dev, "cs46xx_setup_eapd_slot()+\n"); /* * See if the devices are powered down. If so, we must power them up first @@ -3359,7 +3378,8 @@ static int voyetra_setup_eapd_slot(struct snd_cs46xx *chip) * stuff. */ if(chip->nr_ac97_codecs != 2) { - snd_printk (KERN_ERR "cs46xx: cs46xx_setup_eapd_slot() - no secondary codec configured\n"); + dev_err(chip->card->dev, + "cs46xx_setup_eapd_slot() - no secondary codec configured\n"); return -EINVAL; } @@ -3400,7 +3420,7 @@ static int voyetra_setup_eapd_slot(struct snd_cs46xx *chip) snd_cs46xx_pokeBA0(chip, BA0_ACOSV, valid_slots); if ( cs46xx_wait_for_fifo(chip,1) ) { - snd_printdd("FIFO is busy\n"); + dev_dbg(chip->card->dev, "FIFO is busy\n"); return -EINVAL; } @@ -3421,7 +3441,9 @@ static int voyetra_setup_eapd_slot(struct snd_cs46xx *chip) * Wait for command to complete */ if ( cs46xx_wait_for_fifo(chip,200) ) { - snd_printdd("failed waiting for FIFO at addr (%02X)\n",idx); + dev_dbg(chip->card->dev, + "failed waiting for FIFO at addr (%02X)\n", + idx); return -EINVAL; } @@ -3510,14 +3532,14 @@ static void amp_hercules(struct snd_cs46xx *chip, int change) chip->amplifier += change; if (chip->amplifier && !old) { - snd_printdd ("Hercules amplifier ON\n"); + dev_dbg(chip->card->dev, "Hercules amplifier ON\n"); snd_cs46xx_pokeBA0(chip, BA0_EGPIODR, EGPIODR_GPOE2 | val1); /* enable EGPIO2 output */ snd_cs46xx_pokeBA0(chip, BA0_EGPIOPTR, EGPIOPTR_GPPT2 | val2); /* open-drain on output */ } else if (old && !chip->amplifier) { - snd_printdd ("Hercules amplifier OFF\n"); + dev_dbg(chip->card->dev, "Hercules amplifier OFF\n"); snd_cs46xx_pokeBA0(chip, BA0_EGPIODR, val1 & ~EGPIODR_GPOE2); /* disable */ snd_cs46xx_pokeBA0(chip, BA0_EGPIOPTR, val2 & ~EGPIOPTR_GPPT2); /* disable */ } @@ -3525,7 +3547,7 @@ static void amp_hercules(struct snd_cs46xx *chip, int change) static void voyetra_mixer_init (struct snd_cs46xx *chip) { - snd_printdd ("initializing Voyetra mixer\n"); + dev_dbg(chip->card->dev, "initializing Voyetra mixer\n"); /* Enable SPDIF out */ snd_cs46xx_pokeBA0(chip, BA0_EGPIODR, EGPIODR_GPOE0); @@ -3543,7 +3565,7 @@ static void hercules_mixer_init (struct snd_cs46xx *chip) /* set EGPIO to default */ hercules_init(chip); - snd_printdd ("initializing Hercules mixer\n"); + dev_dbg(chip->card->dev, "initializing Hercules mixer\n"); #ifdef CONFIG_SND_CS46XX_NEW_DSP if (chip->in_suspend) @@ -3554,7 +3576,9 @@ static void hercules_mixer_init (struct snd_cs46xx *chip) kctl = snd_ctl_new1(&snd_hercules_controls[idx], chip); if ((err = snd_ctl_add(card, kctl)) < 0) { - printk (KERN_ERR "cs46xx: failed to initialize Hercules mixer (%d)\n",err); + dev_err(card->dev, + "failed to initialize Hercules mixer (%d)\n", + err); break; } } @@ -3826,8 +3850,7 @@ static int snd_cs46xx_resume(struct device *dev) pci_set_power_state(pci, PCI_D0); pci_restore_state(pci); if (pci_enable_device(pci) < 0) { - printk(KERN_ERR "cs46xx: pci_enable_device failed, " - "disabling device\n"); + dev_err(dev, "pci_enable_device failed, disabling device\n"); snd_card_disconnect(card); return -EIO; } @@ -3932,7 +3955,8 @@ int snd_cs46xx_create(struct snd_card *card, chip->ba1_addr = pci_resource_start(pci, 1); if (chip->ba0_addr == 0 || chip->ba0_addr == (unsigned long)~0 || chip->ba1_addr == 0 || chip->ba1_addr == (unsigned long)~0) { - snd_printk(KERN_ERR "wrong address(es) - ba0 = 0x%lx, ba1 = 0x%lx\n", + dev_err(chip->card->dev, + "wrong address(es) - ba0 = 0x%lx, ba1 = 0x%lx\n", chip->ba0_addr, chip->ba1_addr); snd_cs46xx_free(chip); return -ENOMEM; @@ -3969,7 +3993,8 @@ int snd_cs46xx_create(struct snd_card *card, for (cp = &cards[0]; cp->name; cp++) { if (cp->vendor == ss_vendor && cp->id == ss_card) { - snd_printdd ("hack for %s enabled\n", cp->name); + dev_dbg(chip->card->dev, "hack for %s enabled\n", + cp->name); chip->amplifier_ctrl = cp->amp; chip->active_ctrl = cp->active; @@ -3982,12 +4007,14 @@ int snd_cs46xx_create(struct snd_card *card, } if (external_amp) { - snd_printk(KERN_INFO "Crystal EAPD support forced on.\n"); + dev_info(chip->card->dev, + "Crystal EAPD support forced on.\n"); chip->amplifier_ctrl = amp_voyetra; } if (thinkpad) { - snd_printk(KERN_INFO "Activating CLKRUN hack for Thinkpad.\n"); + dev_info(chip->card->dev, + "Activating CLKRUN hack for Thinkpad.\n"); chip->active_ctrl = clkrun_hack; clkrun_init(chip); } @@ -4005,14 +4032,16 @@ int snd_cs46xx_create(struct snd_card *card, region = &chip->region.idx[idx]; if ((region->resource = request_mem_region(region->base, region->size, region->name)) == NULL) { - snd_printk(KERN_ERR "unable to request memory region 0x%lx-0x%lx\n", + dev_err(chip->card->dev, + "unable to request memory region 0x%lx-0x%lx\n", region->base, region->base + region->size - 1); snd_cs46xx_free(chip); return -EBUSY; } region->remap_addr = ioremap_nocache(region->base, region->size); if (region->remap_addr == NULL) { - snd_printk(KERN_ERR "%s ioremap problem\n", region->name); + dev_err(chip->card->dev, + "%s ioremap problem\n", region->name); snd_cs46xx_free(chip); return -ENOMEM; } @@ -4020,7 +4049,7 @@ int snd_cs46xx_create(struct snd_card *card, if (request_irq(pci->irq, snd_cs46xx_interrupt, IRQF_SHARED, KBUILD_MODNAME, chip)) { - snd_printk(KERN_ERR "unable to grab IRQ %d\n", pci->irq); + dev_err(chip->card->dev, "unable to grab IRQ %d\n", pci->irq); snd_cs46xx_free(chip); return -EBUSY; } @@ -4058,8 +4087,6 @@ int snd_cs46xx_create(struct snd_card *card, chip->active_ctrl(chip, -1); /* disable CLKRUN */ - snd_card_set_dev(card, &pci->dev); - *rchip = chip; return 0; } diff --git a/sound/pci/cs46xx/dsp_spos.c b/sound/pci/cs46xx/dsp_spos.c index 1686b4f4c44..1c4a0fb3ffe 100644 --- a/sound/pci/cs46xx/dsp_spos.c +++ b/sound/pci/cs46xx/dsp_spos.c @@ -85,12 +85,15 @@ static int shadow_and_reallocate_code (struct snd_cs46xx * chip, u32 * data, u32 address = (hival & 0x00FFF) << 5; address |= loval >> 15; - snd_printdd("handle_wideop[1]: %05x:%05x addr %04x\n",hival,loval,address); + dev_dbg(chip->card->dev, + "handle_wideop[1]: %05x:%05x addr %04x\n", + hival, loval, address); if ( !(address & 0x8000) ) { address += (ins->code.offset / 2) - overlay_begin_address; } else { - snd_printdd("handle_wideop[1]: ROM symbol not reallocated\n"); + dev_dbg(chip->card->dev, + "handle_wideop[1]: ROM symbol not reallocated\n"); } hival &= 0xFF000; @@ -102,8 +105,9 @@ static int shadow_and_reallocate_code (struct snd_cs46xx * chip, u32 * data, u32 address = (hival & 0x00FFF) << 5; address |= loval >> 15; - snd_printdd("handle_wideop:[2] %05x:%05x addr %04x\n",hival,loval,address); - nreallocated ++; + dev_dbg(chip->card->dev, + "handle_wideop:[2] %05x:%05x addr %04x\n", + hival, loval, address); nreallocated++; } /* wide_opcodes[j] == wide_op */ } /* for */ } /* mod_type == 0 ... */ @@ -113,7 +117,8 @@ static int shadow_and_reallocate_code (struct snd_cs46xx * chip, u32 * data, u32 ins->code.data[ins->code.size++] = hival; } - snd_printdd("dsp_spos: %d instructions reallocated\n",nreallocated); + dev_dbg(chip->card->dev, + "dsp_spos: %d instructions reallocated\n", nreallocated); return nreallocated; } @@ -157,7 +162,8 @@ static int add_symbols (struct snd_cs46xx * chip, struct dsp_module_desc * modul for (i = 0;i < module->symbol_table.nsymbols; ++i) { if (ins->symbol_table.nsymbols == (DSP_MAX_SYMBOLS - 1)) { - snd_printk(KERN_ERR "dsp_spos: symbol table is full\n"); + dev_err(chip->card->dev, + "dsp_spos: symbol table is full\n"); return -ENOMEM; } @@ -176,8 +182,11 @@ static int add_symbols (struct snd_cs46xx * chip, struct dsp_module_desc * modul ins->symbol_table.nsymbols++; } else { - /* if (0) printk ("dsp_spos: symbol <%s> duplicated, probably nothing wrong with that (Cirrus?)\n", - module->symbol_table.symbols[i].symbol_name); */ +#if 0 + dev_dbg(chip->card->dev, + "dsp_spos: symbol <%s> duplicated, probably nothing wrong with that (Cirrus?)\n", + module->symbol_table.symbols[i].symbol_name); */ +#endif } } @@ -192,14 +201,15 @@ add_symbol (struct snd_cs46xx * chip, char * symbol_name, u32 address, int type) int index; if (ins->symbol_table.nsymbols == (DSP_MAX_SYMBOLS - 1)) { - snd_printk(KERN_ERR "dsp_spos: symbol table is full\n"); + dev_err(chip->card->dev, "dsp_spos: symbol table is full\n"); return NULL; } if (cs46xx_dsp_lookup_symbol(chip, symbol_name, type) != NULL) { - snd_printk(KERN_ERR "dsp_spos: symbol <%s> duplicated\n", symbol_name); + dev_err(chip->card->dev, + "dsp_spos: symbol <%s> duplicated\n", symbol_name); return NULL; } @@ -305,19 +315,20 @@ static int dsp_load_parameter(struct snd_cs46xx *chip, u32 doffset, dsize; if (!parameter) { - snd_printdd("dsp_spos: module got no parameter segment\n"); + dev_dbg(chip->card->dev, + "dsp_spos: module got no parameter segment\n"); return 0; } doffset = (parameter->offset * 4 + DSP_PARAMETER_BYTE_OFFSET); dsize = parameter->size * 4; - snd_printdd("dsp_spos: " - "downloading parameter data to chip (%08x-%08x)\n", + dev_dbg(chip->card->dev, + "dsp_spos: downloading parameter data to chip (%08x-%08x)\n", doffset,doffset + dsize); if (snd_cs46xx_download (chip, parameter->data, doffset, dsize)) { - snd_printk(KERN_ERR "dsp_spos: " - "failed to download parameter data to DSP\n"); + dev_err(chip->card->dev, + "dsp_spos: failed to download parameter data to DSP\n"); return -EINVAL; } return 0; @@ -329,18 +340,21 @@ static int dsp_load_sample(struct snd_cs46xx *chip, u32 doffset, dsize; if (!sample) { - snd_printdd("dsp_spos: module got no sample segment\n"); + dev_dbg(chip->card->dev, + "dsp_spos: module got no sample segment\n"); return 0; } doffset = (sample->offset * 4 + DSP_SAMPLE_BYTE_OFFSET); dsize = sample->size * 4; - snd_printdd("dsp_spos: downloading sample data to chip (%08x-%08x)\n", + dev_dbg(chip->card->dev, + "dsp_spos: downloading sample data to chip (%08x-%08x)\n", doffset,doffset + dsize); if (snd_cs46xx_download (chip,sample->data,doffset,dsize)) { - snd_printk(KERN_ERR "dsp_spos: failed to sample data to DSP\n"); + dev_err(chip->card->dev, + "dsp_spos: failed to sample data to DSP\n"); return -EINVAL; } return 0; @@ -354,14 +368,16 @@ int cs46xx_dsp_load_module (struct snd_cs46xx * chip, struct dsp_module_desc * m int err; if (ins->nmodules == DSP_MAX_MODULES - 1) { - snd_printk(KERN_ERR "dsp_spos: to many modules loaded into DSP\n"); + dev_err(chip->card->dev, + "dsp_spos: to many modules loaded into DSP\n"); return -ENOMEM; } - snd_printdd("dsp_spos: loading module %s into DSP\n", module->module_name); + dev_dbg(chip->card->dev, + "dsp_spos: loading module %s into DSP\n", module->module_name); if (ins->nmodules == 0) { - snd_printdd("dsp_spos: clearing parameter area\n"); + dev_dbg(chip->card->dev, "dsp_spos: clearing parameter area\n"); snd_cs46xx_clear_BA1(chip, DSP_PARAMETER_BYTE_OFFSET, DSP_PARAMETER_BYTE_SIZE); } @@ -371,7 +387,7 @@ int cs46xx_dsp_load_module (struct snd_cs46xx * chip, struct dsp_module_desc * m return err; if (ins->nmodules == 0) { - snd_printdd("dsp_spos: clearing sample area\n"); + dev_dbg(chip->card->dev, "dsp_spos: clearing sample area\n"); snd_cs46xx_clear_BA1(chip, DSP_SAMPLE_BYTE_OFFSET, DSP_SAMPLE_BYTE_SIZE); } @@ -381,15 +397,17 @@ int cs46xx_dsp_load_module (struct snd_cs46xx * chip, struct dsp_module_desc * m return err; if (ins->nmodules == 0) { - snd_printdd("dsp_spos: clearing code area\n"); + dev_dbg(chip->card->dev, "dsp_spos: clearing code area\n"); snd_cs46xx_clear_BA1(chip, DSP_CODE_BYTE_OFFSET, DSP_CODE_BYTE_SIZE); } if (code == NULL) { - snd_printdd("dsp_spos: module got no code segment\n"); + dev_dbg(chip->card->dev, + "dsp_spos: module got no code segment\n"); } else { if (ins->code.offset + code->size > DSP_CODE_BYTE_SIZE) { - snd_printk(KERN_ERR "dsp_spos: no space available in DSP\n"); + dev_err(chip->card->dev, + "dsp_spos: no space available in DSP\n"); return -ENOMEM; } @@ -401,19 +419,22 @@ int cs46xx_dsp_load_module (struct snd_cs46xx * chip, struct dsp_module_desc * m if (snd_BUG_ON(!module->symbol_table.symbols)) return -ENOMEM; if (add_symbols(chip,module)) { - snd_printk(KERN_ERR "dsp_spos: failed to load symbol table\n"); + dev_err(chip->card->dev, + "dsp_spos: failed to load symbol table\n"); return -ENOMEM; } doffset = (code->offset * 4 + ins->code.offset * 4 + DSP_CODE_BYTE_OFFSET); dsize = code->size * 4; - snd_printdd("dsp_spos: downloading code to chip (%08x-%08x)\n", + dev_dbg(chip->card->dev, + "dsp_spos: downloading code to chip (%08x-%08x)\n", doffset,doffset + dsize); module->nfixups = shadow_and_reallocate_code(chip,code->data,code->size,module->overlay_begin_address); if (snd_cs46xx_download (chip,(ins->code.data + ins->code.offset),doffset,dsize)) { - snd_printk(KERN_ERR "dsp_spos: failed to download code to DSP\n"); + dev_err(chip->card->dev, + "dsp_spos: failed to download code to DSP\n"); return -EINVAL; } @@ -447,7 +468,7 @@ cs46xx_dsp_lookup_symbol (struct snd_cs46xx * chip, char * symbol_name, int symb } #if 0 - printk ("dsp_spos: symbol <%s> type %02x not found\n", + dev_err(chip->card->dev, "dsp_spos: symbol <%s> type %02x not found\n", symbol_name,symbol_type); #endif @@ -910,7 +931,6 @@ int cs46xx_dsp_proc_done (struct snd_cs46xx *chip) } #endif /* CONFIG_PROC_FS */ -static int debug_tree; static void _dsp_create_task_tree (struct snd_cs46xx *chip, u32 * task_data, u32 dest, int size) { @@ -919,13 +939,13 @@ static void _dsp_create_task_tree (struct snd_cs46xx *chip, u32 * task_data, int i; for (i = 0; i < size; ++i) { - if (debug_tree) printk ("addr %p, val %08x\n",spdst,task_data[i]); + dev_dbg(chip->card->dev, "addr %p, val %08x\n", + spdst, task_data[i]); writel(task_data[i],spdst); spdst += sizeof(u32); } } -static int debug_scb; static void _dsp_create_scb (struct snd_cs46xx *chip, u32 * scb_data, u32 dest) { void __iomem *spdst = chip->region.idx[1].remap_addr + @@ -933,7 +953,8 @@ static void _dsp_create_scb (struct snd_cs46xx *chip, u32 * scb_data, u32 dest) int i; for (i = 0; i < 0x10; ++i) { - if (debug_scb) printk ("addr %p, val %08x\n",spdst,scb_data[i]); + dev_dbg(chip->card->dev, "addr %p, val %08x\n", + spdst, scb_data[i]); writel(scb_data[i],spdst); spdst += sizeof(u32); } @@ -960,7 +981,8 @@ static struct dsp_scb_descriptor * _map_scb (struct snd_cs46xx *chip, char * nam int index; if (ins->nscb == DSP_MAX_SCB_DESC - 1) { - snd_printk(KERN_ERR "dsp_spos: got no place for other SCB\n"); + dev_err(chip->card->dev, + "dsp_spos: got no place for other SCB\n"); return NULL; } @@ -991,7 +1013,8 @@ _map_task_tree (struct snd_cs46xx *chip, char * name, u32 dest, u32 size) struct dsp_task_descriptor * desc = NULL; if (ins->ntask == DSP_MAX_TASK_DESC - 1) { - snd_printk(KERN_ERR "dsp_spos: got no place for other TASK\n"); + dev_err(chip->card->dev, + "dsp_spos: got no place for other TASK\n"); return NULL; } @@ -1031,7 +1054,7 @@ cs46xx_dsp_create_scb (struct snd_cs46xx *chip, char * name, u32 * scb_data, u32 desc->data = scb_data; _dsp_create_scb(chip,scb_data,dest); } else { - snd_printk(KERN_ERR "dsp_spos: failed to map SCB\n"); + dev_err(chip->card->dev, "dsp_spos: failed to map SCB\n"); #ifdef CONFIG_PM_SLEEP kfree(scb_data); #endif @@ -1052,7 +1075,7 @@ cs46xx_dsp_create_task_tree (struct snd_cs46xx *chip, char * name, u32 * task_da desc->data = task_data; _dsp_create_task_tree(chip,task_data,dest,size); } else { - snd_printk(KERN_ERR "dsp_spos: failed to map TASK\n"); + dev_err(chip->card->dev, "dsp_spos: failed to map TASK\n"); } return desc; @@ -1105,31 +1128,36 @@ int cs46xx_dsp_scb_and_task_init (struct snd_cs46xx *chip) null_algorithm = cs46xx_dsp_lookup_symbol(chip, "NULLALGORITHM", SYMBOL_CODE); if (null_algorithm == NULL) { - snd_printk(KERN_ERR "dsp_spos: symbol NULLALGORITHM not found\n"); + dev_err(chip->card->dev, + "dsp_spos: symbol NULLALGORITHM not found\n"); return -EIO; } fg_task_tree_header_code = cs46xx_dsp_lookup_symbol(chip, "FGTASKTREEHEADERCODE", SYMBOL_CODE); if (fg_task_tree_header_code == NULL) { - snd_printk(KERN_ERR "dsp_spos: symbol FGTASKTREEHEADERCODE not found\n"); + dev_err(chip->card->dev, + "dsp_spos: symbol FGTASKTREEHEADERCODE not found\n"); return -EIO; } task_tree_header_code = cs46xx_dsp_lookup_symbol(chip, "TASKTREEHEADERCODE", SYMBOL_CODE); if (task_tree_header_code == NULL) { - snd_printk(KERN_ERR "dsp_spos: symbol TASKTREEHEADERCODE not found\n"); + dev_err(chip->card->dev, + "dsp_spos: symbol TASKTREEHEADERCODE not found\n"); return -EIO; } task_tree_thread = cs46xx_dsp_lookup_symbol(chip, "TASKTREETHREAD", SYMBOL_CODE); if (task_tree_thread == NULL) { - snd_printk(KERN_ERR "dsp_spos: symbol TASKTREETHREAD not found\n"); + dev_err(chip->card->dev, + "dsp_spos: symbol TASKTREETHREAD not found\n"); return -EIO; } magic_snoop_task = cs46xx_dsp_lookup_symbol(chip, "MAGICSNOOPTASK", SYMBOL_CODE); if (magic_snoop_task == NULL) { - snd_printk(KERN_ERR "dsp_spos: symbol MAGICSNOOPTASK not found\n"); + dev_err(chip->card->dev, + "dsp_spos: symbol MAGICSNOOPTASK not found\n"); return -EIO; } @@ -1476,7 +1504,7 @@ int cs46xx_dsp_scb_and_task_init (struct snd_cs46xx *chip) return 0; _fail_end: - snd_printk(KERN_ERR "dsp_spos: failed to setup SCB's in DSP\n"); + dev_err(chip->card->dev, "dsp_spos: failed to setup SCB's in DSP\n"); return -EINVAL; } @@ -1491,18 +1519,21 @@ static int cs46xx_dsp_async_init (struct snd_cs46xx *chip, s16_async_codec_input_task = cs46xx_dsp_lookup_symbol(chip, "S16_ASYNCCODECINPUTTASK", SYMBOL_CODE); if (s16_async_codec_input_task == NULL) { - snd_printk(KERN_ERR "dsp_spos: symbol S16_ASYNCCODECINPUTTASK not found\n"); + dev_err(chip->card->dev, + "dsp_spos: symbol S16_ASYNCCODECINPUTTASK not found\n"); return -EIO; } spdifo_task = cs46xx_dsp_lookup_symbol(chip, "SPDIFOTASK", SYMBOL_CODE); if (spdifo_task == NULL) { - snd_printk(KERN_ERR "dsp_spos: symbol SPDIFOTASK not found\n"); + dev_err(chip->card->dev, + "dsp_spos: symbol SPDIFOTASK not found\n"); return -EIO; } spdifi_task = cs46xx_dsp_lookup_symbol(chip, "SPDIFITASK", SYMBOL_CODE); if (spdifi_task == NULL) { - snd_printk(KERN_ERR "dsp_spos: symbol SPDIFITASK not found\n"); + dev_err(chip->card->dev, + "dsp_spos: symbol SPDIFITASK not found\n"); return -EIO; } @@ -1883,7 +1914,8 @@ int cs46xx_poke_via_dsp (struct snd_cs46xx *chip, u32 address, u32 data) } if (i == 25) { - snd_printk(KERN_ERR "dsp_spos: SPIOWriteTask not responding\n"); + dev_err(chip->card->dev, + "dsp_spos: SPIOWriteTask not responding\n"); return -EBUSY; } diff --git a/sound/pci/cs46xx/dsp_spos_scb_lib.c b/sound/pci/cs46xx/dsp_spos_scb_lib.c index 409e8764fbe..8284bc9b585 100644 --- a/sound/pci/cs46xx/dsp_spos_scb_lib.c +++ b/sound/pci/cs46xx/dsp_spos_scb_lib.c @@ -233,8 +233,11 @@ void cs46xx_dsp_proc_free_scb_desc (struct dsp_scb_descriptor * scb) { if (scb->proc_info) { struct proc_scb_info * scb_info = scb->proc_info->private_data; + struct snd_cs46xx *chip = scb_info->chip; - snd_printdd("cs46xx_dsp_proc_free_scb_desc: freeing %s\n",scb->scb_name); + dev_dbg(chip->card->dev, + "cs46xx_dsp_proc_free_scb_desc: freeing %s\n", + scb->scb_name); snd_info_free_entry(scb->proc_info); scb->proc_info = NULL; @@ -305,7 +308,7 @@ _dsp_create_generic_scb (struct snd_cs46xx *chip, char * name, u32 * scb_data, u scb_data[SCBfuncEntryPtr] &= 0xFFFF0000; scb_data[SCBfuncEntryPtr] |= task_entry->address; - snd_printdd("dsp_spos: creating SCB <%s>\n",name); + dev_dbg(chip->card->dev, "dsp_spos: creating SCB <%s>\n", name); scb = cs46xx_dsp_create_scb(chip,name,scb_data,dest); @@ -320,9 +323,15 @@ _dsp_create_generic_scb (struct snd_cs46xx *chip, char * name, u32 * scb_data, u /* update parent SCB */ if (scb->parent_scb_ptr) { #if 0 - printk ("scb->parent_scb_ptr = %s\n",scb->parent_scb_ptr->scb_name); - printk ("scb->parent_scb_ptr->next_scb_ptr = %s\n",scb->parent_scb_ptr->next_scb_ptr->scb_name); - printk ("scb->parent_scb_ptr->sub_list_ptr = %s\n",scb->parent_scb_ptr->sub_list_ptr->scb_name); + dev_dbg(chip->card->dev, + "scb->parent_scb_ptr = %s\n", + scb->parent_scb_ptr->scb_name); + dev_dbg(chip->card->dev, + "scb->parent_scb_ptr->next_scb_ptr = %s\n", + scb->parent_scb_ptr->next_scb_ptr->scb_name); + dev_dbg(chip->card->dev, + "scb->parent_scb_ptr->sub_list_ptr = %s\n", + scb->parent_scb_ptr->sub_list_ptr->scb_name); #endif /* link to parent SCB */ if (scb_child_type == SCB_ON_PARENT_NEXT_SCB) { @@ -368,7 +377,8 @@ cs46xx_dsp_create_generic_scb (struct snd_cs46xx *chip, char * name, u32 * scb_d SYMBOL_CODE); if (task_entry == NULL) { - snd_printk (KERN_ERR "dsp_spos: symbol %s not found\n",task_entry_name); + dev_err(chip->card->dev, + "dsp_spos: symbol %s not found\n", task_entry_name); return NULL; } @@ -582,7 +592,8 @@ cs46xx_dsp_create_pcm_reader_scb(struct snd_cs46xx * chip, char * scb_name, SYMBOL_CODE); if (ins->null_algorithm == NULL) { - snd_printk (KERN_ERR "dsp_spos: symbol NULLALGORITHM not found\n"); + dev_err(chip->card->dev, + "dsp_spos: symbol NULLALGORITHM not found\n"); return NULL; } } @@ -612,7 +623,8 @@ cs46xx_dsp_create_src_task_scb(struct snd_cs46xx * chip, char * scb_name, unsigned int phiIncr; unsigned int correctionPerGOF, correctionPerSec; - snd_printdd( "dsp_spos: setting %s rate to %u\n",scb_name,rate); + dev_dbg(chip->card->dev, "dsp_spos: setting %s rate to %u\n", + scb_name, rate); /* * Compute the values used to drive the actual sample rate conversion. @@ -670,7 +682,8 @@ cs46xx_dsp_create_src_task_scb(struct snd_cs46xx * chip, char * scb_name, SYMBOL_CODE); if (ins->s16_up == NULL) { - snd_printk (KERN_ERR "dsp_spos: symbol S16_UPSRC not found\n"); + dev_err(chip->card->dev, + "dsp_spos: symbol S16_UPSRC not found\n"); return NULL; } } @@ -1265,7 +1278,7 @@ cs46xx_dsp_create_pcm_channel (struct snd_cs46xx * chip, the Sample Rate Converted (which could alter the raw data stream ...) */ if (sample_rate == 48000) { - snd_printdd ("IEC958 pass through\n"); + dev_dbg(chip->card->dev, "IEC958 pass through\n"); /* Hack to bypass creating a new SRC */ pass_through = 1; } @@ -1299,13 +1312,14 @@ cs46xx_dsp_create_pcm_channel (struct snd_cs46xx * chip, } if (pcm_index == -1) { - snd_printk (KERN_ERR "dsp_spos: no free PCM channel\n"); + dev_err(chip->card->dev, "dsp_spos: no free PCM channel\n"); return NULL; } if (src_scb == NULL) { if (ins->nsrc_scb >= DSP_MAX_SRC_NR) { - snd_printk(KERN_ERR "dsp_spos: to many SRC instances\n!"); + dev_err(chip->card->dev, + "dsp_spos: to many SRC instances\n!"); return NULL; } @@ -1331,7 +1345,8 @@ cs46xx_dsp_create_pcm_channel (struct snd_cs46xx * chip, snprintf (scb_name,DSP_MAX_SCB_NAME,"SrcTask_SCB%d",src_index); - snd_printdd( "dsp_spos: creating SRC \"%s\"\n",scb_name); + dev_dbg(chip->card->dev, + "dsp_spos: creating SRC \"%s\"\n", scb_name); src_scb = cs46xx_dsp_create_src_task_scb(chip,scb_name, sample_rate, src_output_buffer_addr[src_index], @@ -1343,7 +1358,8 @@ cs46xx_dsp_create_pcm_channel (struct snd_cs46xx * chip, pass_through); if (!src_scb) { - snd_printk (KERN_ERR "dsp_spos: failed to create SRCtaskSCB\n"); + dev_err(chip->card->dev, + "dsp_spos: failed to create SRCtaskSCB\n"); return NULL; } @@ -1355,8 +1371,8 @@ cs46xx_dsp_create_pcm_channel (struct snd_cs46xx * chip, snprintf (scb_name,DSP_MAX_SCB_NAME,"PCMReader_SCB%d",pcm_index); - snd_printdd( "dsp_spos: creating PCM \"%s\" (%d)\n",scb_name, - pcm_channel_id); + dev_dbg(chip->card->dev, "dsp_spos: creating PCM \"%s\" (%d)\n", + scb_name, pcm_channel_id); pcm_scb = cs46xx_dsp_create_pcm_reader_scb(chip,scb_name, pcm_reader_buffer_addr[pcm_index], @@ -1369,7 +1385,8 @@ cs46xx_dsp_create_pcm_channel (struct snd_cs46xx * chip, ); if (!pcm_scb) { - snd_printk (KERN_ERR "dsp_spos: failed to create PCMreaderSCB\n"); + dev_err(chip->card->dev, + "dsp_spos: failed to create PCMreaderSCB\n"); return NULL; } @@ -1419,7 +1436,8 @@ int cs46xx_dsp_pcm_channel_set_period (struct snd_cs46xx * chip, temp |= DMA_RQ_C1_SOURCE_MOD16; break; default: - snd_printdd ("period size (%d) not supported by HW\n", period_size); + dev_dbg(chip->card->dev, + "period size (%d) not supported by HW\n", period_size); return -EINVAL; } @@ -1457,7 +1475,8 @@ int cs46xx_dsp_pcm_ostream_set_period (struct snd_cs46xx * chip, temp |= DMA_RQ_C1_DEST_MOD16; break; default: - snd_printdd ("period size (%d) not supported by HW\n", period_size); + dev_dbg(chip->card->dev, + "period size (%d) not supported by HW\n", period_size); return -EINVAL; } diff --git a/sound/pci/cs5530.c b/sound/pci/cs5530.c index c6b82c85e04..b4e0ff6a99a 100644 --- a/sound/pci/cs5530.c +++ b/sound/pci/cs5530.c @@ -160,17 +160,17 @@ static int snd_cs5530_create(struct snd_card *card, sb_base = 0x220 + 0x20 * (map & 3); if (map & (1<<2)) - printk(KERN_INFO "CS5530: XpressAudio at 0x%lx\n", sb_base); + dev_info(card->dev, "XpressAudio at 0x%lx\n", sb_base); else { - printk(KERN_ERR "Could not find XpressAudio!\n"); + dev_err(card->dev, "Could not find XpressAudio!\n"); snd_cs5530_free(chip); return -ENODEV; } if (map & (1<<5)) - printk(KERN_INFO "CS5530: MPU at 0x300\n"); + dev_info(card->dev, "MPU at 0x300\n"); else if (map & (1<<6)) - printk(KERN_INFO "CS5530: MPU at 0x330\n"); + dev_info(card->dev, "MPU at 0x330\n"); irq = snd_cs5530_mixer_read(sb_base, 0x80) & 0x0F; dma8 = snd_cs5530_mixer_read(sb_base, 0x81); @@ -182,7 +182,7 @@ static int snd_cs5530_create(struct snd_card *card, else if (dma8 & 0x80) dma16 = 7; else { - printk(KERN_ERR "CS5530: No 16bit DMA enabled\n"); + dev_err(card->dev, "No 16bit DMA enabled\n"); snd_cs5530_free(chip); return -ENODEV; } @@ -194,7 +194,7 @@ static int snd_cs5530_create(struct snd_card *card, else if (dma8 & 0x08) dma8 = 3; else { - printk(KERN_ERR "CS5530: No 8bit DMA enabled\n"); + dev_err(card->dev, "No 8bit DMA enabled\n"); snd_cs5530_free(chip); return -ENODEV; } @@ -208,32 +208,31 @@ static int snd_cs5530_create(struct snd_card *card, else if (irq & 8) irq = 10; else { - printk(KERN_ERR "CS5530: SoundBlaster IRQ not set\n"); + dev_err(card->dev, "SoundBlaster IRQ not set\n"); snd_cs5530_free(chip); return -ENODEV; } - printk(KERN_INFO "CS5530: IRQ: %d DMA8: %d DMA16: %d\n", irq, dma8, - dma16); + dev_info(card->dev, "IRQ: %d DMA8: %d DMA16: %d\n", irq, dma8, dma16); err = snd_sbdsp_create(card, sb_base, irq, snd_sb16dsp_interrupt, dma8, dma16, SB_HW_CS5530, &chip->sb); if (err < 0) { - printk(KERN_ERR "CS5530: Could not create SoundBlaster\n"); + dev_err(card->dev, "Could not create SoundBlaster\n"); snd_cs5530_free(chip); return err; } err = snd_sb16dsp_pcm(chip->sb, 0, &chip->sb->pcm); if (err < 0) { - printk(KERN_ERR "CS5530: Could not create PCM\n"); + dev_err(card->dev, "Could not create PCM\n"); snd_cs5530_free(chip); return err; } err = snd_sbmixer_new(chip->sb); if (err < 0) { - printk(KERN_ERR "CS5530: Could not create Mixer\n"); + dev_err(card->dev, "Could not create Mixer\n"); snd_cs5530_free(chip); return err; } @@ -244,7 +243,6 @@ static int snd_cs5530_create(struct snd_card *card, return err; } - snd_card_set_dev(card, &pci->dev); *rchip = chip; return 0; } @@ -264,7 +262,8 @@ static int snd_cs5530_probe(struct pci_dev *pci, return -ENOENT; } - err = snd_card_create(index[dev], id[dev], THIS_MODULE, 0, &card); + err = snd_card_new(&pci->dev, index[dev], id[dev], THIS_MODULE, + 0, &card); if (err < 0) return err; diff --git a/sound/pci/cs5535audio/cs5535audio.c b/sound/pci/cs5535audio/cs5535audio.c index c0d2835344d..edcbbda5c48 100644 --- a/sound/pci/cs5535audio/cs5535audio.c +++ b/sound/pci/cs5535audio/cs5535audio.c @@ -84,7 +84,8 @@ static void wait_till_cmd_acked(struct cs5535audio *cs5535au, unsigned long time udelay(1); } while (--timeout); if (!timeout) - snd_printk(KERN_ERR "Failure writing to cs5535 codec\n"); + dev_err(cs5535au->card->dev, + "Failure writing to cs5535 codec\n"); } static unsigned short snd_cs5535audio_codec_read(struct cs5535audio *cs5535au, @@ -109,8 +110,9 @@ static unsigned short snd_cs5535audio_codec_read(struct cs5535audio *cs5535au, udelay(1); } while (--timeout); if (!timeout) - snd_printk(KERN_ERR "Failure reading codec reg 0x%x," - "Last value=0x%x\n", reg, val); + dev_err(cs5535au->card->dev, + "Failure reading codec reg 0x%x, Last value=0x%x\n", + reg, val); return (unsigned short) val; } @@ -168,7 +170,7 @@ static int snd_cs5535audio_mixer(struct cs5535audio *cs5535au) olpc_prequirks(card, &ac97); if ((err = snd_ac97_mixer(pbus, &ac97, &cs5535au->ac97)) < 0) { - snd_printk(KERN_ERR "mixer failed\n"); + dev_err(card->dev, "mixer failed\n"); return err; } @@ -176,7 +178,7 @@ static int snd_cs5535audio_mixer(struct cs5535audio *cs5535au) err = olpc_quirks(card, cs5535au->ac97); if (err < 0) { - snd_printk(KERN_ERR "olpc quirks failed\n"); + dev_err(card->dev, "olpc quirks failed\n"); return err; } @@ -194,8 +196,9 @@ static void process_bm0_irq(struct cs5535audio *cs5535au) dma = cs5535au->playback_substream->runtime->private_data; snd_pcm_period_elapsed(cs5535au->playback_substream); } else { - snd_printk(KERN_ERR "unexpected bm0 irq src, bm_stat=%x\n", - bm_stat); + dev_err(cs5535au->card->dev, + "unexpected bm0 irq src, bm_stat=%x\n", + bm_stat); } } @@ -241,8 +244,9 @@ static irqreturn_t snd_cs5535audio_interrupt(int irq, void *dev_id) process_bm1_irq(cs5535au); break; default: - snd_printk(KERN_ERR "Unexpected irq src: " - "0x%x\n", acc_irq_stat); + dev_err(cs5535au->card->dev, + "Unexpected irq src: 0x%x\n", + acc_irq_stat); break; } } @@ -287,7 +291,7 @@ static int snd_cs5535audio_create(struct snd_card *card, if (pci_set_dma_mask(pci, DMA_BIT_MASK(32)) < 0 || pci_set_consistent_dma_mask(pci, DMA_BIT_MASK(32)) < 0) { - printk(KERN_WARNING "unable to get 32bit dma\n"); + dev_warn(card->dev, "unable to get 32bit dma\n"); err = -ENXIO; goto pcifail; } @@ -312,7 +316,7 @@ static int snd_cs5535audio_create(struct snd_card *card, if (request_irq(pci->irq, snd_cs5535audio_interrupt, IRQF_SHARED, KBUILD_MODNAME, cs5535au)) { - snd_printk(KERN_ERR "unable to grab IRQ %d\n", pci->irq); + dev_err(card->dev, "unable to grab IRQ %d\n", pci->irq); err = -EBUSY; goto sndfail; } @@ -324,8 +328,6 @@ static int snd_cs5535audio_create(struct snd_card *card, cs5535au, &ops)) < 0) goto sndfail; - snd_card_set_dev(card, &pci->dev); - *rcs5535au = cs5535au; return 0; @@ -353,7 +355,8 @@ static int snd_cs5535audio_probe(struct pci_dev *pci, return -ENOENT; } - err = snd_card_create(index[dev], id[dev], THIS_MODULE, 0, &card); + err = snd_card_new(&pci->dev, index[dev], id[dev], THIS_MODULE, + 0, &card); if (err < 0) return err; diff --git a/sound/pci/cs5535audio/cs5535audio_olpc.c b/sound/pci/cs5535audio/cs5535audio_olpc.c index e6a44507d55..3b0fdaca8dc 100644 --- a/sound/pci/cs5535audio/cs5535audio_olpc.c +++ b/sound/pci/cs5535audio/cs5535audio_olpc.c @@ -36,7 +36,8 @@ void olpc_analog_input(struct snd_ac97 *ac97, int on) err = snd_ac97_update_bits(ac97, AC97_AD_TEST2, 1 << AC97_AD_HPFD_SHIFT, on << AC97_AD_HPFD_SHIFT); if (err < 0) { - snd_printk(KERN_ERR "setting High Pass Filter - %d\n", err); + dev_err(ac97->bus->card->dev, + "setting High Pass Filter - %d\n", err); return; } @@ -58,7 +59,7 @@ void olpc_mic_bias(struct snd_ac97 *ac97, int on) err = snd_ac97_update_bits(ac97, AC97_AD_MISC, 1 << AC97_AD_VREFD_SHIFT, on << AC97_AD_VREFD_SHIFT); if (err < 0) - snd_printk(KERN_ERR "setting MIC Bias - %d\n", err); + dev_err(ac97->bus->card->dev, "setting MIC Bias - %d\n", err); } static int olpc_dc_info(struct snd_kcontrol *kctl, @@ -153,7 +154,7 @@ int olpc_quirks(struct snd_card *card, struct snd_ac97 *ac97) return 0; if (gpio_request(OLPC_GPIO_MIC_AC, DRV_NAME)) { - printk(KERN_ERR DRV_NAME ": unable to allocate MIC GPIO\n"); + dev_err(card->dev, "unable to allocate MIC GPIO\n"); return -EIO; } gpio_direction_output(OLPC_GPIO_MIC_AC, 0); diff --git a/sound/pci/cs5535audio/cs5535audio_pcm.c b/sound/pci/cs5535audio/cs5535audio_pcm.c index 9ab01a7047c..9c2dc911d8d 100644 --- a/sound/pci/cs5535audio/cs5535audio_pcm.c +++ b/sound/pci/cs5535audio/cs5535audio_pcm.c @@ -317,7 +317,7 @@ static int snd_cs5535audio_trigger(struct snd_pcm_substream *substream, int cmd) dma->ops->disable_dma(cs5535au); break; default: - snd_printk(KERN_ERR "unhandled trigger\n"); + dev_err(cs5535au->card->dev, "unhandled trigger\n"); err = -EINVAL; break; } @@ -335,13 +335,13 @@ static snd_pcm_uframes_t snd_cs5535audio_pcm_pointer(struct snd_pcm_substream dma = substream->runtime->private_data; curdma = dma->ops->read_dma_pntr(cs5535au); if (curdma < dma->buf_addr) { - snd_printk(KERN_ERR "curdma=%x < %x bufaddr.\n", + dev_err(cs5535au->card->dev, "curdma=%x < %x bufaddr.\n", curdma, dma->buf_addr); return 0; } curdma -= dma->buf_addr; if (curdma >= dma->buf_bytes) { - snd_printk(KERN_ERR "diff=%x >= %x buf_bytes.\n", + dev_err(cs5535au->card->dev, "diff=%x >= %x buf_bytes.\n", curdma, dma->buf_bytes); return 0; } diff --git a/sound/pci/cs5535audio/cs5535audio_pm.c b/sound/pci/cs5535audio/cs5535audio_pm.c index 6c34def5986..34cc60057d0 100644 --- a/sound/pci/cs5535audio/cs5535audio_pm.c +++ b/sound/pci/cs5535audio/cs5535audio_pm.c @@ -74,7 +74,7 @@ static int snd_cs5535audio_suspend(struct device *dev) snd_cs5535audio_stop_hardware(cs5535au); if (pci_save_state(pci)) { - printk(KERN_ERR "cs5535audio: pci_save_state failed!\n"); + dev_err(dev, "pci_save_state failed!\n"); return -EIO; } pci_disable_device(pci); @@ -94,8 +94,7 @@ static int snd_cs5535audio_resume(struct device *dev) pci_set_power_state(pci, PCI_D0); pci_restore_state(pci); if (pci_enable_device(pci) < 0) { - printk(KERN_ERR "cs5535audio: pci_enable_device failed, " - "disabling device\n"); + dev_err(dev, "pci_enable_device failed, disabling device\n"); snd_card_disconnect(card); return -EIO; } @@ -113,7 +112,7 @@ static int snd_cs5535audio_resume(struct device *dev) } while (--timeout); if (!timeout) - snd_printk(KERN_ERR "Failure getting AC Link ready\n"); + dev_err(cs5535au->card->dev, "Failure getting AC Link ready\n"); /* set up rate regs, dma. actual initiation is done in trig */ for (i = 0; i < NUM_CS5535AUDIO_DMAS; i++) { diff --git a/sound/pci/ctxfi/ctatc.c b/sound/pci/ctxfi/ctatc.c index eb86829529e..af632bd0832 100644 --- a/sound/pci/ctxfi/ctatc.c +++ b/sound/pci/ctxfi/ctatc.c @@ -1739,8 +1739,6 @@ int ct_atc_create(struct snd_card *card, struct pci_dev *pci, if (err < 0) goto error1; - snd_card_set_dev(card, &pci->dev); - *ratc = atc; return 0; diff --git a/sound/pci/ctxfi/xfi.c b/sound/pci/ctxfi/xfi.c index d464ad2fc7b..98426d09c8b 100644 --- a/sound/pci/ctxfi/xfi.c +++ b/sound/pci/ctxfi/xfi.c @@ -71,7 +71,8 @@ ct_card_probe(struct pci_dev *pci, const struct pci_device_id *pci_id) dev++; return -ENOENT; } - err = snd_card_create(index[dev], id[dev], THIS_MODULE, 0, &card); + err = snd_card_new(&pci->dev, index[dev], id[dev], THIS_MODULE, + 0, &card); if (err) return err; if ((reference_rate != 48000) && (reference_rate != 44100)) { diff --git a/sound/pci/echoaudio/echoaudio.c b/sound/pci/echoaudio/echoaudio.c index 05cfe551ce4..9f10c9e0df5 100644 --- a/sound/pci/echoaudio/echoaudio.c +++ b/sound/pci/echoaudio/echoaudio.c @@ -58,7 +58,8 @@ static int get_firmware(const struct firmware **fw_entry, snprintf(name, sizeof(name), "ea/%s", card_fw[fw_index].data); err = request_firmware(fw_entry, name, pci_device(chip)); if (err < 0) - snd_printk(KERN_ERR "get_firmware(): Firmware not available (%d)\n", err); + dev_err(chip->card->dev, + "get_firmware(): Firmware not available (%d)\n", err); #ifdef CONFIG_PM_SLEEP else chip->fw_cache[fw_index] = *fw_entry; @@ -563,7 +564,7 @@ static int init_engine(struct snd_pcm_substream *substream, err = snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params)); if (err < 0) { - snd_printk(KERN_ERR "malloc_pages err=%d\n", err); + dev_err(chip->card->dev, "malloc_pages err=%d\n", err); spin_lock_irq(&chip->lock); free_pipes(chip, pipe); spin_unlock_irq(&chip->lock); @@ -1989,8 +1990,8 @@ static int snd_echo_create(struct snd_card *card, if ((chip->iores = request_mem_region(chip->dsp_registers_phys, sz, ECHOCARD_NAME)) == NULL) { + dev_err(chip->card->dev, "cannot get memory region\n"); snd_echo_free(chip); - snd_printk(KERN_ERR "cannot get memory region\n"); return -EBUSY; } chip->dsp_registers = (volatile u32 __iomem *) @@ -1998,8 +1999,8 @@ static int snd_echo_create(struct snd_card *card, if (request_irq(pci->irq, snd_echo_interrupt, IRQF_SHARED, KBUILD_MODNAME, chip)) { + dev_err(chip->card->dev, "cannot grab irq\n"); snd_echo_free(chip); - snd_printk(KERN_ERR "cannot grab irq\n"); return -EBUSY; } chip->irq = pci->irq; @@ -2011,8 +2012,8 @@ static int snd_echo_create(struct snd_card *card, if (snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(chip->pci), sizeof(struct comm_page), &chip->commpage_dma_buf) < 0) { + dev_err(chip->card->dev, "cannot allocate the comm page\n"); snd_echo_free(chip); - snd_printk(KERN_ERR "cannot allocate the comm page\n"); return -ENOMEM; } chip->comm_page_phys = chip->commpage_dma_buf.addr; @@ -2058,12 +2059,11 @@ static int snd_echo_probe(struct pci_dev *pci, DE_INIT(("Echoaudio driver starting...\n")); i = 0; - err = snd_card_create(index[dev], id[dev], THIS_MODULE, 0, &card); + err = snd_card_new(&pci->dev, index[dev], id[dev], THIS_MODULE, + 0, &card); if (err < 0) return err; - snd_card_set_dev(card, &pci->dev); - chip = NULL; /* Tells snd_echo_create to allocate chip */ if ((err = snd_echo_create(card, pci, &chip)) < 0) { snd_card_free(card); @@ -2082,7 +2082,7 @@ static int snd_echo_probe(struct pci_dev *pci, chip->dsp_registers_phys, chip->irq); if ((err = snd_echo_new_pcm(chip)) < 0) { - snd_printk(KERN_ERR "new pcm error %d\n", err); + dev_err(chip->card->dev, "new pcm error %d\n", err); snd_card_free(card); return err; } @@ -2090,7 +2090,7 @@ static int snd_echo_probe(struct pci_dev *pci, #ifdef ECHOCARD_HAS_MIDI if (chip->has_midi) { /* Some Mia's do not have midi */ if ((err = snd_echo_midi_create(card, chip)) < 0) { - snd_printk(KERN_ERR "new midi error %d\n", err); + dev_err(chip->card->dev, "new midi error %d\n", err); snd_card_free(card); return err; } @@ -2189,14 +2189,14 @@ static int snd_echo_probe(struct pci_dev *pci, err = snd_card_register(card); if (err < 0) goto ctl_error; - snd_printk(KERN_INFO "Card registered: %s\n", card->longname); + dev_info(card->dev, "Card registered: %s\n", card->longname); pci_set_drvdata(pci, chip); dev++; return 0; ctl_error: - snd_printk(KERN_ERR "new control error %d\n", err); + dev_err(card->dev, "new control error %d\n", err); snd_card_free(card); return err; } @@ -2291,8 +2291,8 @@ static int snd_echo_resume(struct device *dev) if (request_irq(pci->irq, snd_echo_interrupt, IRQF_SHARED, KBUILD_MODNAME, chip)) { + dev_err(chip->card->dev, "cannot grab irq\n"); snd_echo_free(chip); - snd_printk(KERN_ERR "cannot grab irq\n"); return -EBUSY; } chip->irq = pci->irq; diff --git a/sound/pci/echoaudio/echoaudio_dsp.c b/sound/pci/echoaudio/echoaudio_dsp.c index d8c670c9d62..5a6a217b82e 100644 --- a/sound/pci/echoaudio/echoaudio_dsp.c +++ b/sound/pci/echoaudio/echoaudio_dsp.c @@ -53,7 +53,7 @@ static int wait_handshake(struct echoaudio *chip) udelay(1); } - snd_printk(KERN_ERR "wait_handshake(): Timeout waiting for DSP\n"); + dev_err(chip->card->dev, "wait_handshake(): Timeout waiting for DSP\n"); return -EBUSY; } @@ -149,7 +149,8 @@ static int read_sn(struct echoaudio *chip) for (i = 0; i < 5; i++) { if (read_dsp(chip, &sn[i])) { - snd_printk(KERN_ERR "Failed to read serial number\n"); + dev_err(chip->card->dev, + "Failed to read serial number\n"); return -EIO; } } @@ -184,7 +185,7 @@ static int load_asic_generic(struct echoaudio *chip, u32 cmd, short asic) err = get_firmware(&fw, chip, asic); if (err < 0) { - snd_printk(KERN_WARNING "Firmware not found !\n"); + dev_warn(chip->card->dev, "Firmware not found !\n"); return err; } @@ -247,7 +248,7 @@ static int install_resident_loader(struct echoaudio *chip) i = get_firmware(&fw, chip, FW_361_LOADER); if (i < 0) { - snd_printk(KERN_WARNING "Firmware not found !\n"); + dev_warn(chip->card->dev, "Firmware not found !\n"); return i; } diff --git a/sound/pci/echoaudio/midi.c b/sound/pci/echoaudio/midi.c index abfd51c2530..7f4dfae0323 100644 --- a/sound/pci/echoaudio/midi.c +++ b/sound/pci/echoaudio/midi.c @@ -221,7 +221,8 @@ static void snd_echo_midi_output_write(unsigned long data) DE_MID(("Try to send %d bytes...\n", bytes)); sent = write_midi(chip, buf, bytes); if (sent < 0) { - snd_printk(KERN_ERR "write_midi() error %d\n", sent); + dev_err(chip->card->dev, + "write_midi() error %d\n", sent); /* retry later */ sent = 9000; chip->midi_full = 1; diff --git a/sound/pci/emu10k1/emu10k1.c b/sound/pci/emu10k1/emu10k1.c index 9e1bd0c39a8..ad9d9f8b48e 100644 --- a/sound/pci/emu10k1/emu10k1.c +++ b/sound/pci/emu10k1/emu10k1.c @@ -117,7 +117,8 @@ static int snd_card_emu10k1_probe(struct pci_dev *pci, return -ENOENT; } - err = snd_card_create(index[dev], id[dev], THIS_MODULE, 0, &card); + err = snd_card_new(&pci->dev, index[dev], id[dev], THIS_MODULE, + 0, &card); if (err < 0) return err; if (max_buffer_size[dev] < 32) @@ -169,7 +170,8 @@ static int snd_card_emu10k1_probe(struct pci_dev *pci, if (snd_seq_device_new(card, 1, SNDRV_SEQ_DEV_ID_EMU10K1_SYNTH, sizeof(struct snd_emu10k1_synth_arg), &wave) < 0 || wave == NULL) { - snd_printk(KERN_WARNING "can't initialize Emu10k1 wavetable synth\n"); + dev_warn(emu->card->dev, + "can't initialize Emu10k1 wavetable synth\n"); } else { struct snd_emu10k1_synth_arg *arg; arg = SNDRV_SEQ_DEVICE_ARGPTR(wave); @@ -246,8 +248,7 @@ static int snd_emu10k1_resume(struct device *dev) pci_set_power_state(pci, PCI_D0); pci_restore_state(pci); if (pci_enable_device(pci) < 0) { - printk(KERN_ERR "emu10k1: pci_enable_device failed, " - "disabling device\n"); + dev_err(dev, "pci_enable_device failed, disabling device\n"); snd_card_disconnect(card); return -EIO; } diff --git a/sound/pci/emu10k1/emu10k1_callback.c b/sound/pci/emu10k1/emu10k1_callback.c index cae36597aa7..3f3ef38d9b6 100644 --- a/sound/pci/emu10k1/emu10k1_callback.c +++ b/sound/pci/emu10k1/emu10k1_callback.c @@ -105,7 +105,7 @@ snd_emu10k1_synth_get_voice(struct snd_emu10k1 *hw) vp = &emu->voices[best[i].voice]; if ((ch = vp->ch) < 0) { /* - printk(KERN_WARNING + dev_warn(emu->card->dev, "synth_get_voice: ch < 0 (%d) ??", i); */ continue; @@ -339,7 +339,7 @@ start_voice(struct snd_emux_voice *vp) return -EINVAL; emem->map_locked++; if (snd_emu10k1_memblk_map(hw, emem) < 0) { - /* printk(KERN_ERR "emu: cannot map!\n"); */ + /* dev_err(hw->card->devK, "emu: cannot map!\n"); */ return -ENOMEM; } mapped_offset = snd_emu10k1_memblk_offset(emem) >> 1; diff --git a/sound/pci/emu10k1/emu10k1_main.c b/sound/pci/emu10k1/emu10k1_main.c index bdd888ec9a8..22926978802 100644 --- a/sound/pci/emu10k1/emu10k1_main.c +++ b/sound/pci/emu10k1/emu10k1_main.c @@ -217,7 +217,7 @@ static int snd_emu10k1_init(struct snd_emu10k1 *emu, int enable_ir, int resume) } if (emu->card_capabilities->ca0108_chip) { /* audigy2 Value */ /* Hacks for Alice3 to work independent of haP16V driver */ - snd_printk(KERN_INFO "Audigy2 value: Special config.\n"); + dev_info(emu->card->dev, "Audigy2 value: Special config.\n"); /* Setup SRCMulti_I2S SamplingRate */ tmp = snd_emu10k1_ptr_read(emu, A_SPDIF_SAMPLERATE, 0); tmp &= 0xfffff1ff; @@ -723,7 +723,8 @@ static int emu1010_firmware_thread(void *data) if (reg & EMU_HANA_OPTION_DOCK_OFFLINE) { /* Audio Dock attached */ /* Return to Audio Dock programming mode */ - snd_printk(KERN_INFO "emu1010: Loading Audio Dock Firmware\n"); + dev_info(emu->card->dev, + "emu1010: Loading Audio Dock Firmware\n"); snd_emu1010_fpga_write(emu, EMU_HANA_FPGA_CONFIG, EMU_HANA_FPGA_CONFIG_AUDIODOCK); if (!emu->dock_fw) { @@ -756,19 +757,25 @@ static int emu1010_firmware_thread(void *data) snd_emu1010_fpga_write(emu, EMU_HANA_FPGA_CONFIG, 0); snd_emu1010_fpga_read(emu, EMU_HANA_IRQ_STATUS, ®); - snd_printk(KERN_INFO "emu1010: EMU_HANA+DOCK_IRQ_STATUS = 0x%x\n", reg); + dev_info(emu->card->dev, + "emu1010: EMU_HANA+DOCK_IRQ_STATUS = 0x%x\n", + reg); /* ID, should read & 0x7f = 0x55 when FPGA programmed. */ snd_emu1010_fpga_read(emu, EMU_HANA_ID, ®); - snd_printk(KERN_INFO "emu1010: EMU_HANA+DOCK_ID = 0x%x\n", reg); + dev_info(emu->card->dev, + "emu1010: EMU_HANA+DOCK_ID = 0x%x\n", reg); if ((reg & 0x1f) != 0x15) { /* FPGA failed to be programmed */ - snd_printk(KERN_INFO "emu1010: Loading Audio Dock Firmware file failed, reg = 0x%x\n", reg); + dev_info(emu->card->dev, + "emu1010: Loading Audio Dock Firmware file failed, reg = 0x%x\n", + reg); continue; } - snd_printk(KERN_INFO "emu1010: Audio Dock Firmware loaded\n"); + dev_info(emu->card->dev, + "emu1010: Audio Dock Firmware loaded\n"); snd_emu1010_fpga_read(emu, EMU_DOCK_MAJOR_REV, &tmp); snd_emu1010_fpga_read(emu, EMU_DOCK_MINOR_REV, &tmp2); - snd_printk(KERN_INFO "Audio Dock ver: %u.%u\n", + dev_info(emu->card->dev, "Audio Dock ver: %u.%u\n", tmp, tmp2); /* Sync clocking between 1010 and Dock */ /* Allow DLL to settle */ @@ -777,7 +784,7 @@ static int emu1010_firmware_thread(void *data) snd_emu1010_fpga_write(emu, EMU_HANA_UNMUTE, EMU_UNMUTE); } } - snd_printk(KERN_INFO "emu1010: firmware thread stopping\n"); + dev_info(emu->card->dev, "emu1010: firmware thread stopping\n"); return 0; } @@ -818,7 +825,7 @@ static int snd_emu10k1_emu1010_init(struct snd_emu10k1 *emu) u32 tmp, tmp2, reg; int err; - snd_printk(KERN_INFO "emu1010: Special config.\n"); + dev_info(emu->card->dev, "emu1010: Special config.\n"); /* AC97 2.1, Any 16Meg of 4Gig address, Auto-Mute, EMU32 Slave, * Lock Sound Memory Cache, Lock Tank Memory Cache, * Mute all codecs. @@ -843,7 +850,7 @@ static int snd_emu10k1_emu1010_init(struct snd_emu10k1 *emu) /* ID, should read & 0x7f = 0x55. (Bit 7 is the IRQ bit) */ snd_emu1010_fpga_read(emu, EMU_HANA_ID, ®); - snd_printdd("reg1 = 0x%x\n", reg); + dev_dbg(emu->card->dev, "reg1 = 0x%x\n", reg); if ((reg & 0x3f) == 0x15) { /* FPGA netlist already present so clear it */ /* Return to programming mode */ @@ -851,13 +858,14 @@ static int snd_emu10k1_emu1010_init(struct snd_emu10k1 *emu) snd_emu1010_fpga_write(emu, EMU_HANA_FPGA_CONFIG, 0x02); } snd_emu1010_fpga_read(emu, EMU_HANA_ID, ®); - snd_printdd("reg2 = 0x%x\n", reg); + dev_dbg(emu->card->dev, "reg2 = 0x%x\n", reg); if ((reg & 0x3f) == 0x15) { /* FPGA failed to return to programming mode */ - snd_printk(KERN_INFO "emu1010: FPGA failed to return to programming mode\n"); + dev_info(emu->card->dev, + "emu1010: FPGA failed to return to programming mode\n"); return -ENODEV; } - snd_printk(KERN_INFO "emu1010: EMU_HANA_ID = 0x%x\n", reg); + dev_info(emu->card->dev, "emu1010: EMU_HANA_ID = 0x%x\n", reg); if (!emu->firmware) { const char *filename; @@ -880,16 +888,19 @@ static int snd_emu10k1_emu1010_init(struct snd_emu10k1 *emu) err = request_firmware(&emu->firmware, filename, &emu->pci->dev); if (err != 0) { - snd_printk(KERN_ERR "emu1010: firmware: %s not found. Err = %d\n", filename, err); + dev_info(emu->card->dev, + "emu1010: firmware: %s not found. Err = %d\n", + filename, err); return err; } - snd_printk(KERN_INFO "emu1010: firmware file = %s, size = 0x%zx\n", + dev_info(emu->card->dev, + "emu1010: firmware file = %s, size = 0x%zx\n", filename, emu->firmware->size); } err = snd_emu1010_load_firmware(emu, emu->firmware); if (err != 0) { - snd_printk(KERN_INFO "emu1010: Loading Firmware failed\n"); + dev_info(emu->card->dev, "emu1010: Loading Firmware failed\n"); return err; } @@ -897,21 +908,23 @@ static int snd_emu10k1_emu1010_init(struct snd_emu10k1 *emu) snd_emu1010_fpga_read(emu, EMU_HANA_ID, ®); if ((reg & 0x3f) != 0x15) { /* FPGA failed to be programmed */ - snd_printk(KERN_INFO "emu1010: Loading Hana Firmware file failed, reg = 0x%x\n", reg); + dev_info(emu->card->dev, + "emu1010: Loading Hana Firmware file failed, reg = 0x%x\n", + reg); return -ENODEV; } - snd_printk(KERN_INFO "emu1010: Hana Firmware loaded\n"); + dev_info(emu->card->dev, "emu1010: Hana Firmware loaded\n"); snd_emu1010_fpga_read(emu, EMU_HANA_MAJOR_REV, &tmp); snd_emu1010_fpga_read(emu, EMU_HANA_MINOR_REV, &tmp2); - snd_printk(KERN_INFO "emu1010: Hana version: %u.%u\n", tmp, tmp2); + dev_info(emu->card->dev, "emu1010: Hana version: %u.%u\n", tmp, tmp2); /* Enable 48Volt power to Audio Dock */ snd_emu1010_fpga_write(emu, EMU_HANA_DOCK_PWR, EMU_HANA_DOCK_PWR_ON); snd_emu1010_fpga_read(emu, EMU_HANA_OPTION_CARDS, ®); - snd_printk(KERN_INFO "emu1010: Card options = 0x%x\n", reg); + dev_info(emu->card->dev, "emu1010: Card options = 0x%x\n", reg); snd_emu1010_fpga_read(emu, EMU_HANA_OPTION_CARDS, ®); - snd_printk(KERN_INFO "emu1010: Card options = 0x%x\n", reg); + dev_info(emu->card->dev, "emu1010: Card options = 0x%x\n", reg); snd_emu1010_fpga_read(emu, EMU_HANA_OPTICAL_TYPE, &tmp); /* Optical -> ADAT I/O */ /* 0 : SPDIF @@ -950,7 +963,7 @@ static int snd_emu10k1_emu1010_init(struct snd_emu10k1 *emu) snd_emu1010_fpga_write(emu, EMU_HANA_IRQ_ENABLE, 0x00); snd_emu1010_fpga_read(emu, EMU_HANA_OPTION_CARDS, ®); - snd_printk(KERN_INFO "emu1010: Card options3 = 0x%x\n", reg); + dev_info(emu->card->dev, "emu1010: Card options3 = 0x%x\n", reg); /* Default WCLK set to 48kHz. */ snd_emu1010_fpga_write(emu, EMU_HANA_DEFCLOCK, 0x00); /* Word Clock source, Internal 48kHz x1 */ @@ -1808,7 +1821,9 @@ int snd_emu10k1_create(struct snd_card *card, emu->revision = pci->revision; pci_read_config_dword(pci, PCI_SUBSYSTEM_VENDOR_ID, &emu->serial); pci_read_config_word(pci, PCI_SUBSYSTEM_ID, &emu->model); - snd_printdd("vendor = 0x%x, device = 0x%x, subsystem_vendor_id = 0x%x, subsystem_id = 0x%x\n", pci->vendor, pci->device, emu->serial, emu->model); + dev_dbg(card->dev, + "vendor = 0x%x, device = 0x%x, subsystem_vendor_id = 0x%x, subsystem_id = 0x%x\n", + pci->vendor, pci->device, emu->serial, emu->model); for (c = emu_chip_details; c->vendor; c++) { if (c->vendor == pci->vendor && c->device == pci->device) { @@ -1827,21 +1842,21 @@ int snd_emu10k1_create(struct snd_card *card, } } if (c->vendor == 0) { - snd_printk(KERN_ERR "emu10k1: Card not recognised\n"); + dev_err(card->dev, "emu10k1: Card not recognised\n"); kfree(emu); pci_disable_device(pci); return -ENOENT; } emu->card_capabilities = c; if (c->subsystem && !subsystem) - snd_printdd("Sound card name = %s\n", c->name); + dev_dbg(card->dev, "Sound card name = %s\n", c->name); else if (subsystem) - snd_printdd("Sound card name = %s, " + dev_dbg(card->dev, "Sound card name = %s, " "vendor = 0x%x, device = 0x%x, subsystem = 0x%x. " "Forced to subsystem = 0x%x\n", c->name, pci->vendor, pci->device, emu->serial, c->subsystem); else - snd_printdd("Sound card name = %s, " + dev_dbg(card->dev, "Sound card name = %s, " "vendor = 0x%x, device = 0x%x, subsystem = 0x%x.\n", c->name, pci->vendor, pci->device, emu->serial); @@ -1869,7 +1884,9 @@ int snd_emu10k1_create(struct snd_card *card, emu->dma_mask = is_audigy ? AUDIGY_DMA_MASK : EMU10K1_DMA_MASK; if (pci_set_dma_mask(pci, emu->dma_mask) < 0 || pci_set_consistent_dma_mask(pci, emu->dma_mask) < 0) { - snd_printk(KERN_ERR "architecture does not support PCI busmaster DMA with mask 0x%lx\n", emu->dma_mask); + dev_err(card->dev, + "architecture does not support PCI busmaster DMA with mask 0x%lx\n", + emu->dma_mask); kfree(emu); pci_disable_device(pci); return -ENXIO; @@ -2021,7 +2038,6 @@ int snd_emu10k1_create(struct snd_card *card, snd_emu10k1_proc_init(emu); #endif - snd_card_set_dev(card, &pci->dev); *remu = emu; return 0; diff --git a/sound/pci/emu10k1/emu10k1_patch.c b/sound/pci/emu10k1/emu10k1_patch.c index 662a45876a8..0e069aeab86 100644 --- a/sound/pci/emu10k1/emu10k1_patch.c +++ b/sound/pci/emu10k1/emu10k1_patch.c @@ -50,7 +50,8 @@ snd_emu10k1_sample_new(struct snd_emux *rec, struct snd_sf_sample *sp, return -EINVAL; if (sp->v.size == 0) { - snd_printd("emu: rom font for sample %d\n", sp->v.sample); + dev_dbg(emu->card->dev, + "emu: rom font for sample %d\n", sp->v.sample); return 0; } @@ -92,7 +93,8 @@ snd_emu10k1_sample_new(struct snd_emux *rec, struct snd_sf_sample *sp, blocksize *= 2; sp->block = snd_emu10k1_synth_alloc(emu, blocksize); if (sp->block == NULL) { - snd_printd("emu10k1: synth malloc failed (size=%d)\n", blocksize); + dev_dbg(emu->card->dev, + "synth malloc failed (size=%d)\n", blocksize); /* not ENOMEM (for compatibility with OSS) */ return -ENOSPC; } diff --git a/sound/pci/emu10k1/emu10k1x.c b/sound/pci/emu10k1/emu10k1x.c index 56ad9d6f200..efe01752697 100644 --- a/sound/pci/emu10k1/emu10k1x.c +++ b/sound/pci/emu10k1/emu10k1x.c @@ -369,7 +369,8 @@ static void snd_emu10k1x_pcm_interrupt(struct emu10k1x *emu, struct emu10k1x_voi if (epcm->substream == NULL) return; #if 0 - snd_printk(KERN_INFO "IRQ: position = 0x%x, period = 0x%x, size = 0x%x\n", + dev_info(emu->card->dev, + "IRQ: position = 0x%x, period = 0x%x, size = 0x%x\n", epcm->substream->ops->pointer(epcm->substream), snd_pcm_lib_period_bytes(epcm->substream), snd_pcm_lib_buffer_bytes(epcm->substream)); @@ -487,7 +488,11 @@ static int snd_emu10k1x_pcm_trigger(struct snd_pcm_substream *substream, int channel = epcm->voice->number; int result = 0; -// snd_printk(KERN_INFO "trigger - emu10k1x = 0x%x, cmd = %i, pointer = %d\n", (int)emu, cmd, (int)substream->ops->pointer(substream)); + /* + dev_dbg(emu->card->dev, + "trigger - emu10k1x = 0x%x, cmd = %i, pointer = %d\n", + (int)emu, cmd, (int)substream->ops->pointer(substream)); + */ switch (cmd) { case SNDRV_PCM_TRIGGER_START: @@ -826,7 +831,7 @@ static irqreturn_t snd_emu10k1x_interrupt(int irq, void *dev_id) // acknowledge the interrupt if necessary outl(status, chip->port + IPR); - // snd_printk(KERN_INFO "interrupt %08x\n", status); + /* dev_dbg(chip->card->dev, "interrupt %08x\n", status); */ return IRQ_HANDLED; } @@ -919,7 +924,7 @@ static int snd_emu10k1x_create(struct snd_card *card, return err; if (pci_set_dma_mask(pci, DMA_BIT_MASK(28)) < 0 || pci_set_consistent_dma_mask(pci, DMA_BIT_MASK(28)) < 0) { - snd_printk(KERN_ERR "error to set 28bit mask DMA\n"); + dev_err(card->dev, "error to set 28bit mask DMA\n"); pci_disable_device(pci); return -ENXIO; } @@ -940,14 +945,15 @@ static int snd_emu10k1x_create(struct snd_card *card, chip->port = pci_resource_start(pci, 0); if ((chip->res_port = request_region(chip->port, 8, "EMU10K1X")) == NULL) { - snd_printk(KERN_ERR "emu10k1x: cannot allocate the port 0x%lx\n", chip->port); + dev_err(card->dev, "cannot allocate the port 0x%lx\n", + chip->port); snd_emu10k1x_free(chip); return -EBUSY; } if (request_irq(pci->irq, snd_emu10k1x_interrupt, IRQF_SHARED, KBUILD_MODNAME, chip)) { - snd_printk(KERN_ERR "emu10k1x: cannot grab irq %d\n", pci->irq); + dev_err(card->dev, "cannot grab irq %d\n", pci->irq); snd_emu10k1x_free(chip); return -EBUSY; } @@ -964,7 +970,7 @@ static int snd_emu10k1x_create(struct snd_card *card, chip->revision = pci->revision; pci_read_config_dword(pci, PCI_SUBSYSTEM_VENDOR_ID, &chip->serial); pci_read_config_word(pci, PCI_SUBSYSTEM_ID, &chip->model); - snd_printk(KERN_INFO "Model %04x Rev %08x Serial %08x\n", chip->model, + dev_info(card->dev, "Model %04x Rev %08x Serial %08x\n", chip->model, chip->revision, chip->serial); outl(0, chip->port + INTE); @@ -1248,7 +1254,9 @@ static void mpu401_clear_rx(struct emu10k1x *emu, struct emu10k1x_midi *mpu) mpu401_read_data(emu, mpu); #ifdef CONFIG_SND_DEBUG if (timeout <= 0) - snd_printk(KERN_ERR "cmd: clear rx timeout (status = 0x%x)\n", mpu401_read_stat(emu, mpu)); + dev_err(emu->card->dev, + "cmd: clear rx timeout (status = 0x%x)\n", + mpu401_read_stat(emu, mpu)); #endif } @@ -1322,7 +1330,8 @@ static int snd_emu10k1x_midi_cmd(struct emu10k1x * emu, } spin_unlock_irqrestore(&midi->input_lock, flags); if (!ok) { - snd_printk(KERN_ERR "midi_cmd: 0x%x failed at 0x%lx (status = 0x%x, data = 0x%x)!!!\n", + dev_err(emu->card->dev, + "midi_cmd: 0x%x failed at 0x%lx (status = 0x%x, data = 0x%x)!!!\n", cmd, emu->port, mpu401_read_stat(emu, midi), mpu401_read_data(emu, midi)); @@ -1564,7 +1573,8 @@ static int snd_emu10k1x_probe(struct pci_dev *pci, return -ENOENT; } - err = snd_card_create(index[dev], id[dev], THIS_MODULE, 0, &card); + err = snd_card_new(&pci->dev, index[dev], id[dev], THIS_MODULE, + 0, &card); if (err < 0) return err; @@ -1608,8 +1618,6 @@ static int snd_emu10k1x_probe(struct pci_dev *pci, sprintf(card->longname, "%s at 0x%lx irq %i", card->shortname, chip->port, chip->irq); - snd_card_set_dev(card, &pci->dev); - if ((err = snd_card_register(card)) < 0) { snd_card_free(card); return err; diff --git a/sound/pci/emu10k1/emufx.c b/sound/pci/emu10k1/emufx.c index 1f9c7c4bbcd..745f0627c63 100644 --- a/sound/pci/emu10k1/emufx.c +++ b/sound/pci/emu10k1/emufx.c @@ -1547,7 +1547,7 @@ A_OP(icode, &ptr, iMAC0, A_GPR(var), A_GPR(var), A_GPR(vol), A_EXTIN(input)) /* A_PUT_STEREO_OUTPUT(A_EXTOUT_FRONT_L, A_EXTOUT_FRONT_R, playback + SND_EMU10K1_PLAYBACK_CHANNELS); */ if (emu->card_capabilities->emu_model) { /* EMU1010 Outputs from PCM Front, Rear, Center, LFE, Side */ - snd_printk(KERN_INFO "EMU outputs on\n"); + dev_info(emu->card->dev, "EMU outputs on\n"); for (z = 0; z < 8; z++) { if (emu->card_capabilities->ca0108_chip) { A_OP(icode, &ptr, iACC3, A3_EMU32OUT(z), A_GPR(playback + SND_EMU10K1_PLAYBACK_CHANNELS + z), A_C_00000000, A_C_00000000); @@ -1571,7 +1571,9 @@ A_OP(icode, &ptr, iMAC0, A_GPR(var), A_GPR(var), A_GPR(vol), A_EXTIN(input)) A_SWITCH(icode, &ptr, tmp + 1, playback + SND_EMU10K1_PLAYBACK_CHANNELS + z, tmp + 1); if ((z==1) && (emu->card_capabilities->spdif_bug)) { /* Due to a SPDIF output bug on some Audigy cards, this code delays the Right channel by 1 sample */ - snd_printk(KERN_INFO "Installing spdif_bug patch: %s\n", emu->card_capabilities->name); + dev_info(emu->card->dev, + "Installing spdif_bug patch: %s\n", + emu->card_capabilities->name); A_OP(icode, &ptr, iACC3, A_EXTOUT(A_EXTOUT_FRONT_L + z), A_GPR(gpr - 3), A_C_00000000, A_C_00000000); A_OP(icode, &ptr, iACC3, A_GPR(gpr - 3), A_GPR(tmp + 0), A_GPR(tmp + 1), A_C_00000000); } else { @@ -1595,7 +1597,7 @@ A_OP(icode, &ptr, iMAC0, A_GPR(var), A_GPR(var), A_GPR(vol), A_EXTIN(input)) if (emu->card_capabilities->emu_model) { if (emu->card_capabilities->ca0108_chip) { - snd_printk(KERN_INFO "EMU2 inputs on\n"); + dev_info(emu->card->dev, "EMU2 inputs on\n"); for (z = 0; z < 0x10; z++) { snd_emu10k1_audigy_dsp_convert_32_to_2x16( icode, &ptr, tmp, bit_shifter16, @@ -1603,11 +1605,11 @@ A_OP(icode, &ptr, iMAC0, A_GPR(var), A_GPR(var), A_GPR(vol), A_EXTIN(input)) A_FXBUS2(z*2) ); } } else { - snd_printk(KERN_INFO "EMU inputs on\n"); + dev_info(emu->card->dev, "EMU inputs on\n"); /* Capture 16 (originally 8) channels of S32_LE sound */ /* - printk(KERN_DEBUG "emufx.c: gpr=0x%x, tmp=0x%x\n", + dev_dbg(emu->card->dev, "emufx.c: gpr=0x%x, tmp=0x%x\n", gpr, tmp); */ /* For the EMU1010: How to get 32bit values from the DSP. High 16bits into L, low 16bits into R. */ diff --git a/sound/pci/emu10k1/emumixer.c b/sound/pci/emu10k1/emumixer.c index f6c3da0d377..c5ae2a24d8a 100644 --- a/sound/pci/emu10k1/emumixer.c +++ b/sound/pci/emu10k1/emumixer.c @@ -1853,8 +1853,10 @@ int snd_emu10k1_mixer(struct snd_emu10k1 *emu, if ((err = snd_ac97_mixer(pbus, &ac97, &emu->ac97)) < 0) { if (emu->card_capabilities->ac97_chip == 1) return err; - snd_printd(KERN_INFO "emu10k1: AC97 is optional on this board\n"); - snd_printd(KERN_INFO" Proceeding without ac97 mixers...\n"); + dev_info(emu->card->dev, + "AC97 is optional on this board\n"); + dev_info(emu->card->dev, + "Proceeding without ac97 mixers...\n"); snd_device_free(emu->card, pbus); goto no_ac97; /* FIXME: get rid of ugly gotos.. */ } diff --git a/sound/pci/emu10k1/emumpu401.c b/sound/pci/emu10k1/emumpu401.c index 1ec91246dfe..fdf2b0ada48 100644 --- a/sound/pci/emu10k1/emumpu401.c +++ b/sound/pci/emu10k1/emumpu401.c @@ -64,7 +64,9 @@ static void mpu401_clear_rx(struct snd_emu10k1 *emu, struct snd_emu10k1_midi *mp mpu401_read_data(emu, mpu); #ifdef CONFIG_SND_DEBUG if (timeout <= 0) - snd_printk(KERN_ERR "cmd: clear rx timeout (status = 0x%x)\n", mpu401_read_stat(emu, mpu)); + dev_err(emu->card->dev, + "cmd: clear rx timeout (status = 0x%x)\n", + mpu401_read_stat(emu, mpu)); #endif } @@ -141,7 +143,8 @@ static int snd_emu10k1_midi_cmd(struct snd_emu10k1 * emu, struct snd_emu10k1_mid } spin_unlock_irqrestore(&midi->input_lock, flags); if (!ok) { - snd_printk(KERN_ERR "midi_cmd: 0x%x failed at 0x%lx (status = 0x%x, data = 0x%x)!!!\n", + dev_err(emu->card->dev, + "midi_cmd: 0x%x failed at 0x%lx (status = 0x%x, data = 0x%x)!!!\n", cmd, emu->port, mpu401_read_stat(emu, midi), mpu401_read_data(emu, midi)); diff --git a/sound/pci/emu10k1/emupcm.c b/sound/pci/emu10k1/emupcm.c index 5ae1d045bdc..f82481bd254 100644 --- a/sound/pci/emu10k1/emupcm.c +++ b/sound/pci/emu10k1/emupcm.c @@ -44,7 +44,8 @@ static void snd_emu10k1_pcm_interrupt(struct snd_emu10k1 *emu, if (epcm->substream == NULL) return; #if 0 - printk(KERN_DEBUG "IRQ: position = 0x%x, period = 0x%x, size = 0x%x\n", + dev_dbg(emu->card->dev, + "IRQ: position = 0x%x, period = 0x%x, size = 0x%x\n", epcm->substream->runtime->hw->pointer(emu, epcm->substream), snd_pcm_lib_period_bytes(epcm->substream), snd_pcm_lib_buffer_bytes(epcm->substream)); @@ -147,7 +148,7 @@ static int snd_emu10k1_pcm_channel_alloc(struct snd_emu10k1_pcm * epcm, int voic &epcm->extra); if (err < 0) { /* - printk(KERN_DEBUG "pcm_channel_alloc: " + dev_dbg(emu->card->dev, "pcm_channel_alloc: " "failed extra: voices=%d, frame=%d\n", voices, frame); */ @@ -761,7 +762,8 @@ static int snd_emu10k1_playback_trigger(struct snd_pcm_substream *substream, int result = 0; /* - printk(KERN_DEBUG "trigger - emu10k1 = 0x%x, cmd = %i, pointer = %i\n", + dev_dbg(emu->card->dev, + "trigger - emu10k1 = 0x%x, cmd = %i, pointer = %i\n", (int)emu, cmd, substream->ops->pointer(substream)) */ spin_lock(&emu->reg_lock); @@ -815,7 +817,7 @@ static int snd_emu10k1_capture_trigger(struct snd_pcm_substream *substream, outl(epcm->capture_ipr, emu->port + IPR); snd_emu10k1_intr_enable(emu, epcm->capture_inte); /* - printk(KERN_DEBUG "adccr = 0x%x, adcbs = 0x%x\n", + dev_dbg(emu->card->dev, "adccr = 0x%x, adcbs = 0x%x\n", epcm->adccr, epcm->adcbs); */ switch (epcm->type) { @@ -826,7 +828,10 @@ static int snd_emu10k1_capture_trigger(struct snd_pcm_substream *substream, if (emu->audigy) { snd_emu10k1_ptr_write(emu, A_FXWC1, 0, epcm->capture_cr_val); snd_emu10k1_ptr_write(emu, A_FXWC2, 0, epcm->capture_cr_val2); - snd_printdd("cr_val=0x%x, cr_val2=0x%x\n", epcm->capture_cr_val, epcm->capture_cr_val2); + dev_dbg(emu->card->dev, + "cr_val=0x%x, cr_val2=0x%x\n", + epcm->capture_cr_val, + epcm->capture_cr_val2); } else snd_emu10k1_ptr_write(emu, FXWC, 0, epcm->capture_cr_val); break; @@ -889,7 +894,7 @@ static snd_pcm_uframes_t snd_emu10k1_playback_pointer(struct snd_pcm_substream * } #endif /* - printk(KERN_DEBUG + dev_dbg(emu->card->dev, "ptr = 0x%lx, buffer_size = 0x%lx, period_size = 0x%lx\n", (long)ptr, (long)runtime->buffer_size, (long)runtime->period_size); @@ -1594,7 +1599,8 @@ static void snd_emu10k1_fx8010_playback_tram_poke1(unsigned short *dst_left, unsigned int tram_shift) { /* - printk(KERN_DEBUG "tram_poke1: dst_left = 0x%p, dst_right = 0x%p, " + dev_dbg(emu->card->dev, + "tram_poke1: dst_left = 0x%p, dst_right = 0x%p, " "src = 0x%p, count = 0x%x\n", dst_left, dst_right, src, count); */ @@ -1675,7 +1681,7 @@ static int snd_emu10k1_fx8010_playback_prepare(struct snd_pcm_substream *substre unsigned int i; /* - printk(KERN_DEBUG "prepare: etram_pages = 0x%p, dma_area = 0x%x, " + dev_dbg(emu->card->dev, "prepare: etram_pages = 0x%p, dma_area = 0x%x, " "buffer_size = 0x%x (0x%x)\n", emu->fx8010.etram_pages, runtime->dma_area, runtime->buffer_size, runtime->buffer_size << 2); diff --git a/sound/pci/emu10k1/io.c b/sound/pci/emu10k1/io.c index e4fba49fee4..706b4f0c680 100644 --- a/sound/pci/emu10k1/io.c +++ b/sound/pci/emu10k1/io.c @@ -71,11 +71,8 @@ void snd_emu10k1_ptr_write(struct snd_emu10k1 *emu, unsigned int reg, unsigned i unsigned long flags; unsigned int mask; - if (!emu) { - snd_printk(KERN_ERR "ptr_write: emu is null!\n"); - dump_stack(); + if (snd_BUG_ON(!emu)) return; - } mask = emu->audigy ? A_PTR_ADDRESS_MASK : PTR_ADDRESS_MASK; regptr = ((reg << 16) & mask) | (chn & PTR_CHANNELNUM_MASK); @@ -199,7 +196,7 @@ int snd_emu10k1_i2c_write(struct snd_emu10k1 *emu, int err = 0; if ((reg > 0x7f) || (value > 0x1ff)) { - snd_printk(KERN_ERR "i2c_write: invalid values.\n"); + dev_err(emu->card->dev, "i2c_write: invalid values.\n"); return -EINVAL; } @@ -227,7 +224,7 @@ int snd_emu10k1_i2c_write(struct snd_emu10k1 *emu, break; if (timeout > 1000) { - snd_printk(KERN_WARNING + dev_warn(emu->card->dev, "emu10k1:I2C:timeout status=0x%x\n", status); break; @@ -239,8 +236,8 @@ int snd_emu10k1_i2c_write(struct snd_emu10k1 *emu, } if (retry == 10) { - snd_printk(KERN_ERR "Writing to ADC failed!\n"); - snd_printk(KERN_ERR "status=0x%x, reg=%d, value=%d\n", + dev_err(emu->card->dev, "Writing to ADC failed!\n"); + dev_err(emu->card->dev, "status=0x%x, reg=%d, value=%d\n", status, reg, value); /* dump_stack(); */ err = -EINVAL; diff --git a/sound/pci/emu10k1/irq.c b/sound/pci/emu10k1/irq.c index 30bfed6f833..3c5c5e3dc2d 100644 --- a/sound/pci/emu10k1/irq.c +++ b/sound/pci/emu10k1/irq.c @@ -41,11 +41,12 @@ irqreturn_t snd_emu10k1_interrupt(int irq, void *dev_id) orig_status = status; handled = 1; if ((status & 0xffffffff) == 0xffffffff) { - snd_printk(KERN_INFO "snd-emu10k1: Suspected sound card removal\n"); + dev_info(emu->card->dev, + "Suspected sound card removal\n"); break; } if (status & IPR_PCIERROR) { - snd_printk(KERN_ERR "interrupt: PCI error\n"); + dev_err(emu->card->dev, "interrupt: PCI error\n"); snd_emu10k1_intr_disable(emu, INTE_PCIERRORENABLE); status &= ~IPR_PCIERROR; } @@ -157,19 +158,22 @@ irqreturn_t snd_emu10k1_interrupt(int irq, void *dev_id) struct snd_emu10k1_voice *pvoice = &(emu->p16v_voices[0]); struct snd_emu10k1_voice *cvoice = &(emu->p16v_capture_voice); - //printk(KERN_INFO "status2=0x%x\n", status2); + /* dev_dbg(emu->card->dev, "status2=0x%x\n", status2); */ orig_status2 = status2; if(status2 & mask) { if(pvoice->use) { snd_pcm_period_elapsed(pvoice->epcm->substream); } else { - snd_printk(KERN_ERR "p16v: status: 0x%08x, mask=0x%08x, pvoice=%p, use=%d\n", status2, mask, pvoice, pvoice->use); + dev_err(emu->card->dev, + "p16v: status: 0x%08x, mask=0x%08x, pvoice=%p, use=%d\n", + status2, mask, pvoice, + pvoice->use); } } if(status2 & 0x110000) { - //printk(KERN_INFO "capture int found\n"); + /* dev_info(emu->card->dev, "capture int found\n"); */ if(cvoice->use) { - //printk(KERN_INFO "capture period_elapsed\n"); + /* dev_info(emu->card->dev, "capture period_elapsed\n"); */ snd_pcm_period_elapsed(cvoice->epcm->substream); } } @@ -180,7 +184,8 @@ irqreturn_t snd_emu10k1_interrupt(int irq, void *dev_id) if (status) { unsigned int bits; - snd_printk(KERN_ERR "emu10k1: unhandled interrupt: 0x%08x\n", status); + dev_err(emu->card->dev, + "unhandled interrupt: 0x%08x\n", status); //make sure any interrupts we don't handle are disabled: bits = INTE_FXDSPENABLE | INTE_PCIERRORENABLE | @@ -202,7 +207,7 @@ irqreturn_t snd_emu10k1_interrupt(int irq, void *dev_id) outl(orig_status, emu->port + IPR); /* ack all */ } if (timeout == 1000) - snd_printk(KERN_INFO "emu10k1 irq routine failure\n"); + dev_info(emu->card->dev, "emu10k1 irq routine failure\n"); return IRQ_RETVAL(handled); } diff --git a/sound/pci/emu10k1/memory.c b/sound/pci/emu10k1/memory.c index ae709c1ab3a..c68e6dd2fa6 100644 --- a/sound/pci/emu10k1/memory.c +++ b/sound/pci/emu10k1/memory.c @@ -236,11 +236,13 @@ __found_pages: static int is_valid_page(struct snd_emu10k1 *emu, dma_addr_t addr) { if (addr & ~emu->dma_mask) { - snd_printk(KERN_ERR "max memory size is 0x%lx (addr = 0x%lx)!!\n", emu->dma_mask, (unsigned long)addr); + dev_err(emu->card->dev, + "max memory size is 0x%lx (addr = 0x%lx)!!\n", + emu->dma_mask, (unsigned long)addr); return 0; } if (addr & (EMUPAGESIZE-1)) { - snd_printk(KERN_ERR "page is not aligned\n"); + dev_err(emu->card->dev, "page is not aligned\n"); return 0; } return 1; @@ -331,7 +333,8 @@ snd_emu10k1_alloc_pages(struct snd_emu10k1 *emu, struct snd_pcm_substream *subst else addr = snd_pcm_sgbuf_get_addr(substream, ofs); if (! is_valid_page(emu, addr)) { - printk(KERN_ERR "emu: failure page = %d\n", idx); + dev_err(emu->card->dev, + "emu: failure page = %d\n", idx); mutex_unlock(&hdr->block_mutex); return NULL; } @@ -507,7 +510,8 @@ static inline void *offset_ptr(struct snd_emu10k1 *emu, int page, int offset) return NULL; ptr = emu->page_ptr_table[page]; if (! ptr) { - printk(KERN_ERR "emu10k1: access to NULL ptr: page = %d\n", page); + dev_err(emu->card->dev, + "access to NULL ptr: page = %d\n", page); return NULL; } ptr += offset & (PAGE_SIZE - 1); diff --git a/sound/pci/emu10k1/p16v.c b/sound/pci/emu10k1/p16v.c index 7e2025cd6d9..a4fe7f0c945 100644 --- a/sound/pci/emu10k1/p16v.c +++ b/sound/pci/emu10k1/p16v.c @@ -168,7 +168,7 @@ static void snd_p16v_pcm_free_substream(struct snd_pcm_runtime *runtime) struct snd_emu10k1_pcm *epcm = runtime->private_data; if (epcm) { - /* snd_printk(KERN_DEBUG "epcm free: %p\n", epcm); */ + /* dev_dbg(emu->card->dev, "epcm free: %p\n", epcm); */ kfree(epcm); } } @@ -183,14 +183,14 @@ static int snd_p16v_pcm_open_playback_channel(struct snd_pcm_substream *substrea int err; epcm = kzalloc(sizeof(*epcm), GFP_KERNEL); - /* snd_printk(KERN_DEBUG "epcm kcalloc: %p\n", epcm); */ + /* dev_dbg(emu->card->dev, "epcm kcalloc: %p\n", epcm); */ if (epcm == NULL) return -ENOMEM; epcm->emu = emu; epcm->substream = substream; /* - snd_printk(KERN_DEBUG "epcm device=%d, channel_id=%d\n", + dev_dbg(emu->card->dev, "epcm device=%d, channel_id=%d\n", substream->pcm->device, channel_id); */ runtime->private_data = epcm; @@ -203,10 +203,10 @@ static int snd_p16v_pcm_open_playback_channel(struct snd_pcm_substream *substrea channel->use=1; #if 0 /* debug */ - snd_printk(KERN_DEBUG + dev_dbg(emu->card->dev, "p16v: open channel_id=%d, channel=%p, use=0x%x\n", channel_id, channel, channel->use); - printk(KERN_DEBUG "open:channel_id=%d, chip=%p, channel=%p\n", + dev_dbg(emu->card->dev, "open:channel_id=%d, chip=%p, channel=%p\n", channel_id, chip, channel); #endif /* debug */ /* channel->interrupt = snd_p16v_pcm_channel_interrupt; */ @@ -231,14 +231,14 @@ static int snd_p16v_pcm_open_capture_channel(struct snd_pcm_substream *substream int err; epcm = kzalloc(sizeof(*epcm), GFP_KERNEL); - /* snd_printk(KERN_DEBUG "epcm kcalloc: %p\n", epcm); */ + /* dev_dbg(emu->card->dev, "epcm kcalloc: %p\n", epcm); */ if (epcm == NULL) return -ENOMEM; epcm->emu = emu; epcm->substream = substream; /* - snd_printk(KERN_DEBUG "epcm device=%d, channel_id=%d\n", + dev_dbg(emu->card->dev, "epcm device=%d, channel_id=%d\n", substream->pcm->device, channel_id); */ runtime->private_data = epcm; @@ -251,10 +251,10 @@ static int snd_p16v_pcm_open_capture_channel(struct snd_pcm_substream *substream channel->use=1; #if 0 /* debug */ - snd_printk(KERN_DEBUG + dev_dbg(emu->card->dev, "p16v: open channel_id=%d, channel=%p, use=0x%x\n", channel_id, channel, channel->use); - printk(KERN_DEBUG "open:channel_id=%d, chip=%p, channel=%p\n", + dev_dbg(emu->card->dev, "open:channel_id=%d, chip=%p, channel=%p\n", channel_id, chip, channel); #endif /* debug */ /* channel->interrupt = snd_p16v_pcm_channel_interrupt; */ @@ -349,15 +349,18 @@ static int snd_p16v_pcm_prepare_playback(struct snd_pcm_substream *substream) u32 tmp; #if 0 /* debug */ - snd_printk(KERN_DEBUG "prepare:channel_number=%d, rate=%d, " + dev_dbg(emu->card->dev, + "prepare:channel_number=%d, rate=%d, " "format=0x%x, channels=%d, buffer_size=%ld, " "period_size=%ld, periods=%u, frames_to_bytes=%d\n", channel, runtime->rate, runtime->format, runtime->channels, runtime->buffer_size, runtime->period_size, runtime->periods, frames_to_bytes(runtime, 1)); - snd_printk(KERN_DEBUG "dma_addr=%x, dma_area=%p, table_base=%p\n", + dev_dbg(emu->card->dev, + "dma_addr=%x, dma_area=%p, table_base=%p\n", runtime->dma_addr, runtime->dma_area, table_base); - snd_printk(KERN_DEBUG "dma_addr=%x, dma_area=%p, dma_bytes(size)=%x\n", + dev_dbg(emu->card->dev, + "dma_addr=%x, dma_area=%p, dma_bytes(size)=%x\n", emu->p16v_buffer.addr, emu->p16v_buffer.area, emu->p16v_buffer.bytes); #endif /* debug */ @@ -405,7 +408,7 @@ static int snd_p16v_pcm_prepare_capture(struct snd_pcm_substream *substream) u32 tmp; /* - printk(KERN_DEBUG "prepare capture:channel_number=%d, rate=%d, " + dev_dbg(emu->card->dev, "prepare capture:channel_number=%d, rate=%d, " "format=0x%x, channels=%d, buffer_size=%ld, period_size=%ld, " "frames_to_bytes=%d\n", channel, runtime->rate, runtime->format, runtime->channels, @@ -491,13 +494,13 @@ static int snd_p16v_pcm_trigger_playback(struct snd_pcm_substream *substream, runtime = s->runtime; epcm = runtime->private_data; channel = substream->pcm->device-emu->p16v_device_offset; - /* snd_printk(KERN_DEBUG "p16v channel=%d\n", channel); */ + /* dev_dbg(emu->card->dev, "p16v channel=%d\n", channel); */ epcm->running = running; basic |= (0x1<<channel); inte |= (INTE2_PLAYBACK_CH_0_LOOP<<channel); snd_pcm_trigger_done(s, substream); } - /* snd_printk(KERN_DEBUG "basic=0x%x, inte=0x%x\n", basic, inte); */ + /* dev_dbg(emu->card->dev, "basic=0x%x, inte=0x%x\n", basic, inte); */ switch (cmd) { case SNDRV_PCM_TRIGGER_START: @@ -588,10 +591,10 @@ snd_p16v_pcm_pointer_capture(struct snd_pcm_substream *substream) ptr=ptr2; if (ptr >= runtime->buffer_size) { ptr -= runtime->buffer_size; - printk(KERN_WARNING "buffer capture limited!\n"); + dev_warn(emu->card->dev, "buffer capture limited!\n"); } /* - printk(KERN_DEBUG "ptr1 = 0x%lx, ptr2=0x%lx, ptr=0x%lx, " + dev_dbg(emu->card->dev, "ptr1 = 0x%lx, ptr2=0x%lx, ptr=0x%lx, " "buffer_size = 0x%x, period_size = 0x%x, bits=%d, rate=%d\n", ptr1, ptr2, ptr, (int)runtime->buffer_size, (int)runtime->period_size, (int)runtime->frame_bits, @@ -630,7 +633,7 @@ int snd_p16v_free(struct snd_emu10k1 *chip) if (chip->p16v_buffer.area) { snd_dma_free_pages(&chip->p16v_buffer); /* - snd_printk(KERN_DEBUG "period lables free: %p\n", + dev_dbg(chip->card->dev, "period lables free: %p\n", &chip->p16v_buffer); */ } @@ -644,7 +647,7 @@ int snd_p16v_pcm(struct snd_emu10k1 *emu, int device, struct snd_pcm **rpcm) int err; int capture=1; - /* snd_printk(KERN_DEBUG "snd_p16v_pcm called. device=%d\n", device); */ + /* dev_dbg(emu->card->dev, "snd_p16v_pcm called. device=%d\n", device); */ emu->p16v_device_offset = device; if (rpcm) *rpcm = NULL; @@ -672,7 +675,7 @@ int snd_p16v_pcm(struct snd_emu10k1 *emu, int device, struct snd_pcm **rpcm) ((65536 - 64) * 8), ((65536 - 64) * 8))) < 0) return err; /* - snd_printk(KERN_DEBUG + dev_dbg(emu->card->dev, "preallocate playback substream: err=%d\n", err); */ } @@ -686,7 +689,7 @@ int snd_p16v_pcm(struct snd_emu10k1 *emu, int device, struct snd_pcm **rpcm) 65536 - 64, 65536 - 64)) < 0) return err; /* - snd_printk(KERN_DEBUG + dev_dbg(emu->card->dev, "preallocate capture substream: err=%d\n", err); */ } diff --git a/sound/pci/emu10k1/voice.c b/sound/pci/emu10k1/voice.c index 101e7cb79cb..f16fd5cfb7c 100644 --- a/sound/pci/emu10k1/voice.c +++ b/sound/pci/emu10k1/voice.c @@ -55,7 +55,7 @@ static int voice_alloc(struct snd_emu10k1 *emu, int type, int number, first_voice = last_voice = 0; for (i = emu->next_free_voice, j = 0; j < NUM_G ; i += number, j += number) { /* - printk(KERN_DEBUG "i %d j %d next free %d!\n", + dev_dbg(emu->card->dev, "i %d j %d next free %d!\n", i, j, emu->next_free_voice); */ i %= NUM_G; @@ -75,7 +75,7 @@ static int voice_alloc(struct snd_emu10k1 *emu, int type, int number, } } if (!skip) { - /* printk(KERN_DEBUG "allocated voice %d\n", i); */ + /* dev_dbg(emu->card->dev, "allocated voice %d\n", i); */ first_voice = i; last_voice = (i + number) % NUM_G; emu->next_free_voice = last_voice; @@ -89,7 +89,7 @@ static int voice_alloc(struct snd_emu10k1 *emu, int type, int number, for (i = 0; i < number; i++) { voice = &emu->voices[(first_voice + i) % NUM_G]; /* - printk(kERN_DEBUG "voice alloc - %i, %i of %i\n", + dev_dbg(emu->card->dev, "voice alloc - %i, %i of %i\n", voice->number, idx-first_voice+1, number); */ voice->use = 1; diff --git a/sound/pci/ens1370.c b/sound/pci/ens1370.c index 61262f39600..29cd339ffc3 100644 --- a/sound/pci/ens1370.c +++ b/sound/pci/ens1370.c @@ -525,7 +525,7 @@ static unsigned int snd_es1371_wait_src_ready(struct ensoniq * ensoniq) return r; cond_resched(); } - snd_printk(KERN_ERR "wait src ready timeout 0x%lx [0x%x]\n", + dev_err(ensoniq->card->dev, "wait src ready timeout 0x%lx [0x%x]\n", ES_REG(ensoniq, 1371_SMPRATE), r); return 0; } @@ -587,7 +587,7 @@ static void snd_es1370_codec_write(struct snd_ak4531 *ak4531, unsigned long end_time = jiffies + HZ / 10; #if 0 - printk(KERN_DEBUG + dev_dbg(ensoniq->card->dev, "CODEC WRITE: reg = 0x%x, val = 0x%x (0x%x), creg = 0x%x\n", reg, val, ES_1370_CODEC_WRITE(reg, val), ES_REG(ensoniq, 1370_CODEC)); #endif @@ -598,7 +598,7 @@ static void snd_es1370_codec_write(struct snd_ak4531 *ak4531, } schedule_timeout_uninterruptible(1); } while (time_after(end_time, jiffies)); - snd_printk(KERN_ERR "codec write timeout, status = 0x%x\n", + dev_err(ensoniq->card->dev, "codec write timeout, status = 0x%x\n", inl(ES_REG(ensoniq, STATUS))); } @@ -649,7 +649,7 @@ static void snd_es1371_codec_write(struct snd_ac97 *ac97, } } mutex_unlock(&ensoniq->src_mutex); - snd_printk(KERN_ERR "codec write timeout at 0x%lx [0x%x]\n", + dev_err(ensoniq->card->dev, "codec write timeout at 0x%lx [0x%x]\n", ES_REG(ensoniq, 1371_CODEC), inl(ES_REG(ensoniq, 1371_CODEC))); } @@ -706,8 +706,8 @@ static unsigned short snd_es1371_codec_read(struct snd_ac97 *ac97, } mutex_unlock(&ensoniq->src_mutex); if (++fail > 10) { - snd_printk(KERN_ERR "codec read timeout (final) " - "at 0x%lx, reg = 0x%x [0x%x]\n", + dev_err(ensoniq->card->dev, + "codec read timeout (final) at 0x%lx, reg = 0x%x [0x%x]\n", ES_REG(ensoniq, 1371_CODEC), reg, inl(ES_REG(ensoniq, 1371_CODEC))); return 0; @@ -716,7 +716,7 @@ static unsigned short snd_es1371_codec_read(struct snd_ac97 *ac97, } } mutex_unlock(&ensoniq->src_mutex); - snd_printk(KERN_ERR "es1371: codec read timeout at 0x%lx [0x%x]\n", + dev_err(ensoniq->card->dev, "codec read timeout at 0x%lx [0x%x]\n", ES_REG(ensoniq, 1371_CODEC), inl(ES_REG(ensoniq, 1371_CODEC))); return 0; } @@ -1796,7 +1796,7 @@ static int snd_ensoniq_1370_mixer(struct ensoniq *ensoniq) #ifdef SUPPORT_JOYSTICK #ifdef CHIP1371 -static int snd_ensoniq_get_joystick_port(int dev) +static int snd_ensoniq_get_joystick_port(struct ensoniq *ensoniq, int dev) { switch (joystick_port[dev]) { case 0: /* disabled */ @@ -1808,12 +1808,13 @@ static int snd_ensoniq_get_joystick_port(int dev) return joystick_port[dev]; default: - printk(KERN_ERR "ens1371: invalid joystick port %#x", joystick_port[dev]); + dev_err(ensoniq->card->dev, + "invalid joystick port %#x", joystick_port[dev]); return 0; } } #else -static inline int snd_ensoniq_get_joystick_port(int dev) +static int snd_ensoniq_get_joystick_port(struct ensoniq *ensoniq, int dev) { return joystick[dev] ? 0x200 : 0; } @@ -1824,7 +1825,7 @@ static int snd_ensoniq_create_gameport(struct ensoniq *ensoniq, int dev) struct gameport *gp; int io_port; - io_port = snd_ensoniq_get_joystick_port(dev); + io_port = snd_ensoniq_get_joystick_port(ensoniq, dev); switch (io_port) { case 0: @@ -1835,14 +1836,16 @@ static int snd_ensoniq_create_gameport(struct ensoniq *ensoniq, int dev) if (request_region(io_port, 8, "ens137x: gameport")) break; if (io_port > 0x218) { - printk(KERN_WARNING "ens137x: no gameport ports available\n"); + dev_warn(ensoniq->card->dev, + "no gameport ports available\n"); return -EBUSY; } break; default: if (!request_region(io_port, 8, "ens137x: gameport")) { - printk(KERN_WARNING "ens137x: gameport io port %#x in use\n", + dev_warn(ensoniq->card->dev, + "gameport io port %#x in use\n", io_port); return -EBUSY; } @@ -1851,7 +1854,8 @@ static int snd_ensoniq_create_gameport(struct ensoniq *ensoniq, int dev) ensoniq->gameport = gp = gameport_allocate_port(); if (!gp) { - printk(KERN_ERR "ens137x: cannot allocate memory for gameport\n"); + dev_err(ensoniq->card->dev, + "cannot allocate memory for gameport\n"); release_region(io_port, 8); return -ENOMEM; } @@ -2082,8 +2086,7 @@ static int snd_ensoniq_resume(struct device *dev) pci_set_power_state(pci, PCI_D0); pci_restore_state(pci); if (pci_enable_device(pci) < 0) { - printk(KERN_ERR DRIVER_NAME ": pci_enable_device failed, " - "disabling device\n"); + dev_err(dev, "pci_enable_device failed, disabling device\n"); snd_card_disconnect(card); return -EIO; } @@ -2137,7 +2140,7 @@ static int snd_ensoniq_create(struct snd_card *card, ensoniq->port = pci_resource_start(pci, 0); if (request_irq(pci->irq, snd_audiopci_interrupt, IRQF_SHARED, KBUILD_MODNAME, ensoniq)) { - snd_printk(KERN_ERR "unable to grab IRQ %d\n", pci->irq); + dev_err(card->dev, "unable to grab IRQ %d\n", pci->irq); snd_ensoniq_free(ensoniq); return -EBUSY; } @@ -2145,7 +2148,7 @@ static int snd_ensoniq_create(struct snd_card *card, #ifdef CHIP1370 if (snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(pci), 16, &ensoniq->dma_bug) < 0) { - snd_printk(KERN_ERR "unable to allocate space for phantom area - dma_bug\n"); + dev_err(card->dev, "unable to allocate space for phantom area - dma_bug\n"); snd_ensoniq_free(ensoniq); return -EBUSY; } @@ -2180,8 +2183,6 @@ static int snd_ensoniq_create(struct snd_card *card, snd_ensoniq_proc_init(ensoniq); - snd_card_set_dev(card, &pci->dev); - *rensoniq = ensoniq; return 0; } @@ -2437,7 +2438,8 @@ static int snd_audiopci_probe(struct pci_dev *pci, return -ENOENT; } - err = snd_card_create(index[dev], id[dev], THIS_MODULE, 0, &card); + err = snd_card_new(&pci->dev, index[dev], id[dev], THIS_MODULE, + 0, &card); if (err < 0) return err; diff --git a/sound/pci/es1938.c b/sound/pci/es1938.c index 9213fb38921..34d95bf916b 100644 --- a/sound/pci/es1938.c +++ b/sound/pci/es1938.c @@ -254,7 +254,6 @@ MODULE_DEVICE_TABLE(pci, snd_es1938_ids); #define WRITE_LOOP_TIMEOUT 0x10000 #define GET_LOOP_TIMEOUT 0x01000 -#undef REG_DEBUG /* ----------------------------------------------------------------- * Write to a mixer register * -----------------------------------------------------------------*/ @@ -265,9 +264,7 @@ static void snd_es1938_mixer_write(struct es1938 *chip, unsigned char reg, unsig outb(reg, SLSB_REG(chip, MIXERADDR)); outb(val, SLSB_REG(chip, MIXERDATA)); spin_unlock_irqrestore(&chip->mixer_lock, flags); -#ifdef REG_DEBUG - snd_printk(KERN_DEBUG "Mixer reg %02x set to %02x\n", reg, val); -#endif + dev_dbg(chip->card->dev, "Mixer reg %02x set to %02x\n", reg, val); } /* ----------------------------------------------------------------- @@ -281,9 +278,7 @@ static int snd_es1938_mixer_read(struct es1938 *chip, unsigned char reg) outb(reg, SLSB_REG(chip, MIXERADDR)); data = inb(SLSB_REG(chip, MIXERDATA)); spin_unlock_irqrestore(&chip->mixer_lock, flags); -#ifdef REG_DEBUG - snd_printk(KERN_DEBUG "Mixer reg %02x now is %02x\n", reg, data); -#endif + dev_dbg(chip->card->dev, "Mixer reg %02x now is %02x\n", reg, data); return data; } @@ -302,10 +297,9 @@ static int snd_es1938_mixer_bits(struct es1938 *chip, unsigned char reg, if (val != oval) { new = (old & ~mask) | (val & mask); outb(new, SLSB_REG(chip, MIXERDATA)); -#ifdef REG_DEBUG - snd_printk(KERN_DEBUG "Mixer reg %02x was %02x, set to %02x\n", + dev_dbg(chip->card->dev, + "Mixer reg %02x was %02x, set to %02x\n", reg, old, new); -#endif } spin_unlock_irqrestore(&chip->mixer_lock, flags); return oval; @@ -324,7 +318,8 @@ static void snd_es1938_write_cmd(struct es1938 *chip, unsigned char cmd) return; } } - printk(KERN_ERR "snd_es1938_write_cmd timeout (0x02%x/0x02%x)\n", cmd, v); + dev_err(chip->card->dev, + "snd_es1938_write_cmd timeout (0x02%x/0x02%x)\n", cmd, v); } /* ----------------------------------------------------------------- @@ -337,7 +332,7 @@ static int snd_es1938_get_byte(struct es1938 *chip) for (i = GET_LOOP_TIMEOUT; i; i--) if ((v = inb(SLSB_REG(chip, STATUS))) & 0x80) return inb(SLSB_REG(chip, READDATA)); - snd_printk(KERN_ERR "get_byte timeout: status 0x02%x\n", v); + dev_err(chip->card->dev, "get_byte timeout: status 0x02%x\n", v); return -ENODEV; } @@ -351,9 +346,7 @@ static void snd_es1938_write(struct es1938 *chip, unsigned char reg, unsigned ch snd_es1938_write_cmd(chip, reg); snd_es1938_write_cmd(chip, val); spin_unlock_irqrestore(&chip->reg_lock, flags); -#ifdef REG_DEBUG - snd_printk(KERN_DEBUG "Reg %02x set to %02x\n", reg, val); -#endif + dev_dbg(chip->card->dev, "Reg %02x set to %02x\n", reg, val); } /* ----------------------------------------------------------------- @@ -368,9 +361,7 @@ static unsigned char snd_es1938_read(struct es1938 *chip, unsigned char reg) snd_es1938_write_cmd(chip, reg); val = snd_es1938_get_byte(chip); spin_unlock_irqrestore(&chip->reg_lock, flags); -#ifdef REG_DEBUG - snd_printk(KERN_DEBUG "Reg %02x now is %02x\n", reg, val); -#endif + dev_dbg(chip->card->dev, "Reg %02x now is %02x\n", reg, val); return val; } @@ -391,10 +382,8 @@ static int snd_es1938_bits(struct es1938 *chip, unsigned char reg, unsigned char snd_es1938_write_cmd(chip, reg); new = (old & ~mask) | (val & mask); snd_es1938_write_cmd(chip, new); -#ifdef REG_DEBUG - snd_printk(KERN_DEBUG "Reg %02x was %02x, set to %02x\n", + dev_dbg(chip->card->dev, "Reg %02x was %02x, set to %02x\n", reg, old, new); -#endif } spin_unlock_irqrestore(&chip->reg_lock, flags); return oval; @@ -416,7 +405,7 @@ static void snd_es1938_reset(struct es1938 *chip) goto __next; } } - snd_printk(KERN_ERR "ESS Solo-1 reset failed\n"); + dev_err(chip->card->dev, "ESS Solo-1 reset failed\n"); __next: snd_es1938_write_cmd(chip, ESS_CMD_ENABLEEXT); @@ -1504,16 +1493,15 @@ static int es1938_resume(struct device *dev) pci_set_power_state(pci, PCI_D0); pci_restore_state(pci); if (pci_enable_device(pci) < 0) { - printk(KERN_ERR "es1938: pci_enable_device failed, " - "disabling device\n"); + dev_err(dev, "pci_enable_device failed, disabling device\n"); snd_card_disconnect(card); return -EIO; } if (request_irq(pci->irq, snd_es1938_interrupt, IRQF_SHARED, KBUILD_MODNAME, chip)) { - printk(KERN_ERR "es1938: unable to grab IRQ %d, " - "disabling device\n", pci->irq); + dev_err(dev, "unable to grab IRQ %d, disabling device\n", + pci->irq); snd_card_disconnect(card); return -EIO; } @@ -1545,7 +1533,8 @@ static int snd_es1938_create_gameport(struct es1938 *chip) chip->gameport = gp = gameport_allocate_port(); if (!gp) { - printk(KERN_ERR "es1938: cannot allocate memory for gameport\n"); + dev_err(chip->card->dev, + "cannot allocate memory for gameport\n"); return -ENOMEM; } @@ -1612,7 +1601,8 @@ static int snd_es1938_create(struct snd_card *card, /* check, if we can restrict PCI DMA transfers to 24 bits */ if (pci_set_dma_mask(pci, DMA_BIT_MASK(24)) < 0 || pci_set_consistent_dma_mask(pci, DMA_BIT_MASK(24)) < 0) { - snd_printk(KERN_ERR "architecture does not support 24bit PCI busmaster DMA\n"); + dev_err(card->dev, + "architecture does not support 24bit PCI busmaster DMA\n"); pci_disable_device(pci); return -ENXIO; } @@ -1639,15 +1629,14 @@ static int snd_es1938_create(struct snd_card *card, chip->game_port = pci_resource_start(pci, 4); if (request_irq(pci->irq, snd_es1938_interrupt, IRQF_SHARED, KBUILD_MODNAME, chip)) { - snd_printk(KERN_ERR "unable to grab IRQ %d\n", pci->irq); + dev_err(card->dev, "unable to grab IRQ %d\n", pci->irq); snd_es1938_free(chip); return -EBUSY; } chip->irq = pci->irq; -#ifdef ES1938_DDEBUG - snd_printk(KERN_DEBUG "create: io: 0x%lx, sb: 0x%lx, vc: 0x%lx, mpu: 0x%lx, game: 0x%lx\n", + dev_dbg(card->dev, + "create: io: 0x%lx, sb: 0x%lx, vc: 0x%lx, mpu: 0x%lx, game: 0x%lx\n", chip->io_port, chip->sb_port, chip->vc_port, chip->mpu_port, chip->game_port); -#endif chip->ddma_port = chip->vc_port + 0x00; /* fix from Thomas Sailer */ @@ -1658,8 +1647,6 @@ static int snd_es1938_create(struct snd_card *card, return err; } - snd_card_set_dev(card, &pci->dev); - *rchip = chip; return 0; } @@ -1675,21 +1662,22 @@ static irqreturn_t snd_es1938_interrupt(int irq, void *dev_id) status = inb(SLIO_REG(chip, IRQCONTROL)); #if 0 - printk(KERN_DEBUG "Es1938debug - interrupt status: =0x%x\n", status); + dev_dbg(chip->card->dev, + "Es1938debug - interrupt status: =0x%x\n", status); #endif /* AUDIO 1 */ if (status & 0x10) { #if 0 - printk(KERN_DEBUG + dev_dbg(chip->card->dev, "Es1938debug - AUDIO channel 1 interrupt\n"); - printk(KERN_DEBUG + dev_dbg(chip->card->dev, "Es1938debug - AUDIO channel 1 DMAC DMA count: %u\n", inw(SLDM_REG(chip, DMACOUNT))); - printk(KERN_DEBUG + dev_dbg(chip->card->dev, "Es1938debug - AUDIO channel 1 DMAC DMA base: %u\n", inl(SLDM_REG(chip, DMAADDR))); - printk(KERN_DEBUG + dev_dbg(chip->card->dev, "Es1938debug - AUDIO channel 1 DMAC DMA status: 0x%x\n", inl(SLDM_REG(chip, DMASTATUS))); #endif @@ -1705,12 +1693,12 @@ static irqreturn_t snd_es1938_interrupt(int irq, void *dev_id) /* AUDIO 2 */ if (status & 0x20) { #if 0 - printk(KERN_DEBUG + dev_dbg(chip->card->dev, "Es1938debug - AUDIO channel 2 interrupt\n"); - printk(KERN_DEBUG + dev_dbg(chip->card->dev, "Es1938debug - AUDIO channel 2 DMAC DMA count: %u\n", inw(SLIO_REG(chip, AUDIO2DMACOUNT))); - printk(KERN_DEBUG + dev_dbg(chip->card->dev, "Es1938debug - AUDIO channel 2 DMAC DMA base: %u\n", inl(SLIO_REG(chip, AUDIO2DMAADDR))); @@ -1808,7 +1796,8 @@ static int snd_es1938_probe(struct pci_dev *pci, return -ENOENT; } - err = snd_card_create(index[dev], id[dev], THIS_MODULE, 0, &card); + err = snd_card_new(&pci->dev, index[dev], id[dev], THIS_MODULE, + 0, &card); if (err < 0) return err; for (idx = 0; idx < 5; idx++) { @@ -1843,7 +1832,7 @@ static int snd_es1938_probe(struct pci_dev *pci, SLSB_REG(chip, FMLOWADDR), SLSB_REG(chip, FMHIGHADDR), OPL3_HW_OPL3, 1, &opl3) < 0) { - printk(KERN_ERR "es1938: OPL3 not detected at 0x%lx\n", + dev_err(card->dev, "OPL3 not detected at 0x%lx\n", SLSB_REG(chip, FMLOWADDR)); } else { if ((err = snd_opl3_timer_new(opl3, 0, 1)) < 0) { @@ -1859,7 +1848,7 @@ static int snd_es1938_probe(struct pci_dev *pci, chip->mpu_port, MPU401_INFO_INTEGRATED | MPU401_INFO_IRQ_HOOK, -1, &chip->rmidi) < 0) { - printk(KERN_ERR "es1938: unable to initialize MPU-401\n"); + dev_err(card->dev, "unable to initialize MPU-401\n"); } else { // this line is vital for MIDI interrupt handling on ess-solo1 // andreas@flying-snail.de diff --git a/sound/pci/es1968.c b/sound/pci/es1968.c index 772cc36f951..5bb1cf60330 100644 --- a/sound/pci/es1968.c +++ b/sound/pci/es1968.c @@ -632,7 +632,7 @@ static int snd_es1968_ac97_wait(struct es1968 *chip) return 0; cond_resched(); } - snd_printd("es1968: ac97 timeout\n"); + dev_dbg(chip->card->dev, "ac97 timeout\n"); return 1; /* timeout */ } @@ -644,7 +644,7 @@ static int snd_es1968_ac97_wait_poll(struct es1968 *chip) if (!(inb(chip->io_port + ESM_AC97_INDEX) & 1)) return 0; } - snd_printd("es1968: ac97 timeout\n"); + dev_dbg(chip->card->dev, "ac97 timeout\n"); return 1; /* timeout */ } @@ -687,7 +687,7 @@ static void apu_index_set(struct es1968 *chip, u16 index) for (i = 0; i < 1000; i++) if (__maestro_read(chip, IDR1_CRAM_POINTER) == index) return; - snd_printd("es1968: APU register select failed. (Timeout)\n"); + dev_dbg(chip->card->dev, "APU register select failed. (Timeout)\n"); } /* no spinlock */ @@ -699,7 +699,7 @@ static void apu_data_set(struct es1968 *chip, u16 data) return; __maestro_write(chip, IDR0_DATA_PORT, data); } - snd_printd("es1968: APU register set probably failed (Timeout)!\n"); + dev_dbg(chip->card->dev, "APU register set probably failed (Timeout)!\n"); } /* no spinlock */ @@ -1442,13 +1442,14 @@ snd_es1968_init_dmabuf(struct es1968 *chip) snd_dma_pci_data(chip->pci), chip->total_bufsize, &chip->dma); if (err < 0 || ! chip->dma.area) { - snd_printk(KERN_ERR "es1968: can't allocate dma pages for size %d\n", + dev_err(chip->card->dev, + "can't allocate dma pages for size %d\n", chip->total_bufsize); return -ENOMEM; } if ((chip->dma.addr + chip->dma.bytes - 1) & ~((1 << 28) - 1)) { snd_dma_free_pages(&chip->dma); - snd_printk(KERN_ERR "es1968: DMA buffer beyond 256MB.\n"); + dev_err(chip->card->dev, "DMA buffer beyond 256MB.\n"); return -ENOMEM; } @@ -1489,7 +1490,8 @@ static int snd_es1968_hw_params(struct snd_pcm_substream *substream, } chan->memory = snd_es1968_new_memory(chip, size); if (chan->memory == NULL) { - // snd_printd("cannot allocate dma buffer: size = %d\n", size); + dev_dbg(chip->card->dev, + "cannot allocate dma buffer: size = %d\n", size); return -ENOMEM; } snd_pcm_set_runtime_buffer(substream, &chan->memory->buf); @@ -1715,11 +1717,13 @@ static void es1968_measure_clock(struct es1968 *chip) /* search 2 APUs (although one apu is enough) */ if ((apu = snd_es1968_alloc_apu_pair(chip, ESM_APU_PCM_PLAY)) < 0) { - snd_printk(KERN_ERR "Hmm, cannot find empty APU pair!?\n"); + dev_err(chip->card->dev, "Hmm, cannot find empty APU pair!?\n"); return; } if ((memory = snd_es1968_new_memory(chip, CLOCK_MEASURE_BUFSIZE)) == NULL) { - snd_printk(KERN_ERR "cannot allocate dma buffer - using default clock %d\n", chip->clock); + dev_warn(chip->card->dev, + "cannot allocate dma buffer - using default clock %d\n", + chip->clock); snd_es1968_free_apu_pair(chip, apu); return; } @@ -1780,7 +1784,7 @@ static void es1968_measure_clock(struct es1968 *chip) else t += stop_time.tv_usec - start_time.tv_usec; if (t == 0) { - snd_printk(KERN_ERR "?? calculation error..\n"); + dev_err(chip->card->dev, "?? calculation error..\n"); } else { offset *= 1000; offset = (offset / t) * 1000 + ((offset % t) * 1000) / t; @@ -1788,7 +1792,7 @@ static void es1968_measure_clock(struct es1968 *chip) if (offset >= 40000 && offset <= 50000) chip->clock = (chip->clock * offset) / 48000; } - printk(KERN_INFO "es1968: clocking to %d\n", chip->clock); + dev_info(chip->card->dev, "clocking to %d\n", chip->clock); } snd_es1968_free_memory(chip, memory); snd_es1968_free_apu_pair(chip, apu); @@ -2108,7 +2112,7 @@ static void snd_es1968_ac97_reset(struct es1968 *chip) outw(inw(ioaddr + 0x3c) & 0xfffc, ioaddr + 0x3c); #if 0 /* the loop here needs to be much better if we want it.. */ - snd_printk(KERN_INFO "trying software reset\n"); + dev_info(chip->card->dev, "trying software reset\n"); /* try and do a software reset */ outb(0x80 | 0x7c, ioaddr + 0x30); for (w = 0;; w++) { @@ -2416,8 +2420,7 @@ static int es1968_resume(struct device *dev) pci_set_power_state(pci, PCI_D0); pci_restore_state(pci); if (pci_enable_device(pci) < 0) { - printk(KERN_ERR "es1968: pci_enable_device failed, " - "disabling device\n"); + dev_err(dev, "pci_enable_device failed, disabling device\n"); snd_card_disconnect(card); return -EIO; } @@ -2479,7 +2482,8 @@ static int snd_es1968_create_gameport(struct es1968 *chip, int dev) chip->gameport = gp = gameport_allocate_port(); if (!gp) { - printk(KERN_ERR "es1968: cannot allocate memory for gameport\n"); + dev_err(chip->card->dev, + "cannot allocate memory for gameport\n"); release_and_free_resource(r); return -ENOMEM; } @@ -2706,7 +2710,8 @@ static int snd_es1968_create(struct snd_card *card, /* check, if we can restrict PCI DMA transfers to 28 bits */ if (pci_set_dma_mask(pci, DMA_BIT_MASK(28)) < 0 || pci_set_consistent_dma_mask(pci, DMA_BIT_MASK(28)) < 0) { - snd_printk(KERN_ERR "architecture does not support 28bit PCI busmaster DMA\n"); + dev_err(card->dev, + "architecture does not support 28bit PCI busmaster DMA\n"); pci_disable_device(pci); return -ENXIO; } @@ -2740,7 +2745,7 @@ static int snd_es1968_create(struct snd_card *card, chip->io_port = pci_resource_start(pci, 0); if (request_irq(pci->irq, snd_es1968_interrupt, IRQF_SHARED, KBUILD_MODNAME, chip)) { - snd_printk(KERN_ERR "unable to grab IRQ %d\n", pci->irq); + dev_err(card->dev, "unable to grab IRQ %d\n", pci->irq); snd_es1968_free(chip); return -EBUSY; } @@ -2770,7 +2775,7 @@ static int snd_es1968_create(struct snd_card *card, } if (do_pm > 1) { /* not matched; disabling pm */ - printk(KERN_INFO "es1968: not attempting power management.\n"); + dev_info(card->dev, "not attempting power management.\n"); do_pm = 0; } } @@ -2783,8 +2788,6 @@ static int snd_es1968_create(struct snd_card *card, return err; } - snd_card_set_dev(card, &pci->dev); - #ifdef CONFIG_SND_ES1968_RADIO /* don't play with GPIOs on laptops */ if (chip->pci->subsystem_vendor != 0x125d) @@ -2802,7 +2805,7 @@ static int snd_es1968_create(struct snd_card *card, for (i = 0; i < ARRAY_SIZE(snd_es1968_tea575x_gpios); i++) { chip->tea575x_tuner = i; if (!snd_tea575x_init(&chip->tea, THIS_MODULE)) { - snd_printk(KERN_INFO "es1968: detected TEA575x radio type %s\n", + dev_info(card->dev, "detected TEA575x radio type %s\n", get_tea575x_gpio(chip)->name); strlcpy(chip->tea.card, get_tea575x_gpio(chip)->name, sizeof(chip->tea.card)); @@ -2836,7 +2839,8 @@ static int snd_es1968_probe(struct pci_dev *pci, return -ENOENT; } - err = snd_card_create(index[dev], id[dev], THIS_MODULE, 0, &card); + err = snd_card_new(&pci->dev, index[dev], id[dev], THIS_MODULE, + 0, &card); if (err < 0) return err; @@ -2900,7 +2904,7 @@ static int snd_es1968_probe(struct pci_dev *pci, MPU401_INFO_INTEGRATED | MPU401_INFO_IRQ_HOOK, -1, &chip->rmidi)) < 0) { - printk(KERN_WARNING "es1968: skipping MPU-401 MIDI support..\n"); + dev_warn(card->dev, "skipping MPU-401 MIDI support..\n"); } } @@ -2909,8 +2913,8 @@ static int snd_es1968_probe(struct pci_dev *pci, #ifdef CONFIG_SND_ES1968_INPUT err = snd_es1968_input_register(chip); if (err) - snd_printk(KERN_WARNING "Input device registration " - "failed with error %i", err); + dev_warn(card->dev, + "Input device registration failed with error %i", err); #endif snd_es1968_start_irq(chip); diff --git a/sound/pci/fm801.c b/sound/pci/fm801.c index 45bc8a95b7c..db18ccabadd 100644 --- a/sound/pci/fm801.c +++ b/sound/pci/fm801.c @@ -254,7 +254,7 @@ static void snd_fm801_codec_write(struct snd_ac97 *ac97, goto ok1; udelay(10); } - snd_printk(KERN_ERR "AC'97 interface is busy (1)\n"); + dev_err(chip->card->dev, "AC'97 interface is busy (1)\n"); return; ok1: @@ -269,7 +269,7 @@ static void snd_fm801_codec_write(struct snd_ac97 *ac97, return; udelay(10); } - snd_printk(KERN_ERR "AC'97 interface #%d is busy (2)\n", ac97->num); + dev_err(chip->card->dev, "AC'97 interface #%d is busy (2)\n", ac97->num); } static unsigned short snd_fm801_codec_read(struct snd_ac97 *ac97, unsigned short reg) @@ -285,7 +285,7 @@ static unsigned short snd_fm801_codec_read(struct snd_ac97 *ac97, unsigned short goto ok1; udelay(10); } - snd_printk(KERN_ERR "AC'97 interface is busy (1)\n"); + dev_err(chip->card->dev, "AC'97 interface is busy (1)\n"); return 0; ok1: @@ -297,7 +297,7 @@ static unsigned short snd_fm801_codec_read(struct snd_ac97 *ac97, unsigned short goto ok2; udelay(10); } - snd_printk(KERN_ERR "AC'97 interface #%d is busy (2)\n", ac97->num); + dev_err(chip->card->dev, "AC'97 interface #%d is busy (2)\n", ac97->num); return 0; ok2: @@ -306,7 +306,7 @@ static unsigned short snd_fm801_codec_read(struct snd_ac97 *ac97, unsigned short goto ok3; udelay(10); } - snd_printk(KERN_ERR "AC'97 interface #%d is not valid (2)\n", ac97->num); + dev_err(chip->card->dev, "AC'97 interface #%d is not valid (2)\n", ac97->num); return 0; ok3: @@ -1100,8 +1100,8 @@ static int snd_fm801_chip_init(struct fm801 *chip, int resume) if (wait_for_codec(chip, 0, AC97_RESET, msecs_to_jiffies(750)) < 0) if (!resume) { - snd_printk(KERN_INFO "Primary AC'97 codec not found, " - "assume SF64-PCR (tuner-only)\n"); + dev_info(chip->card->dev, + "Primary AC'97 codec not found, assume SF64-PCR (tuner-only)\n"); chip->tea575x_tuner = 3 | TUNER_ONLY; goto __ac97_ok; } @@ -1225,7 +1225,7 @@ static int snd_fm801_create(struct snd_card *card, if ((tea575x_tuner & TUNER_ONLY) == 0) { if (request_irq(pci->irq, snd_fm801_interrupt, IRQF_SHARED, KBUILD_MODNAME, chip)) { - snd_printk(KERN_ERR "unable to grab IRQ %d\n", chip->irq); + dev_err(card->dev, "unable to grab IRQ %d\n", chip->irq); snd_fm801_free(chip); return -EBUSY; } @@ -1251,8 +1251,6 @@ static int snd_fm801_create(struct snd_card *card, return err; } - snd_card_set_dev(card, &pci->dev); - #ifdef CONFIG_SND_FM801_TEA575X_BOOL err = v4l2_device_register(&pci->dev, &chip->v4l2_dev); if (err < 0) { @@ -1267,7 +1265,7 @@ static int snd_fm801_create(struct snd_card *card, if ((tea575x_tuner & TUNER_TYPE_MASK) > 0 && (tea575x_tuner & TUNER_TYPE_MASK) < 4) { if (snd_tea575x_init(&chip->tea, THIS_MODULE)) { - snd_printk(KERN_ERR "TEA575x radio not found\n"); + dev_err(card->dev, "TEA575x radio not found\n"); snd_fm801_free(chip); return -ENODEV; } @@ -1276,13 +1274,14 @@ static int snd_fm801_create(struct snd_card *card, for (tea575x_tuner = 1; tea575x_tuner <= 3; tea575x_tuner++) { chip->tea575x_tuner = tea575x_tuner; if (!snd_tea575x_init(&chip->tea, THIS_MODULE)) { - snd_printk(KERN_INFO "detected TEA575x radio type %s\n", + dev_info(card->dev, + "detected TEA575x radio type %s\n", get_tea575x_gpio(chip)->name); break; } } if (tea575x_tuner == 4) { - snd_printk(KERN_ERR "TEA575x radio not found\n"); + dev_err(card->dev, "TEA575x radio not found\n"); chip->tea575x_tuner = TUNER_DISABLED; } } @@ -1312,7 +1311,8 @@ static int snd_card_fm801_probe(struct pci_dev *pci, return -ENOENT; } - err = snd_card_create(index[dev], id[dev], THIS_MODULE, 0, &card); + err = snd_card_new(&pci->dev, index[dev], id[dev], THIS_MODULE, + 0, &card); if (err < 0) return err; if ((err = snd_fm801_create(card, pci, tea575x_tuner[dev], radio_nr[dev], &chip)) < 0) { @@ -1411,8 +1411,7 @@ static int snd_fm801_resume(struct device *dev) pci_set_power_state(pci, PCI_D0); pci_restore_state(pci); if (pci_enable_device(pci) < 0) { - printk(KERN_ERR "fm801: pci_enable_device failed, " - "disabling device\n"); + dev_err(dev, "pci_enable_device failed, disabling device\n"); snd_card_disconnect(card); return -EIO; } diff --git a/sound/pci/hda/Kconfig b/sound/pci/hda/Kconfig index 0e53634dbbd..ac17c3fc938 100644 --- a/sound/pci/hda/Kconfig +++ b/sound/pci/hda/Kconfig @@ -1,8 +1,15 @@ -menuconfig SND_HDA_INTEL - tristate "Intel HD Audio" +menu "HD-Audio" + +config SND_HDA + tristate select SND_PCM select SND_VMASTER select SND_KCTL_JACK + +config SND_HDA_INTEL + tristate "HD Audio PCI" + depends on SND_PCI + select SND_HDA help Say Y here to include support for Intel "High Definition Audio" (Azalia) and its compatible devices. @@ -13,7 +20,7 @@ menuconfig SND_HDA_INTEL To compile this driver as a module, choose M here: the module will be called snd-hda-intel. -if SND_HDA_INTEL +if SND_HDA config SND_HDA_DSP_LOADER bool @@ -41,7 +48,6 @@ config SND_HDA_HWDEP config SND_HDA_RECONFIG bool "Allow dynamic codec reconfiguration" - depends on SND_HDA_HWDEP help Say Y here to enable the HD-audio codec re-configuration feature. This adds the sysfs interfaces to allow user to clear the whole @@ -50,7 +56,7 @@ config SND_HDA_RECONFIG config SND_HDA_INPUT_BEEP bool "Support digital beep via input layer" - depends on INPUT=y || INPUT=SND_HDA_INTEL + depends on INPUT=y || INPUT=SND_HDA help Say Y here to build a digital beep interface for HD-audio driver. This interface is used to generate digital beeps. @@ -76,7 +82,6 @@ config SND_HDA_INPUT_JACK config SND_HDA_PATCH_LOADER bool "Support initialization patch loading for HD-audio" select FW_LOADER - select SND_HDA_HWDEP select SND_HDA_RECONFIG help Say Y here to allow the HD-audio driver to load a pseudo @@ -84,8 +89,6 @@ config SND_HDA_PATCH_LOADER start up. The "patch" file can be specified via patch module option, such as patch=hda-init. - This option turns on hwdep and reconfig features automatically. - config SND_HDA_CODEC_REALTEK tristate "Build Realtek HD-audio codec support" select SND_HDA_GENERIC @@ -94,7 +97,7 @@ config SND_HDA_CODEC_REALTEK snd-hda-intel driver, such as ALC880. comment "Set to Y if you want auto-loading the codec driver" - depends on SND_HDA_INTEL=y && SND_HDA_CODEC_REALTEK=m + depends on SND_HDA=y && SND_HDA_CODEC_REALTEK=m config SND_HDA_CODEC_ANALOG tristate "Build Analog Device HD-audio codec support" @@ -104,7 +107,7 @@ config SND_HDA_CODEC_ANALOG snd-hda-intel driver, such as AD1986A. comment "Set to Y if you want auto-loading the codec driver" - depends on SND_HDA_INTEL=y && SND_HDA_CODEC_ANALOG=m + depends on SND_HDA=y && SND_HDA_CODEC_ANALOG=m config SND_HDA_CODEC_SIGMATEL tristate "Build IDT/Sigmatel HD-audio codec support" @@ -114,7 +117,7 @@ config SND_HDA_CODEC_SIGMATEL snd-hda-intel driver, such as STAC9200. comment "Set to Y if you want auto-loading the codec driver" - depends on SND_HDA_INTEL=y && SND_HDA_CODEC_SIGMATEL=m + depends on SND_HDA=y && SND_HDA_CODEC_SIGMATEL=m config SND_HDA_CODEC_VIA tristate "Build VIA HD-audio codec support" @@ -124,7 +127,7 @@ config SND_HDA_CODEC_VIA snd-hda-intel driver, such as VT1708. comment "Set to Y if you want auto-loading the codec driver" - depends on SND_HDA_INTEL=y && SND_HDA_CODEC_VIA=m + depends on SND_HDA=y && SND_HDA_CODEC_VIA=m config SND_HDA_CODEC_HDMI tristate "Build HDMI/DisplayPort HD-audio codec support" @@ -134,7 +137,7 @@ config SND_HDA_CODEC_HDMI Intel and Nvidia HDMI/DisplayPort codecs. comment "Set to Y if you want auto-loading the codec driver" - depends on SND_HDA_INTEL=y && SND_HDA_CODEC_HDMI=m + depends on SND_HDA=y && SND_HDA_CODEC_HDMI=m config SND_HDA_I915 bool @@ -149,7 +152,7 @@ config SND_HDA_CODEC_CIRRUS snd-hda-intel driver, such as CS4206. comment "Set to Y if you want auto-loading the codec driver" - depends on SND_HDA_INTEL=y && SND_HDA_CODEC_CIRRUS=m + depends on SND_HDA=y && SND_HDA_CODEC_CIRRUS=m config SND_HDA_CODEC_CONEXANT tristate "Build Conexant HD-audio codec support" @@ -159,7 +162,7 @@ config SND_HDA_CODEC_CONEXANT snd-hda-intel driver, such as CX20549. comment "Set to Y if you want auto-loading the codec driver" - depends on SND_HDA_INTEL=y && SND_HDA_CODEC_CONEXANT=m + depends on SND_HDA=y && SND_HDA_CODEC_CONEXANT=m config SND_HDA_CODEC_CA0110 tristate "Build Creative CA0110-IBG codec support" @@ -169,7 +172,7 @@ config SND_HDA_CODEC_CA0110 snd-hda-intel driver, found on some Creative X-Fi cards. comment "Set to Y if you want auto-loading the codec driver" - depends on SND_HDA_INTEL=y && SND_HDA_CODEC_CA0110=m + depends on SND_HDA=y && SND_HDA_CODEC_CA0110=m config SND_HDA_CODEC_CA0132 tristate "Build Creative CA0132 codec support" @@ -178,7 +181,7 @@ config SND_HDA_CODEC_CA0132 snd-hda-intel driver. comment "Set to Y if you want auto-loading the codec driver" - depends on SND_HDA_INTEL=y && SND_HDA_CODEC_CA0132=m + depends on SND_HDA=y && SND_HDA_CODEC_CA0132=m config SND_HDA_CODEC_CA0132_DSP bool "Support new DSP code for CA0132 codec" @@ -200,7 +203,7 @@ config SND_HDA_CODEC_CMEDIA snd-hda-intel driver, such as CMI9880. comment "Set to Y if you want auto-loading the codec driver" - depends on SND_HDA_INTEL=y && SND_HDA_CODEC_CMEDIA=m + depends on SND_HDA=y && SND_HDA_CODEC_CMEDIA=m config SND_HDA_CODEC_SI3054 tristate "Build Silicon Labs 3054 HD-modem codec support" @@ -209,7 +212,7 @@ config SND_HDA_CODEC_SI3054 (and compatibles) support in snd-hda-intel driver. comment "Set to Y if you want auto-loading the codec driver" - depends on SND_HDA_INTEL=y && SND_HDA_CODEC_SI3054=m + depends on SND_HDA=y && SND_HDA_CODEC_SI3054=m config SND_HDA_GENERIC tristate "Enable generic HD-audio codec parser" @@ -218,7 +221,7 @@ config SND_HDA_GENERIC in snd-hda-intel driver. comment "Set to Y if you want auto-loading the codec driver" - depends on SND_HDA_INTEL=y && SND_HDA_GENERIC=m + depends on SND_HDA=y && SND_HDA_GENERIC=m config SND_HDA_POWER_SAVE_DEFAULT int "Default time-out for HD-audio power-save mode" @@ -229,3 +232,5 @@ config SND_HDA_POWER_SAVE_DEFAULT power-save mode. 0 means to disable the power-save mode. endif + +endmenu diff --git a/sound/pci/hda/Makefile b/sound/pci/hda/Makefile index 1fcb118e480..d0d0c19ddfc 100644 --- a/sound/pci/hda/Makefile +++ b/sound/pci/hda/Makefile @@ -1,15 +1,16 @@ snd-hda-intel-objs := hda_intel.o +snd-hda-controller-objs := hda_controller.o # for haswell power well snd-hda-intel-$(CONFIG_SND_HDA_I915) += hda_i915.o -snd-hda-codec-y := hda_codec.o hda_jack.o hda_auto_parser.o +snd-hda-codec-y := hda_codec.o hda_jack.o hda_auto_parser.o hda_sysfs.o snd-hda-codec-$(CONFIG_PROC_FS) += hda_proc.o snd-hda-codec-$(CONFIG_SND_HDA_HWDEP) += hda_hwdep.o snd-hda-codec-$(CONFIG_SND_HDA_INPUT_BEEP) += hda_beep.o # for trace-points CFLAGS_hda_codec.o := -I$(src) -CFLAGS_hda_intel.o := -I$(src) +CFLAGS_hda_controller.o := -I$(src) snd-hda-codec-generic-objs := hda_generic.o snd-hda-codec-realtek-objs := patch_realtek.o @@ -25,7 +26,8 @@ snd-hda-codec-via-objs := patch_via.o snd-hda-codec-hdmi-objs := patch_hdmi.o hda_eld.o # common driver -obj-$(CONFIG_SND_HDA_INTEL) := snd-hda-codec.o +obj-$(CONFIG_SND_HDA) := snd-hda-codec.o +obj-$(CONFIG_SND_HDA) += snd-hda-controller.o # codec drivers obj-$(CONFIG_SND_HDA_GENERIC) += snd-hda-codec-generic.o diff --git a/sound/pci/hda/hda_auto_parser.c b/sound/pci/hda/hda_auto_parser.c index 47ad31c6aa7..90d2fda6c8f 100644 --- a/sound/pci/hda/hda_auto_parser.c +++ b/sound/pci/hda/hda_auto_parser.c @@ -227,10 +227,18 @@ int snd_hda_parse_pin_defcfg(struct hda_codec *codec, continue; if (!assoc_line_out) assoc_line_out = assoc; - else if (assoc_line_out != assoc) + else if (assoc_line_out != assoc) { + codec_info(codec, + "ignore pin 0x%x with mismatching assoc# 0x%x vs 0x%x\n", + nid, assoc, assoc_line_out); continue; - if (cfg->line_outs >= ARRAY_SIZE(cfg->line_out_pins)) + } + if (cfg->line_outs >= ARRAY_SIZE(cfg->line_out_pins)) { + codec_info(codec, + "ignore pin 0x%x, too many assigned pins\n", + nid); continue; + } line_out[cfg->line_outs].pin = nid; line_out[cfg->line_outs].seq = seq; cfg->line_outs++; @@ -238,8 +246,12 @@ int snd_hda_parse_pin_defcfg(struct hda_codec *codec, case AC_JACK_SPEAKER: seq = get_defcfg_sequence(def_conf); assoc = get_defcfg_association(def_conf); - if (cfg->speaker_outs >= ARRAY_SIZE(cfg->speaker_pins)) + if (cfg->speaker_outs >= ARRAY_SIZE(cfg->speaker_pins)) { + codec_info(codec, + "ignore pin 0x%x, too many assigned pins\n", + nid); continue; + } speaker_out[cfg->speaker_outs].pin = nid; speaker_out[cfg->speaker_outs].seq = (assoc << 4) | seq; cfg->speaker_outs++; @@ -247,8 +259,12 @@ int snd_hda_parse_pin_defcfg(struct hda_codec *codec, case AC_JACK_HP_OUT: seq = get_defcfg_sequence(def_conf); assoc = get_defcfg_association(def_conf); - if (cfg->hp_outs >= ARRAY_SIZE(cfg->hp_pins)) + if (cfg->hp_outs >= ARRAY_SIZE(cfg->hp_pins)) { + codec_info(codec, + "ignore pin 0x%x, too many assigned pins\n", + nid); continue; + } hp_out[cfg->hp_outs].pin = nid; hp_out[cfg->hp_outs].seq = (assoc << 4) | seq; cfg->hp_outs++; @@ -267,8 +283,12 @@ int snd_hda_parse_pin_defcfg(struct hda_codec *codec, break; case AC_JACK_SPDIF_OUT: case AC_JACK_DIG_OTHER_OUT: - if (cfg->dig_outs >= ARRAY_SIZE(cfg->dig_out_pins)) + if (cfg->dig_outs >= ARRAY_SIZE(cfg->dig_out_pins)) { + codec_info(codec, + "ignore pin 0x%x, too many assigned pins\n", + nid); continue; + } cfg->dig_out_pins[cfg->dig_outs] = nid; cfg->dig_out_type[cfg->dig_outs] = (loc == AC_JACK_LOC_HDMI) ? @@ -313,9 +333,9 @@ int snd_hda_parse_pin_defcfg(struct hda_codec *codec, } if (hsmic) - snd_printdd("Told to look for a headset mic, but didn't find any.\n"); + codec_dbg(codec, "Told to look for a headset mic, but didn't find any.\n"); if (hpmic) - snd_printdd("Told to look for a headphone mic, but didn't find any.\n"); + codec_dbg(codec, "Told to look for a headphone mic, but didn't find any.\n"); } /* FIX-UP: @@ -384,33 +404,33 @@ int snd_hda_parse_pin_defcfg(struct hda_codec *codec, /* * debug prints of the parsed results */ - snd_printd("autoconfig: line_outs=%d (0x%x/0x%x/0x%x/0x%x/0x%x) type:%s\n", + codec_info(codec, "autoconfig: line_outs=%d (0x%x/0x%x/0x%x/0x%x/0x%x) type:%s\n", cfg->line_outs, cfg->line_out_pins[0], cfg->line_out_pins[1], cfg->line_out_pins[2], cfg->line_out_pins[3], cfg->line_out_pins[4], cfg->line_out_type == AUTO_PIN_HP_OUT ? "hp" : (cfg->line_out_type == AUTO_PIN_SPEAKER_OUT ? "speaker" : "line")); - snd_printd(" speaker_outs=%d (0x%x/0x%x/0x%x/0x%x/0x%x)\n", + codec_info(codec, " speaker_outs=%d (0x%x/0x%x/0x%x/0x%x/0x%x)\n", cfg->speaker_outs, cfg->speaker_pins[0], cfg->speaker_pins[1], cfg->speaker_pins[2], cfg->speaker_pins[3], cfg->speaker_pins[4]); - snd_printd(" hp_outs=%d (0x%x/0x%x/0x%x/0x%x/0x%x)\n", + codec_info(codec, " hp_outs=%d (0x%x/0x%x/0x%x/0x%x/0x%x)\n", cfg->hp_outs, cfg->hp_pins[0], cfg->hp_pins[1], cfg->hp_pins[2], cfg->hp_pins[3], cfg->hp_pins[4]); - snd_printd(" mono: mono_out=0x%x\n", cfg->mono_out_pin); + codec_info(codec, " mono: mono_out=0x%x\n", cfg->mono_out_pin); if (cfg->dig_outs) - snd_printd(" dig-out=0x%x/0x%x\n", + codec_info(codec, " dig-out=0x%x/0x%x\n", cfg->dig_out_pins[0], cfg->dig_out_pins[1]); - snd_printd(" inputs:\n"); + codec_info(codec, " inputs:\n"); for (i = 0; i < cfg->num_inputs; i++) { - snd_printd(" %s=0x%x\n", + codec_info(codec, " %s=0x%x\n", hda_get_autocfg_input_label(codec, cfg, i), cfg->inputs[i].pin); } if (cfg->dig_in_pin) - snd_printd(" dig-in=0x%x\n", cfg->dig_in_pin); + codec_info(codec, " dig-in=0x%x\n", cfg->dig_in_pin); return 0; } @@ -774,38 +794,33 @@ static void apply_fixup(struct hda_codec *codec, int id, int action, int depth) case HDA_FIXUP_PINS: if (action != HDA_FIXUP_ACT_PRE_PROBE || !fix->v.pins) break; - snd_printdd(KERN_INFO SFX - "%s: Apply pincfg for %s\n", + codec_dbg(codec, "%s: Apply pincfg for %s\n", codec->chip_name, modelname); snd_hda_apply_pincfgs(codec, fix->v.pins); break; case HDA_FIXUP_VERBS: if (action != HDA_FIXUP_ACT_PROBE || !fix->v.verbs) break; - snd_printdd(KERN_INFO SFX - "%s: Apply fix-verbs for %s\n", + codec_dbg(codec, "%s: Apply fix-verbs for %s\n", codec->chip_name, modelname); snd_hda_add_verbs(codec, fix->v.verbs); break; case HDA_FIXUP_FUNC: if (!fix->v.func) break; - snd_printdd(KERN_INFO SFX - "%s: Apply fix-func for %s\n", + codec_dbg(codec, "%s: Apply fix-func for %s\n", codec->chip_name, modelname); fix->v.func(codec, fix, action); break; case HDA_FIXUP_PINCTLS: if (action != HDA_FIXUP_ACT_PROBE || !fix->v.pins) break; - snd_printdd(KERN_INFO SFX - "%s: Apply pinctl for %s\n", + codec_dbg(codec, "%s: Apply pinctl for %s\n", codec->chip_name, modelname); set_pin_targets(codec, fix->v.pins); break; default: - snd_printk(KERN_ERR SFX - "%s: Invalid fixup type %d\n", + codec_err(codec, "%s: Invalid fixup type %d\n", codec->chip_name, fix->type); break; } diff --git a/sound/pci/hda/hda_beep.c b/sound/pci/hda/hda_beep.c index 0589b39cda6..8c6c50afc0b 100644 --- a/sound/pci/hda/hda_beep.c +++ b/sound/pci/hda/hda_beep.c @@ -20,7 +20,6 @@ */ #include <linux/input.h> -#include <linux/pci.h> #include <linux/slab.h> #include <linux/workqueue.h> #include <linux/export.h> @@ -140,7 +139,10 @@ static void turn_off_beep(struct hda_beep *beep) static void snd_hda_do_detach(struct hda_beep *beep) { - input_unregister_device(beep->dev); + if (beep->registered) + input_unregister_device(beep->dev); + else + input_free_device(beep->dev); beep->dev = NULL; turn_off_beep(beep); } @@ -149,7 +151,6 @@ static int snd_hda_do_attach(struct hda_beep *beep) { struct input_dev *input_dev; struct hda_codec *codec = beep->codec; - int err; input_dev = input_allocate_device(); if (!input_dev) @@ -167,15 +168,9 @@ static int snd_hda_do_attach(struct hda_beep *beep) input_dev->evbit[0] = BIT_MASK(EV_SND); input_dev->sndbit[0] = BIT_MASK(SND_BELL) | BIT_MASK(SND_TONE); input_dev->event = snd_hda_beep_event; - input_dev->dev.parent = &codec->bus->pci->dev; + input_dev->dev.parent = &codec->dev; input_set_drvdata(input_dev, beep); - err = input_register_device(input_dev); - if (err < 0) { - input_free_device(input_dev); - printk(KERN_INFO "hda_beep: unable to register input device\n"); - return err; - } beep->dev = input_dev; return 0; } @@ -245,6 +240,27 @@ void snd_hda_detach_beep_device(struct hda_codec *codec) } EXPORT_SYMBOL_GPL(snd_hda_detach_beep_device); +int snd_hda_register_beep_device(struct hda_codec *codec) +{ + struct hda_beep *beep = codec->beep; + int err; + + if (!beep || !beep->dev) + return 0; + + err = input_register_device(beep->dev); + if (err < 0) { + codec_err(codec, "hda_beep: unable to register input device\n"); + input_free_device(beep->dev); + codec->beep = NULL; + kfree(beep); + return err; + } + beep->registered = true; + return 0; +} +EXPORT_SYMBOL_GPL(snd_hda_register_beep_device); + static bool ctl_has_mute(struct snd_kcontrol *kcontrol) { struct hda_codec *codec = snd_kcontrol_chip(kcontrol); diff --git a/sound/pci/hda/hda_beep.h b/sound/pci/hda/hda_beep.h index cb88464676b..a63b5e07733 100644 --- a/sound/pci/hda/hda_beep.h +++ b/sound/pci/hda/hda_beep.h @@ -34,6 +34,7 @@ struct hda_beep { char phys[32]; int tone; hda_nid_t nid; + unsigned int registered:1; unsigned int enabled:1; unsigned int linear_tone:1; /* linear tone for IDT/STAC codec */ unsigned int playing:1; @@ -45,6 +46,7 @@ struct hda_beep { int snd_hda_enable_beep_device(struct hda_codec *codec, int enable); int snd_hda_attach_beep_device(struct hda_codec *codec, int nid); void snd_hda_detach_beep_device(struct hda_codec *codec); +int snd_hda_register_beep_device(struct hda_codec *codec); #else static inline int snd_hda_attach_beep_device(struct hda_codec *codec, int nid) { @@ -53,5 +55,9 @@ static inline int snd_hda_attach_beep_device(struct hda_codec *codec, int nid) static inline void snd_hda_detach_beep_device(struct hda_codec *codec) { } +static inline int snd_hda_register_beep_device(struct hda_codec *codec) +{ + return 0; +} #endif #endif diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c index dafcf82139e..4c20277a683 100644 --- a/sound/pci/hda/hda_codec.c +++ b/sound/pci/hda/hda_codec.c @@ -23,7 +23,6 @@ #include <linux/init.h> #include <linux/delay.h> #include <linux/slab.h> -#include <linux/pci.h> #include <linux/mutex.h> #include <linux/module.h> #include <linux/async.h> @@ -68,6 +67,7 @@ static struct hda_vendor_id hda_vendor_ids[] = { { 0x17e8, "Chrontel" }, { 0x1854, "LG" }, { 0x1aec, "Wolfson Microelectronics" }, + { 0x1af4, "QEMU" }, { 0x434d, "C-Media" }, { 0x8086, "Intel" }, { 0x8384, "SigmaTel" }, @@ -201,7 +201,7 @@ make_codec_cmd(struct hda_codec *codec, hda_nid_t nid, int flags, if ((codec->addr & ~0xf) || (nid & ~0x7f) || (verb & ~0xfff) || (parm & ~0xffff)) { - printk(KERN_ERR "hda-codec: out of range cmd %x:%x:%x:%x\n", + codec_err(codec, "hda-codec: out of range cmd %x:%x:%x:%x\n", codec->addr, nid, verb, parm); return ~0; } @@ -249,8 +249,8 @@ static int codec_exec_verb(struct hda_codec *codec, unsigned int cmd, snd_hda_power_down(codec); if (!codec_in_pm(codec) && res && *res == -1 && bus->rirb_error) { if (bus->response_reset) { - snd_printd("hda_codec: resetting BUS due to " - "fatal communication error\n"); + codec_dbg(codec, + "resetting BUS due to fatal communication error\n"); trace_hda_bus_reset(bus); bus->ops.bus_reset(bus); } @@ -475,8 +475,7 @@ int snd_hda_get_connections(struct hda_codec *codec, hda_nid_t nid, if (len > 0 && conn_list) { if (len > max_conns) { - snd_printk(KERN_ERR "hda_codec: " - "Too many connections %d for NID 0x%x\n", + codec_err(codec, "Too many connections %d for NID 0x%x\n", len, nid); return -EINVAL; } @@ -574,8 +573,8 @@ int snd_hda_get_raw_connections(struct hda_codec *codec, hda_nid_t nid, range_val = !!(parm & (1 << (shift-1))); /* ranges */ val = parm & mask; if (val == 0 && null_count++) { /* no second chance */ - snd_printdd("hda_codec: " - "invalid CONNECT_LIST verb %x[%i]:%x\n", + codec_dbg(codec, + "invalid CONNECT_LIST verb %x[%i]:%x\n", nid, i, parm); return 0; } @@ -583,7 +582,7 @@ int snd_hda_get_raw_connections(struct hda_codec *codec, hda_nid_t nid, if (range_val) { /* ranges between the previous and this one */ if (!prev_nid || prev_nid >= val) { - snd_printk(KERN_WARNING "hda_codec: " + codec_warn(codec, "invalid dep_range_val %x:%x\n", prev_nid, val); continue; @@ -660,7 +659,7 @@ int snd_hda_get_conn_index(struct hda_codec *codec, hda_nid_t mux, if (!recursive) return -1; if (recursive > 10) { - snd_printd("hda_codec: too deep connection for 0x%x\n", nid); + codec_dbg(codec, "too deep connection for 0x%x\n", nid); return -1; } recursive++; @@ -808,8 +807,7 @@ static int init_unsol_queue(struct hda_bus *bus) unsol = kzalloc(sizeof(*unsol), GFP_KERNEL); if (!unsol) { - snd_printk(KERN_ERR "hda_codec: " - "can't allocate unsolicited queue\n"); + dev_err(bus->card->dev, "can't allocate unsolicited queue\n"); return -ENOMEM; } INIT_WORK(&unsol->work, process_unsol_events); @@ -821,51 +819,36 @@ static int init_unsol_queue(struct hda_bus *bus) /* * destructor */ -static void snd_hda_codec_free(struct hda_codec *codec); - -static int snd_hda_bus_free(struct hda_bus *bus) +static void snd_hda_bus_free(struct hda_bus *bus) { - struct hda_codec *codec, *n; - if (!bus) - return 0; + return; + + WARN_ON(!list_empty(&bus->codec_list)); if (bus->workq) flush_workqueue(bus->workq); if (bus->unsol) kfree(bus->unsol); - list_for_each_entry_safe(codec, n, &bus->codec_list, list) { - snd_hda_codec_free(codec); - } if (bus->ops.private_free) bus->ops.private_free(bus); if (bus->workq) destroy_workqueue(bus->workq); kfree(bus); - return 0; } static int snd_hda_bus_dev_free(struct snd_device *device) { - struct hda_bus *bus = device->device_data; - bus->shutdown = 1; - return snd_hda_bus_free(bus); + snd_hda_bus_free(device->device_data); + return 0; } -#ifdef CONFIG_SND_HDA_HWDEP -static int snd_hda_bus_dev_register(struct snd_device *device) +static int snd_hda_bus_dev_disconnect(struct snd_device *device) { struct hda_bus *bus = device->device_data; - struct hda_codec *codec; - list_for_each_entry(codec, &bus->codec_list, list) { - snd_hda_hwdep_add_sysfs(codec); - snd_hda_hwdep_add_power_sysfs(codec); - } + bus->shutdown = 1; return 0; } -#else -#define snd_hda_bus_dev_register NULL -#endif /** * snd_hda_bus_new - create a HDA bus @@ -882,7 +865,7 @@ int snd_hda_bus_new(struct snd_card *card, struct hda_bus *bus; int err; static struct snd_device_ops dev_ops = { - .dev_register = snd_hda_bus_dev_register, + .dev_disconnect = snd_hda_bus_dev_disconnect, .dev_free = snd_hda_bus_dev_free, }; @@ -896,7 +879,7 @@ int snd_hda_bus_new(struct snd_card *card, bus = kzalloc(sizeof(*bus), GFP_KERNEL); if (bus == NULL) { - snd_printk(KERN_ERR "can't allocate struct hda_bus\n"); + dev_err(card->dev, "can't allocate struct hda_bus\n"); return -ENOMEM; } @@ -915,7 +898,7 @@ int snd_hda_bus_new(struct snd_card *card, "hd-audio%d", card->number); bus->workq = create_singlethread_workqueue(bus->workq_name); if (!bus->workq) { - snd_printk(KERN_ERR "cannot create workqueue %s\n", + dev_err(card->dev, "cannot create workqueue %s\n", bus->workq_name); kfree(bus); return -ENOMEM; @@ -959,7 +942,7 @@ find_codec_preset(struct hda_codec *codec) mutex_lock(&preset_mutex); list_for_each_entry(tbl, &hda_preset_tables, list) { if (!try_module_get(tbl->owner)) { - snd_printk(KERN_ERR "hda_codec: cannot module_get\n"); + codec_err(codec, "cannot module_get\n"); continue; } for (preset = tbl->preset; preset->id; preset++) { @@ -1185,7 +1168,7 @@ unsigned int snd_hda_codec_get_pincfg(struct hda_codec *codec, hda_nid_t nid) { struct hda_pincfg *pin; -#ifdef CONFIG_SND_HDA_HWDEP +#ifdef CONFIG_SND_HDA_RECONFIG { unsigned int cfg = 0; mutex_lock(&codec->user_mutex); @@ -1300,7 +1283,7 @@ static void free_hda_cache(struct hda_cache_rec *cache); static void free_init_pincfgs(struct hda_codec *codec) { snd_array_free(&codec->driver_pins); -#ifdef CONFIG_SND_HDA_HWDEP +#ifdef CONFIG_SND_HDA_RECONFIG snd_array_free(&codec->user_pins); #endif snd_array_free(&codec->init_pins); @@ -1374,6 +1357,7 @@ static void snd_hda_codec_free(struct hda_codec *codec) if (codec->patch_ops.free) codec->patch_ops.free(codec); hda_call_pm_notify(codec, false); /* cancel leftover refcounts */ + snd_hda_sysfs_clear(codec); unload_parser(codec); module_put(codec->owner); free_hda_cache(&codec->amp_cache); @@ -1383,7 +1367,7 @@ static void snd_hda_codec_free(struct hda_codec *codec) kfree(codec->modelname); kfree(codec->wcaps); codec->bus->num_codecs--; - kfree(codec); + put_device(&codec->dev); } static bool snd_hda_codec_get_supported_ps(struct hda_codec *codec, @@ -1392,6 +1376,38 @@ static bool snd_hda_codec_get_supported_ps(struct hda_codec *codec, static unsigned int hda_set_power_state(struct hda_codec *codec, unsigned int power_state); +static int snd_hda_codec_dev_register(struct snd_device *device) +{ + struct hda_codec *codec = device->device_data; + int err = device_add(&codec->dev); + + if (err < 0) + return err; + snd_hda_register_beep_device(codec); + return 0; +} + +static int snd_hda_codec_dev_disconnect(struct snd_device *device) +{ + struct hda_codec *codec = device->device_data; + + snd_hda_detach_beep_device(codec); + device_del(&codec->dev); + return 0; +} + +static int snd_hda_codec_dev_free(struct snd_device *device) +{ + snd_hda_codec_free(device->device_data); + return 0; +} + +/* just free the container */ +static void snd_hda_codec_dev_release(struct device *dev) +{ + kfree(container_of(dev, struct hda_codec, dev)); +} + /** * snd_hda_codec_new - create a HDA codec * @bus: the bus to assign @@ -1408,6 +1424,11 @@ int snd_hda_codec_new(struct hda_bus *bus, char component[31]; hda_nid_t fg; int err; + static struct snd_device_ops dev_ops = { + .dev_register = snd_hda_codec_dev_register, + .dev_disconnect = snd_hda_codec_dev_disconnect, + .dev_free = snd_hda_codec_dev_free, + }; if (snd_BUG_ON(!bus)) return -EINVAL; @@ -1415,17 +1436,27 @@ int snd_hda_codec_new(struct hda_bus *bus, return -EINVAL; if (bus->caddr_tbl[codec_addr]) { - snd_printk(KERN_ERR "hda_codec: " - "address 0x%x is already occupied\n", codec_addr); + dev_err(bus->card->dev, + "address 0x%x is already occupied\n", + codec_addr); return -EBUSY; } codec = kzalloc(sizeof(*codec), GFP_KERNEL); if (codec == NULL) { - snd_printk(KERN_ERR "can't allocate struct hda_codec\n"); + dev_err(bus->card->dev, "can't allocate struct hda_codec\n"); return -ENOMEM; } + device_initialize(&codec->dev); + codec->dev.parent = &bus->card->card_dev; + codec->dev.class = sound_class; + codec->dev.release = snd_hda_codec_dev_release; + codec->dev.groups = snd_hda_dev_attr_groups; + dev_set_name(&codec->dev, "hdaudioC%dD%d", bus->card->number, + codec_addr); + dev_set_drvdata(&codec->dev, codec); /* for sysfs */ + codec->bus = bus; codec->addr = codec_addr; mutex_init(&codec->spdif_mutex); @@ -1456,11 +1487,13 @@ int snd_hda_codec_new(struct hda_bus *bus, hda_keep_power_on(codec); #endif + snd_hda_sysfs_init(codec); + if (codec->bus->modelname) { codec->modelname = kstrdup(codec->bus->modelname, GFP_KERNEL); if (!codec->modelname) { - snd_hda_codec_free(codec); - return -ENODEV; + err = -ENODEV; + goto error; } } @@ -1484,7 +1517,7 @@ int snd_hda_codec_new(struct hda_bus *bus, setup_fg_nodes(codec); if (!codec->afg && !codec->mfg) { - snd_printdd("hda_codec: no AFG or MFG node found\n"); + dev_err(bus->card->dev, "no AFG or MFG node found\n"); err = -ENODEV; goto error; } @@ -1492,7 +1525,7 @@ int snd_hda_codec_new(struct hda_bus *bus, fg = codec->afg ? codec->afg : codec->mfg; err = read_widget_caps(codec, fg); if (err < 0) { - snd_printk(KERN_ERR "hda_codec: cannot malloc\n"); + dev_err(bus->card->dev, "cannot malloc\n"); goto error; } err = read_pin_defaults(codec); @@ -1528,6 +1561,10 @@ int snd_hda_codec_new(struct hda_bus *bus, codec->subsystem_id, codec->revision_id); snd_component_add(codec->bus->card, component); + err = snd_device_new(bus->card, SNDRV_DEV_CODEC, codec, &dev_ops); + if (err < 0) + goto error; + if (codecp) *codecp = codec; return 0; @@ -1550,7 +1587,7 @@ int snd_hda_codec_update_widgets(struct hda_codec *codec) fg = codec->afg ? codec->afg : codec->mfg; err = read_widget_caps(codec, fg); if (err < 0) { - snd_printk(KERN_ERR "hda_codec: cannot malloc\n"); + codec_err(codec, "cannot malloc\n"); return err; } @@ -1627,7 +1664,7 @@ int snd_hda_codec_configure(struct hda_codec *codec) #endif } if (!patch) { - printk(KERN_ERR "hda-codec: No codec parser is available\n"); + codec_err(codec, "No codec parser is available\n"); return -ENODEV; } } @@ -1711,9 +1748,9 @@ void snd_hda_codec_setup_stream(struct hda_codec *codec, hda_nid_t nid, if (!nid) return; - snd_printdd("hda_codec_setup_stream: " - "NID=0x%x, stream=0x%x, channel=%d, format=0x%x\n", - nid, stream_tag, channel_id, format); + codec_dbg(codec, + "hda_codec_setup_stream: NID=0x%x, stream=0x%x, channel=%d, format=0x%x\n", + nid, stream_tag, channel_id, format); p = get_hda_cvt_setup(codec, nid); if (!p) return; @@ -1760,7 +1797,7 @@ void __snd_hda_codec_cleanup_stream(struct hda_codec *codec, hda_nid_t nid, if (codec->no_sticky_stream) do_now = 1; - snd_printdd("hda_codec_cleanup_stream: NID=0x%x\n", nid); + codec_dbg(codec, "hda_codec_cleanup_stream: NID=0x%x\n", nid); p = get_hda_cvt_setup(codec, nid); if (p) { /* here we just clear the active flag when do_now isn't set; @@ -2282,9 +2319,9 @@ int snd_hda_mixer_amp_volume_info(struct snd_kcontrol *kcontrol, uinfo->value.integer.min = 0; uinfo->value.integer.max = get_amp_max_value(codec, nid, dir, ofs); if (!uinfo->value.integer.max) { - printk(KERN_WARNING "hda_codec: " - "num_steps = 0 for NID=0x%x (ctl = %s)\n", nid, - kcontrol->id.name); + codec_warn(codec, + "num_steps = 0 for NID=0x%x (ctl = %s)\n", + nid, kcontrol->id.name); return -EINVAL; } return 0; @@ -2558,8 +2595,8 @@ int snd_hda_add_nid(struct hda_codec *codec, struct snd_kcontrol *kctl, item->nid = nid; return 0; } - printk(KERN_ERR "hda-codec: no NID for mapping control %s:%d:%d\n", - kctl->id.name, kctl->id.index, index); + codec_err(codec, "no NID for mapping control %s:%d:%d\n", + kctl->id.name, kctl->id.index, index); return -EINVAL; } EXPORT_SYMBOL_GPL(snd_hda_add_nid); @@ -2660,6 +2697,7 @@ int snd_hda_codec_reset(struct hda_codec *codec) bus->pcm_dev_bits); } } + snd_hda_detach_beep_device(codec); if (codec->patch_ops.free) codec->patch_ops.free(codec); memset(&codec->patch_ops, 0, sizeof(codec->patch_ops)); @@ -2751,7 +2789,7 @@ static int get_kctl_0dB_offset(struct snd_kcontrol *kctl, int *step_to_check) return -1; if (*step_to_check && *step_to_check != step) { snd_printk(KERN_ERR "hda_codec: Mismatching dB step for vmaster slave (%d!=%d)\n", - *step_to_check, step); +- *step_to_check, step); return -1; } *step_to_check = step; @@ -2821,7 +2859,7 @@ int __snd_hda_add_vmaster(struct hda_codec *codec, char *name, err = map_slaves(codec, slaves, suffix, check_slave_present, NULL); if (err != 1) { - snd_printdd("No slave found for %s\n", name); + codec_dbg(codec, "No slave found for %s\n", name); return 0; } kctl = snd_ctl_make_virtual_master(name, tlv); @@ -3487,7 +3525,7 @@ int snd_hda_create_dig_out_ctls(struct hda_codec *codec, idx = find_empty_mixer_ctl_idx(codec, "IEC958 Playback Switch", idx); if (idx < 0) { - printk(KERN_ERR "hda_codec: too many IEC958 outputs\n"); + codec_err(codec, "too many IEC958 outputs\n"); return -EBUSY; } spdif = snd_array_new(&codec->spdif_out); @@ -3691,7 +3729,7 @@ int snd_hda_create_spdif_in_ctls(struct hda_codec *codec, hda_nid_t nid) idx = find_empty_mixer_ctl_idx(codec, "IEC958 Capture Switch", 0); if (idx < 0) { - printk(KERN_ERR "hda_codec: too many IEC958 inputs\n"); + codec_err(codec, "too many IEC958 inputs\n"); return -EBUSY; } for (dig_mix = dig_in_ctls; dig_mix->name; dig_mix++) { @@ -4010,7 +4048,7 @@ static void sync_power_up_states(struct hda_codec *codec) } } -#ifdef CONFIG_SND_HDA_HWDEP +#ifdef CONFIG_SND_HDA_RECONFIG /* execute additional init verbs */ static void hda_exec_init_verbs(struct hda_codec *codec) { @@ -4118,12 +4156,13 @@ int snd_hda_build_controls(struct hda_bus *bus) list_for_each_entry(codec, &bus->codec_list, list) { int err = snd_hda_codec_build_controls(codec); if (err < 0) { - printk(KERN_ERR "hda_codec: cannot build controls " - "for #%d (error %d)\n", codec->addr, err); + codec_err(codec, + "cannot build controls for #%d (error %d)\n", + codec->addr, err); err = snd_hda_codec_reset(codec); if (err < 0) { - printk(KERN_ERR - "hda_codec: cannot revert codec\n"); + codec_err(codec, + "cannot revert codec\n"); return err; } } @@ -4294,7 +4333,7 @@ unsigned int snd_hda_calc_stream_format(unsigned int rate, break; default: snd_printdd("invalid format width %d\n", - snd_pcm_format_width(format)); + snd_pcm_format_width(format)); return 0; } @@ -4370,10 +4409,10 @@ int snd_hda_query_supported_pcm(struct hda_codec *codec, hda_nid_t nid, rates |= rate_bits[i].alsa_bits; } if (rates == 0) { - snd_printk(KERN_ERR "hda_codec: rates == 0 " - "(nid=0x%x, val=0x%x, ovrd=%i)\n", - nid, val, - (wcaps & AC_WCAP_FORMAT_OVRD) ? 1 : 0); + codec_err(codec, + "rates == 0 (nid=0x%x, val=0x%x, ovrd=%i)\n", + nid, val, + (wcaps & AC_WCAP_FORMAT_OVRD) ? 1 : 0); return -EIO; } *ratesp = rates; @@ -4433,12 +4472,11 @@ int snd_hda_query_supported_pcm(struct hda_codec *codec, hda_nid_t nid, bps = 8; } if (formats == 0) { - snd_printk(KERN_ERR "hda_codec: formats == 0 " - "(nid=0x%x, val=0x%x, ovrd=%i, " - "streams=0x%x)\n", - nid, val, - (wcaps & AC_WCAP_FORMAT_OVRD) ? 1 : 0, - streams); + codec_err(codec, + "formats == 0 (nid=0x%x, val=0x%x, ovrd=%i, streams=0x%x)\n", + nid, val, + (wcaps & AC_WCAP_FORMAT_OVRD) ? 1 : 0, + streams); return -EIO; } if (formatsp) @@ -4629,7 +4667,7 @@ static int get_empty_pcm_device(struct hda_bus *bus, unsigned int type) int i; if (type >= HDA_PCM_NTYPES) { - snd_printk(KERN_WARNING "Invalid PCM type %d\n", type); + dev_err(bus->card->dev, "Invalid PCM type %d\n", type); return -EINVAL; } @@ -4650,10 +4688,11 @@ static int get_empty_pcm_device(struct hda_bus *bus, unsigned int type) } #endif - snd_printk(KERN_WARNING "Too many %s devices\n", + dev_warn(bus->card->dev, "Too many %s devices\n", snd_hda_pcm_type_name[type]); #ifndef CONFIG_SND_DYNAMIC_MINORS - snd_printk(KERN_WARNING "Consider building the kernel with CONFIG_SND_DYNAMIC_MINORS=y\n"); + dev_warn(bus->card->dev, + "Consider building the kernel with CONFIG_SND_DYNAMIC_MINORS=y\n"); #endif return -EAGAIN; } @@ -4691,12 +4730,13 @@ int snd_hda_codec_build_pcms(struct hda_codec *codec) return 0; err = codec->patch_ops.build_pcms(codec); if (err < 0) { - printk(KERN_ERR "hda_codec: cannot build PCMs" - "for #%d (error %d)\n", codec->addr, err); + codec_err(codec, + "cannot build PCMs for #%d (error %d)\n", + codec->addr, err); err = snd_hda_codec_reset(codec); if (err < 0) { - printk(KERN_ERR - "hda_codec: cannot revert codec\n"); + codec_err(codec, + "cannot revert codec\n"); return err; } } @@ -4715,9 +4755,9 @@ int snd_hda_codec_build_pcms(struct hda_codec *codec) cpcm->device = dev; err = snd_hda_attach_pcm(codec, cpcm); if (err < 0) { - printk(KERN_ERR "hda_codec: cannot attach " - "PCM stream %d for codec #%d\n", - dev, codec->addr); + codec_err(codec, + "cannot attach PCM stream %d for codec #%d\n", + dev, codec->addr); continue; /* no fatal error */ } } @@ -4786,8 +4826,8 @@ int snd_hda_check_board_config(struct hda_codec *codec, for (i = 0; i < num_configs; i++) { if (models[i] && !strcmp(codec->modelname, models[i])) { - snd_printd(KERN_INFO "hda_codec: model '%s' is " - "selected\n", models[i]); + codec_info(codec, "model '%s' is selected\n", + models[i]); return i; } } @@ -4809,10 +4849,9 @@ int snd_hda_check_board_config(struct hda_codec *codec, sprintf(tmp, "#%d", tbl->value); model = tmp; } - snd_printdd(KERN_INFO "hda_codec: model '%s' is selected " - "for config %x:%x (%s)\n", - model, tbl->subvendor, tbl->subdevice, - (tbl->name ? tbl->name : "Unknown device")); + 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; } @@ -4870,10 +4909,9 @@ int snd_hda_check_board_codec_sid_config(struct hda_codec *codec, sprintf(tmp, "#%d", tbl->value); model = tmp; } - snd_printdd(KERN_INFO "hda_codec: model '%s' is selected " - "for config %x:%x (%s)\n", - model, tbl->subvendor, tbl->subdevice, - (tbl->name ? tbl->name : "Unknown device")); + 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; } diff --git a/sound/pci/hda/hda_codec.h b/sound/pci/hda/hda_codec.h index ab2a444ba50..a4233136cb9 100644 --- a/sound/pci/hda/hda_codec.h +++ b/sound/pci/hda/hda_codec.h @@ -271,6 +271,7 @@ struct hda_pcm { /* codec information */ struct hda_codec { + struct device dev; struct hda_bus *bus; unsigned int addr; /* codec addr*/ struct list_head list; /* list point */ @@ -332,14 +333,17 @@ struct hda_codec { struct snd_array driver_pins; /* pin configs set by codec parser */ struct snd_array cvt_setups; /* audio convert setups */ -#ifdef CONFIG_SND_HDA_HWDEP struct mutex user_mutex; - struct snd_hwdep *hwdep; /* assigned hwdep device */ +#ifdef CONFIG_SND_HDA_RECONFIG struct snd_array init_verbs; /* additional init verbs */ struct snd_array hints; /* additional hints */ struct snd_array user_pins; /* default pin configs to override */ #endif +#ifdef CONFIG_SND_HDA_HWDEP + struct snd_hwdep *hwdep; /* assigned hwdep device */ +#endif + /* misc flags */ unsigned int spdif_status_reset :1; /* needs to toggle SPDIF for each * status change diff --git a/sound/pci/hda/hda_controller.c b/sound/pci/hda/hda_controller.c new file mode 100644 index 00000000000..97993e17f46 --- /dev/null +++ b/sound/pci/hda/hda_controller.c @@ -0,0 +1,2031 @@ +/* + * + * Implementation of primary alsa driver code base for Intel HD Audio. + * + * Copyright(c) 2004 Intel Corporation. All rights reserved. + * + * Copyright (c) 2004 Takashi Iwai <tiwai@suse.de> + * PeiSen Hou <pshou@realtek.com.tw> + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the Free + * Software Foundation; either version 2 of the License, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * + */ + +#include <linux/clocksource.h> +#include <linux/delay.h> +#include <linux/interrupt.h> +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/pm_runtime.h> +#include <linux/slab.h> +#include <sound/core.h> +#include <sound/initval.h> +#include "hda_priv.h" +#include "hda_controller.h" + +#define CREATE_TRACE_POINTS +#include "hda_intel_trace.h" + +/* DSP lock helpers */ +#ifdef CONFIG_SND_HDA_DSP_LOADER +#define dsp_lock_init(dev) mutex_init(&(dev)->dsp_mutex) +#define dsp_lock(dev) mutex_lock(&(dev)->dsp_mutex) +#define dsp_unlock(dev) mutex_unlock(&(dev)->dsp_mutex) +#define dsp_is_locked(dev) ((dev)->locked) +#else +#define dsp_lock_init(dev) do {} while (0) +#define dsp_lock(dev) do {} while (0) +#define dsp_unlock(dev) do {} while (0) +#define dsp_is_locked(dev) 0 +#endif + +/* + * AZX stream operations. + */ + +/* start a stream */ +static void azx_stream_start(struct azx *chip, struct azx_dev *azx_dev) +{ + /* + * Before stream start, initialize parameter + */ + azx_dev->insufficient = 1; + + /* enable SIE */ + azx_writel(chip, INTCTL, + azx_readl(chip, INTCTL) | (1 << azx_dev->index)); + /* set DMA start and interrupt mask */ + azx_sd_writeb(chip, azx_dev, SD_CTL, + azx_sd_readb(chip, azx_dev, SD_CTL) | + SD_CTL_DMA_START | SD_INT_MASK); +} + +/* stop DMA */ +static void azx_stream_clear(struct azx *chip, struct azx_dev *azx_dev) +{ + azx_sd_writeb(chip, azx_dev, SD_CTL, + azx_sd_readb(chip, azx_dev, SD_CTL) & + ~(SD_CTL_DMA_START | SD_INT_MASK)); + azx_sd_writeb(chip, azx_dev, SD_STS, SD_INT_MASK); /* to be sure */ +} + +/* stop a stream */ +void azx_stream_stop(struct azx *chip, struct azx_dev *azx_dev) +{ + azx_stream_clear(chip, azx_dev); + /* disable SIE */ + azx_writel(chip, INTCTL, + azx_readl(chip, INTCTL) & ~(1 << azx_dev->index)); +} +EXPORT_SYMBOL_GPL(azx_stream_stop); + +/* reset stream */ +static void azx_stream_reset(struct azx *chip, struct azx_dev *azx_dev) +{ + unsigned char val; + int timeout; + + azx_stream_clear(chip, azx_dev); + + azx_sd_writeb(chip, azx_dev, SD_CTL, + azx_sd_readb(chip, azx_dev, SD_CTL) | + SD_CTL_STREAM_RESET); + udelay(3); + timeout = 300; + while (!((val = azx_sd_readb(chip, azx_dev, SD_CTL)) & + SD_CTL_STREAM_RESET) && --timeout) + ; + val &= ~SD_CTL_STREAM_RESET; + azx_sd_writeb(chip, azx_dev, SD_CTL, val); + udelay(3); + + timeout = 300; + /* waiting for hardware to report that the stream is out of reset */ + while (((val = azx_sd_readb(chip, azx_dev, SD_CTL)) & + SD_CTL_STREAM_RESET) && --timeout) + ; + + /* reset first position - may not be synced with hw at this time */ + *azx_dev->posbuf = 0; +} + +/* + * set up the SD for streaming + */ +static int azx_setup_controller(struct azx *chip, struct azx_dev *azx_dev) +{ + unsigned int val; + /* make sure the run bit is zero for SD */ + azx_stream_clear(chip, azx_dev); + /* program the stream_tag */ + val = azx_sd_readl(chip, azx_dev, SD_CTL); + val = (val & ~SD_CTL_STREAM_TAG_MASK) | + (azx_dev->stream_tag << SD_CTL_STREAM_TAG_SHIFT); + if (!azx_snoop(chip)) + val |= SD_CTL_TRAFFIC_PRIO; + azx_sd_writel(chip, azx_dev, SD_CTL, val); + + /* program the length of samples in cyclic buffer */ + azx_sd_writel(chip, azx_dev, SD_CBL, azx_dev->bufsize); + + /* program the stream format */ + /* this value needs to be the same as the one programmed */ + azx_sd_writew(chip, azx_dev, SD_FORMAT, azx_dev->format_val); + + /* program the stream LVI (last valid index) of the BDL */ + azx_sd_writew(chip, azx_dev, SD_LVI, azx_dev->frags - 1); + + /* program the BDL address */ + /* lower BDL address */ + azx_sd_writel(chip, azx_dev, SD_BDLPL, (u32)azx_dev->bdl.addr); + /* upper BDL address */ + azx_sd_writel(chip, azx_dev, SD_BDLPU, + upper_32_bits(azx_dev->bdl.addr)); + + /* enable the position buffer */ + if (chip->position_fix[0] != POS_FIX_LPIB || + chip->position_fix[1] != POS_FIX_LPIB) { + if (!(azx_readl(chip, DPLBASE) & ICH6_DPLBASE_ENABLE)) + azx_writel(chip, DPLBASE, + (u32)chip->posbuf.addr | ICH6_DPLBASE_ENABLE); + } + + /* set the interrupt enable bits in the descriptor control register */ + azx_sd_writel(chip, azx_dev, SD_CTL, + azx_sd_readl(chip, azx_dev, SD_CTL) | SD_INT_MASK); + + return 0; +} + +/* assign a stream for the PCM */ +static inline struct azx_dev * +azx_assign_device(struct azx *chip, struct snd_pcm_substream *substream) +{ + int dev, i, nums; + struct azx_dev *res = NULL; + /* make a non-zero unique key for the substream */ + int key = (substream->pcm->device << 16) | (substream->number << 2) | + (substream->stream + 1); + + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { + dev = chip->playback_index_offset; + nums = chip->playback_streams; + } else { + dev = chip->capture_index_offset; + nums = chip->capture_streams; + } + for (i = 0; i < nums; i++, dev++) { + struct azx_dev *azx_dev = &chip->azx_dev[dev]; + dsp_lock(azx_dev); + if (!azx_dev->opened && !dsp_is_locked(azx_dev)) { + res = azx_dev; + if (res->assigned_key == key) { + res->opened = 1; + res->assigned_key = key; + dsp_unlock(azx_dev); + return azx_dev; + } + } + dsp_unlock(azx_dev); + } + if (res) { + dsp_lock(res); + res->opened = 1; + res->assigned_key = key; + dsp_unlock(res); + } + return res; +} + +/* release the assigned stream */ +static inline void azx_release_device(struct azx_dev *azx_dev) +{ + azx_dev->opened = 0; +} + +static cycle_t azx_cc_read(const struct cyclecounter *cc) +{ + struct azx_dev *azx_dev = container_of(cc, struct azx_dev, azx_cc); + struct snd_pcm_substream *substream = azx_dev->substream; + struct azx_pcm *apcm = snd_pcm_substream_chip(substream); + struct azx *chip = apcm->chip; + + return azx_readl(chip, WALLCLK); +} + +static void azx_timecounter_init(struct snd_pcm_substream *substream, + bool force, cycle_t last) +{ + struct azx_dev *azx_dev = get_azx_dev(substream); + struct timecounter *tc = &azx_dev->azx_tc; + struct cyclecounter *cc = &azx_dev->azx_cc; + u64 nsec; + + cc->read = azx_cc_read; + cc->mask = CLOCKSOURCE_MASK(32); + + /* + * Converting from 24 MHz to ns means applying a 125/3 factor. + * To avoid any saturation issues in intermediate operations, + * the 125 factor is applied first. The division is applied + * last after reading the timecounter value. + * Applying the 1/3 factor as part of the multiplication + * requires at least 20 bits for a decent precision, however + * overflows occur after about 4 hours or less, not a option. + */ + + cc->mult = 125; /* saturation after 195 years */ + cc->shift = 0; + + nsec = 0; /* audio time is elapsed time since trigger */ + timecounter_init(tc, cc, nsec); + if (force) + /* + * force timecounter to use predefined value, + * used for synchronized starts + */ + tc->cycle_last = last; +} + +static u64 azx_adjust_codec_delay(struct snd_pcm_substream *substream, + u64 nsec) +{ + struct azx_pcm *apcm = snd_pcm_substream_chip(substream); + struct hda_pcm_stream *hinfo = apcm->hinfo[substream->stream]; + u64 codec_frames, codec_nsecs; + + if (!hinfo->ops.get_delay) + return nsec; + + codec_frames = hinfo->ops.get_delay(hinfo, apcm->codec, substream); + codec_nsecs = div_u64(codec_frames * 1000000000LL, + substream->runtime->rate); + + if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) + return nsec + codec_nsecs; + + return (nsec > codec_nsecs) ? nsec - codec_nsecs : 0; +} + +/* + * set up a BDL entry + */ +static int setup_bdle(struct azx *chip, + struct snd_dma_buffer *dmab, + struct azx_dev *azx_dev, u32 **bdlp, + int ofs, int size, int with_ioc) +{ + u32 *bdl = *bdlp; + + while (size > 0) { + dma_addr_t addr; + int chunk; + + if (azx_dev->frags >= AZX_MAX_BDL_ENTRIES) + return -EINVAL; + + addr = snd_sgbuf_get_addr(dmab, ofs); + /* program the address field of the BDL entry */ + bdl[0] = cpu_to_le32((u32)addr); + bdl[1] = cpu_to_le32(upper_32_bits(addr)); + /* program the size field of the BDL entry */ + chunk = snd_sgbuf_get_chunk_size(dmab, ofs, size); + /* one BDLE cannot cross 4K boundary on CTHDA chips */ + if (chip->driver_caps & AZX_DCAPS_4K_BDLE_BOUNDARY) { + u32 remain = 0x1000 - (ofs & 0xfff); + if (chunk > remain) + chunk = remain; + } + bdl[2] = cpu_to_le32(chunk); + /* program the IOC to enable interrupt + * only when the whole fragment is processed + */ + size -= chunk; + bdl[3] = (size || !with_ioc) ? 0 : cpu_to_le32(0x01); + bdl += 4; + azx_dev->frags++; + ofs += chunk; + } + *bdlp = bdl; + return ofs; +} + +/* + * set up BDL entries + */ +static int azx_setup_periods(struct azx *chip, + struct snd_pcm_substream *substream, + struct azx_dev *azx_dev) +{ + u32 *bdl; + int i, ofs, periods, period_bytes; + int pos_adj = 0; + + /* reset BDL address */ + azx_sd_writel(chip, azx_dev, SD_BDLPL, 0); + azx_sd_writel(chip, azx_dev, SD_BDLPU, 0); + + period_bytes = azx_dev->period_bytes; + periods = azx_dev->bufsize / period_bytes; + + /* program the initial BDL entries */ + bdl = (u32 *)azx_dev->bdl.area; + ofs = 0; + azx_dev->frags = 0; + + if (chip->bdl_pos_adj) + pos_adj = chip->bdl_pos_adj[chip->dev_index]; + if (!azx_dev->no_period_wakeup && pos_adj > 0) { + struct snd_pcm_runtime *runtime = substream->runtime; + int pos_align = pos_adj; + pos_adj = (pos_adj * runtime->rate + 47999) / 48000; + if (!pos_adj) + pos_adj = pos_align; + else + pos_adj = ((pos_adj + pos_align - 1) / pos_align) * + pos_align; + pos_adj = frames_to_bytes(runtime, pos_adj); + if (pos_adj >= period_bytes) { + dev_warn(chip->card->dev,"Too big adjustment %d\n", + pos_adj); + pos_adj = 0; + } else { + ofs = setup_bdle(chip, snd_pcm_get_dma_buf(substream), + azx_dev, + &bdl, ofs, pos_adj, true); + if (ofs < 0) + goto error; + } + } else + pos_adj = 0; + + for (i = 0; i < periods; i++) { + if (i == periods - 1 && pos_adj) + ofs = setup_bdle(chip, snd_pcm_get_dma_buf(substream), + azx_dev, &bdl, ofs, + period_bytes - pos_adj, 0); + else + ofs = setup_bdle(chip, snd_pcm_get_dma_buf(substream), + azx_dev, &bdl, ofs, + period_bytes, + !azx_dev->no_period_wakeup); + if (ofs < 0) + goto error; + } + return 0; + + error: + dev_err(chip->card->dev, "Too many BDL entries: buffer=%d, period=%d\n", + azx_dev->bufsize, period_bytes); + return -EINVAL; +} + +/* + * PCM ops + */ + +static int azx_pcm_close(struct snd_pcm_substream *substream) +{ + struct azx_pcm *apcm = snd_pcm_substream_chip(substream); + struct hda_pcm_stream *hinfo = apcm->hinfo[substream->stream]; + struct azx *chip = apcm->chip; + struct azx_dev *azx_dev = get_azx_dev(substream); + unsigned long flags; + + mutex_lock(&chip->open_mutex); + spin_lock_irqsave(&chip->reg_lock, flags); + azx_dev->substream = NULL; + azx_dev->running = 0; + spin_unlock_irqrestore(&chip->reg_lock, flags); + azx_release_device(azx_dev); + hinfo->ops.close(hinfo, apcm->codec, substream); + snd_hda_power_down(apcm->codec); + mutex_unlock(&chip->open_mutex); + return 0; +} + +static int azx_pcm_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *hw_params) +{ + struct azx_pcm *apcm = snd_pcm_substream_chip(substream); + struct azx *chip = apcm->chip; + int ret; + + dsp_lock(get_azx_dev(substream)); + if (dsp_is_locked(get_azx_dev(substream))) { + ret = -EBUSY; + goto unlock; + } + + ret = chip->ops->substream_alloc_pages(chip, substream, + params_buffer_bytes(hw_params)); +unlock: + dsp_unlock(get_azx_dev(substream)); + return ret; +} + +static int azx_pcm_hw_free(struct snd_pcm_substream *substream) +{ + struct azx_pcm *apcm = snd_pcm_substream_chip(substream); + struct azx_dev *azx_dev = get_azx_dev(substream); + struct azx *chip = apcm->chip; + struct hda_pcm_stream *hinfo = apcm->hinfo[substream->stream]; + int err; + + /* reset BDL address */ + dsp_lock(azx_dev); + if (!dsp_is_locked(azx_dev)) { + azx_sd_writel(chip, azx_dev, SD_BDLPL, 0); + azx_sd_writel(chip, azx_dev, SD_BDLPU, 0); + azx_sd_writel(chip, azx_dev, SD_CTL, 0); + azx_dev->bufsize = 0; + azx_dev->period_bytes = 0; + azx_dev->format_val = 0; + } + + snd_hda_codec_cleanup(apcm->codec, hinfo, substream); + + err = chip->ops->substream_free_pages(chip, substream); + azx_dev->prepared = 0; + dsp_unlock(azx_dev); + return err; +} + +static int azx_pcm_prepare(struct snd_pcm_substream *substream) +{ + struct azx_pcm *apcm = snd_pcm_substream_chip(substream); + struct azx *chip = apcm->chip; + struct azx_dev *azx_dev = get_azx_dev(substream); + struct hda_pcm_stream *hinfo = apcm->hinfo[substream->stream]; + struct snd_pcm_runtime *runtime = substream->runtime; + unsigned int bufsize, period_bytes, format_val, stream_tag; + int err; + struct hda_spdif_out *spdif = + snd_hda_spdif_out_of_nid(apcm->codec, hinfo->nid); + unsigned short ctls = spdif ? spdif->ctls : 0; + + dsp_lock(azx_dev); + if (dsp_is_locked(azx_dev)) { + err = -EBUSY; + goto unlock; + } + + azx_stream_reset(chip, azx_dev); + format_val = snd_hda_calc_stream_format(runtime->rate, + runtime->channels, + runtime->format, + hinfo->maxbps, + ctls); + if (!format_val) { + dev_err(chip->card->dev, + "invalid format_val, rate=%d, ch=%d, format=%d\n", + runtime->rate, runtime->channels, runtime->format); + err = -EINVAL; + goto unlock; + } + + bufsize = snd_pcm_lib_buffer_bytes(substream); + period_bytes = snd_pcm_lib_period_bytes(substream); + + dev_dbg(chip->card->dev, "azx_pcm_prepare: bufsize=0x%x, format=0x%x\n", + bufsize, format_val); + + if (bufsize != azx_dev->bufsize || + period_bytes != azx_dev->period_bytes || + format_val != azx_dev->format_val || + runtime->no_period_wakeup != azx_dev->no_period_wakeup) { + azx_dev->bufsize = bufsize; + azx_dev->period_bytes = period_bytes; + azx_dev->format_val = format_val; + azx_dev->no_period_wakeup = runtime->no_period_wakeup; + err = azx_setup_periods(chip, substream, azx_dev); + if (err < 0) + goto unlock; + } + + /* when LPIB delay correction gives a small negative value, + * we ignore it; currently set the threshold statically to + * 64 frames + */ + if (runtime->period_size > 64) + azx_dev->delay_negative_threshold = -frames_to_bytes(runtime, 64); + else + azx_dev->delay_negative_threshold = 0; + + /* wallclk has 24Mhz clock source */ + azx_dev->period_wallclk = (((runtime->period_size * 24000) / + runtime->rate) * 1000); + azx_setup_controller(chip, azx_dev); + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) + azx_dev->fifo_size = + azx_sd_readw(chip, azx_dev, SD_FIFOSIZE) + 1; + else + azx_dev->fifo_size = 0; + + stream_tag = azx_dev->stream_tag; + /* CA-IBG chips need the playback stream starting from 1 */ + if ((chip->driver_caps & AZX_DCAPS_CTX_WORKAROUND) && + stream_tag > chip->capture_streams) + stream_tag -= chip->capture_streams; + err = snd_hda_codec_prepare(apcm->codec, hinfo, stream_tag, + azx_dev->format_val, substream); + + unlock: + if (!err) + azx_dev->prepared = 1; + dsp_unlock(azx_dev); + return err; +} + +static int azx_pcm_trigger(struct snd_pcm_substream *substream, int cmd) +{ + struct azx_pcm *apcm = snd_pcm_substream_chip(substream); + struct azx *chip = apcm->chip; + struct azx_dev *azx_dev; + struct snd_pcm_substream *s; + int rstart = 0, start, nsync = 0, sbits = 0; + int nwait, timeout; + + azx_dev = get_azx_dev(substream); + trace_azx_pcm_trigger(chip, azx_dev, cmd); + + if (dsp_is_locked(azx_dev) || !azx_dev->prepared) + return -EPIPE; + + switch (cmd) { + case SNDRV_PCM_TRIGGER_START: + rstart = 1; + case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: + case SNDRV_PCM_TRIGGER_RESUME: + start = 1; + break; + case SNDRV_PCM_TRIGGER_PAUSE_PUSH: + case SNDRV_PCM_TRIGGER_SUSPEND: + case SNDRV_PCM_TRIGGER_STOP: + start = 0; + break; + default: + return -EINVAL; + } + + snd_pcm_group_for_each_entry(s, substream) { + if (s->pcm->card != substream->pcm->card) + continue; + azx_dev = get_azx_dev(s); + sbits |= 1 << azx_dev->index; + nsync++; + snd_pcm_trigger_done(s, substream); + } + + spin_lock(&chip->reg_lock); + + /* first, set SYNC bits of corresponding streams */ + if (chip->driver_caps & AZX_DCAPS_OLD_SSYNC) + azx_writel(chip, OLD_SSYNC, + azx_readl(chip, OLD_SSYNC) | sbits); + else + azx_writel(chip, SSYNC, azx_readl(chip, SSYNC) | sbits); + + snd_pcm_group_for_each_entry(s, substream) { + if (s->pcm->card != substream->pcm->card) + continue; + azx_dev = get_azx_dev(s); + if (start) { + azx_dev->start_wallclk = azx_readl(chip, WALLCLK); + if (!rstart) + azx_dev->start_wallclk -= + azx_dev->period_wallclk; + azx_stream_start(chip, azx_dev); + } else { + azx_stream_stop(chip, azx_dev); + } + azx_dev->running = start; + } + spin_unlock(&chip->reg_lock); + if (start) { + /* wait until all FIFOs get ready */ + for (timeout = 5000; timeout; timeout--) { + nwait = 0; + snd_pcm_group_for_each_entry(s, substream) { + if (s->pcm->card != substream->pcm->card) + continue; + azx_dev = get_azx_dev(s); + if (!(azx_sd_readb(chip, azx_dev, SD_STS) & + SD_STS_FIFO_READY)) + nwait++; + } + if (!nwait) + break; + cpu_relax(); + } + } else { + /* wait until all RUN bits are cleared */ + for (timeout = 5000; timeout; timeout--) { + nwait = 0; + snd_pcm_group_for_each_entry(s, substream) { + if (s->pcm->card != substream->pcm->card) + continue; + azx_dev = get_azx_dev(s); + if (azx_sd_readb(chip, azx_dev, SD_CTL) & + SD_CTL_DMA_START) + nwait++; + } + if (!nwait) + break; + cpu_relax(); + } + } + spin_lock(&chip->reg_lock); + /* reset SYNC bits */ + if (chip->driver_caps & AZX_DCAPS_OLD_SSYNC) + azx_writel(chip, OLD_SSYNC, + azx_readl(chip, OLD_SSYNC) & ~sbits); + else + azx_writel(chip, SSYNC, azx_readl(chip, SSYNC) & ~sbits); + if (start) { + azx_timecounter_init(substream, 0, 0); + if (nsync > 1) { + cycle_t cycle_last; + + /* same start cycle for master and group */ + azx_dev = get_azx_dev(substream); + cycle_last = azx_dev->azx_tc.cycle_last; + + snd_pcm_group_for_each_entry(s, substream) { + if (s->pcm->card != substream->pcm->card) + continue; + azx_timecounter_init(s, 1, cycle_last); + } + } + } + spin_unlock(&chip->reg_lock); + return 0; +} + +/* get the current DMA position with correction on VIA chips */ +static unsigned int azx_via_get_position(struct azx *chip, + struct azx_dev *azx_dev) +{ + unsigned int link_pos, mini_pos, bound_pos; + unsigned int mod_link_pos, mod_dma_pos, mod_mini_pos; + unsigned int fifo_size; + + link_pos = azx_sd_readl(chip, azx_dev, SD_LPIB); + if (azx_dev->substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { + /* Playback, no problem using link position */ + return link_pos; + } + + /* Capture */ + /* For new chipset, + * use mod to get the DMA position just like old chipset + */ + mod_dma_pos = le32_to_cpu(*azx_dev->posbuf); + mod_dma_pos %= azx_dev->period_bytes; + + /* azx_dev->fifo_size can't get FIFO size of in stream. + * Get from base address + offset. + */ + fifo_size = readw(chip->remap_addr + VIA_IN_STREAM0_FIFO_SIZE_OFFSET); + + if (azx_dev->insufficient) { + /* Link position never gather than FIFO size */ + if (link_pos <= fifo_size) + return 0; + + azx_dev->insufficient = 0; + } + + if (link_pos <= fifo_size) + mini_pos = azx_dev->bufsize + link_pos - fifo_size; + else + mini_pos = link_pos - fifo_size; + + /* Find nearest previous boudary */ + mod_mini_pos = mini_pos % azx_dev->period_bytes; + mod_link_pos = link_pos % azx_dev->period_bytes; + if (mod_link_pos >= fifo_size) + bound_pos = link_pos - mod_link_pos; + else if (mod_dma_pos >= mod_mini_pos) + bound_pos = mini_pos - mod_mini_pos; + else { + bound_pos = mini_pos - mod_mini_pos + azx_dev->period_bytes; + if (bound_pos >= azx_dev->bufsize) + bound_pos = 0; + } + + /* Calculate real DMA position we want */ + return bound_pos + mod_dma_pos; +} + +unsigned int azx_get_position(struct azx *chip, + struct azx_dev *azx_dev, + bool with_check) +{ + struct snd_pcm_substream *substream = azx_dev->substream; + struct azx_pcm *apcm = snd_pcm_substream_chip(substream); + unsigned int pos; + int stream = substream->stream; + struct hda_pcm_stream *hinfo = apcm->hinfo[stream]; + int delay = 0; + + switch (chip->position_fix[stream]) { + case POS_FIX_LPIB: + /* read LPIB */ + pos = azx_sd_readl(chip, azx_dev, SD_LPIB); + break; + case POS_FIX_VIACOMBO: + pos = azx_via_get_position(chip, azx_dev); + break; + default: + /* use the position buffer */ + pos = le32_to_cpu(*azx_dev->posbuf); + if (with_check && chip->position_fix[stream] == POS_FIX_AUTO) { + if (!pos || pos == (u32)-1) { + dev_info(chip->card->dev, + "Invalid position buffer, using LPIB read method instead.\n"); + chip->position_fix[stream] = POS_FIX_LPIB; + pos = azx_sd_readl(chip, azx_dev, SD_LPIB); + } else + chip->position_fix[stream] = POS_FIX_POSBUF; + } + break; + } + + if (pos >= azx_dev->bufsize) + pos = 0; + + /* calculate runtime delay from LPIB */ + if (substream->runtime && + chip->position_fix[stream] == POS_FIX_POSBUF && + (chip->driver_caps & AZX_DCAPS_COUNT_LPIB_DELAY)) { + unsigned int lpib_pos = azx_sd_readl(chip, azx_dev, SD_LPIB); + if (stream == SNDRV_PCM_STREAM_PLAYBACK) + delay = pos - lpib_pos; + else + delay = lpib_pos - pos; + if (delay < 0) { + if (delay >= azx_dev->delay_negative_threshold) + delay = 0; + else + delay += azx_dev->bufsize; + } + if (delay >= azx_dev->period_bytes) { + dev_info(chip->card->dev, + "Unstable LPIB (%d >= %d); disabling LPIB delay counting\n", + delay, azx_dev->period_bytes); + delay = 0; + chip->driver_caps &= ~AZX_DCAPS_COUNT_LPIB_DELAY; + } + delay = bytes_to_frames(substream->runtime, delay); + } + + if (substream->runtime) { + if (hinfo->ops.get_delay) + delay += hinfo->ops.get_delay(hinfo, apcm->codec, + substream); + substream->runtime->delay = delay; + } + + trace_azx_get_position(chip, azx_dev, pos, delay); + return pos; +} +EXPORT_SYMBOL_GPL(azx_get_position); + +static snd_pcm_uframes_t azx_pcm_pointer(struct snd_pcm_substream *substream) +{ + struct azx_pcm *apcm = snd_pcm_substream_chip(substream); + struct azx *chip = apcm->chip; + struct azx_dev *azx_dev = get_azx_dev(substream); + return bytes_to_frames(substream->runtime, + azx_get_position(chip, azx_dev, false)); +} + +static int azx_get_wallclock_tstamp(struct snd_pcm_substream *substream, + struct timespec *ts) +{ + struct azx_dev *azx_dev = get_azx_dev(substream); + u64 nsec; + + nsec = timecounter_read(&azx_dev->azx_tc); + nsec = div_u64(nsec, 3); /* can be optimized */ + nsec = azx_adjust_codec_delay(substream, nsec); + + *ts = ns_to_timespec(nsec); + + return 0; +} + +static struct snd_pcm_hardware azx_pcm_hw = { + .info = (SNDRV_PCM_INFO_MMAP | + SNDRV_PCM_INFO_INTERLEAVED | + SNDRV_PCM_INFO_BLOCK_TRANSFER | + SNDRV_PCM_INFO_MMAP_VALID | + /* No full-resume yet implemented */ + /* SNDRV_PCM_INFO_RESUME |*/ + SNDRV_PCM_INFO_PAUSE | + SNDRV_PCM_INFO_SYNC_START | + SNDRV_PCM_INFO_HAS_WALL_CLOCK | + SNDRV_PCM_INFO_NO_PERIOD_WAKEUP), + .formats = SNDRV_PCM_FMTBIT_S16_LE, + .rates = SNDRV_PCM_RATE_48000, + .rate_min = 48000, + .rate_max = 48000, + .channels_min = 2, + .channels_max = 2, + .buffer_bytes_max = AZX_MAX_BUF_SIZE, + .period_bytes_min = 128, + .period_bytes_max = AZX_MAX_BUF_SIZE / 2, + .periods_min = 2, + .periods_max = AZX_MAX_FRAG, + .fifo_size = 0, +}; + +static int azx_pcm_open(struct snd_pcm_substream *substream) +{ + struct azx_pcm *apcm = snd_pcm_substream_chip(substream); + struct hda_pcm_stream *hinfo = apcm->hinfo[substream->stream]; + struct azx *chip = apcm->chip; + struct azx_dev *azx_dev; + struct snd_pcm_runtime *runtime = substream->runtime; + unsigned long flags; + int err; + int buff_step; + + mutex_lock(&chip->open_mutex); + azx_dev = azx_assign_device(chip, substream); + if (azx_dev == NULL) { + mutex_unlock(&chip->open_mutex); + return -EBUSY; + } + runtime->hw = azx_pcm_hw; + runtime->hw.channels_min = hinfo->channels_min; + runtime->hw.channels_max = hinfo->channels_max; + runtime->hw.formats = hinfo->formats; + runtime->hw.rates = hinfo->rates; + snd_pcm_limit_hw_rates(runtime); + snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS); + + /* avoid wrap-around with wall-clock */ + snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_BUFFER_TIME, + 20, + 178000000); + + if (chip->align_buffer_size) + /* constrain buffer sizes to be multiple of 128 + bytes. This is more efficient in terms of memory + access but isn't required by the HDA spec and + prevents users from specifying exact period/buffer + sizes. For example for 44.1kHz, a period size set + to 20ms will be rounded to 19.59ms. */ + buff_step = 128; + else + /* Don't enforce steps on buffer sizes, still need to + be multiple of 4 bytes (HDA spec). Tested on Intel + HDA controllers, may not work on all devices where + option needs to be disabled */ + buff_step = 4; + + snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_BUFFER_BYTES, + buff_step); + snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_BYTES, + buff_step); + snd_hda_power_up_d3wait(apcm->codec); + err = hinfo->ops.open(hinfo, apcm->codec, substream); + if (err < 0) { + azx_release_device(azx_dev); + snd_hda_power_down(apcm->codec); + mutex_unlock(&chip->open_mutex); + return err; + } + snd_pcm_limit_hw_rates(runtime); + /* sanity check */ + if (snd_BUG_ON(!runtime->hw.channels_min) || + snd_BUG_ON(!runtime->hw.channels_max) || + snd_BUG_ON(!runtime->hw.formats) || + snd_BUG_ON(!runtime->hw.rates)) { + azx_release_device(azx_dev); + hinfo->ops.close(hinfo, apcm->codec, substream); + snd_hda_power_down(apcm->codec); + mutex_unlock(&chip->open_mutex); + return -EINVAL; + } + + /* disable WALLCLOCK timestamps for capture streams + until we figure out how to handle digital inputs */ + if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) + runtime->hw.info &= ~SNDRV_PCM_INFO_HAS_WALL_CLOCK; + + spin_lock_irqsave(&chip->reg_lock, flags); + azx_dev->substream = substream; + azx_dev->running = 0; + spin_unlock_irqrestore(&chip->reg_lock, flags); + + runtime->private_data = azx_dev; + snd_pcm_set_sync(substream); + mutex_unlock(&chip->open_mutex); + return 0; +} + +static int azx_pcm_mmap(struct snd_pcm_substream *substream, + struct vm_area_struct *area) +{ + struct azx_pcm *apcm = snd_pcm_substream_chip(substream); + struct azx *chip = apcm->chip; + if (chip->ops->pcm_mmap_prepare) + chip->ops->pcm_mmap_prepare(substream, area); + return snd_pcm_lib_default_mmap(substream, area); +} + +static struct snd_pcm_ops azx_pcm_ops = { + .open = azx_pcm_open, + .close = azx_pcm_close, + .ioctl = snd_pcm_lib_ioctl, + .hw_params = azx_pcm_hw_params, + .hw_free = azx_pcm_hw_free, + .prepare = azx_pcm_prepare, + .trigger = azx_pcm_trigger, + .pointer = azx_pcm_pointer, + .wall_clock = azx_get_wallclock_tstamp, + .mmap = azx_pcm_mmap, + .page = snd_pcm_sgbuf_ops_page, +}; + +static void azx_pcm_free(struct snd_pcm *pcm) +{ + struct azx_pcm *apcm = pcm->private_data; + if (apcm) { + list_del(&apcm->list); + kfree(apcm); + } +} + +#define MAX_PREALLOC_SIZE (32 * 1024 * 1024) + +static int azx_attach_pcm_stream(struct hda_bus *bus, struct hda_codec *codec, + struct hda_pcm *cpcm) +{ + struct azx *chip = bus->private_data; + struct snd_pcm *pcm; + struct azx_pcm *apcm; + int pcm_dev = cpcm->device; + unsigned int size; + int s, err; + + list_for_each_entry(apcm, &chip->pcm_list, list) { + if (apcm->pcm->device == pcm_dev) { + dev_err(chip->card->dev, "PCM %d already exists\n", + pcm_dev); + return -EBUSY; + } + } + err = snd_pcm_new(chip->card, cpcm->name, pcm_dev, + cpcm->stream[SNDRV_PCM_STREAM_PLAYBACK].substreams, + cpcm->stream[SNDRV_PCM_STREAM_CAPTURE].substreams, + &pcm); + if (err < 0) + return err; + strlcpy(pcm->name, cpcm->name, sizeof(pcm->name)); + apcm = kzalloc(sizeof(*apcm), GFP_KERNEL); + if (apcm == NULL) + return -ENOMEM; + apcm->chip = chip; + apcm->pcm = pcm; + apcm->codec = codec; + pcm->private_data = apcm; + pcm->private_free = azx_pcm_free; + if (cpcm->pcm_type == HDA_PCM_TYPE_MODEM) + pcm->dev_class = SNDRV_PCM_CLASS_MODEM; + list_add_tail(&apcm->list, &chip->pcm_list); + cpcm->pcm = pcm; + for (s = 0; s < 2; s++) { + apcm->hinfo[s] = &cpcm->stream[s]; + if (cpcm->stream[s].substreams) + snd_pcm_set_ops(pcm, s, &azx_pcm_ops); + } + /* buffer pre-allocation */ + size = CONFIG_SND_HDA_PREALLOC_SIZE * 1024; + if (size > MAX_PREALLOC_SIZE) + size = MAX_PREALLOC_SIZE; + snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV_SG, + chip->card->dev, + size, MAX_PREALLOC_SIZE); + /* link to codec */ + pcm->dev = &codec->dev; + return 0; +} + +/* + * CORB / RIRB interface + */ +static int azx_alloc_cmd_io(struct azx *chip) +{ + int err; + + /* single page (at least 4096 bytes) must suffice for both ringbuffes */ + err = chip->ops->dma_alloc_pages(chip, SNDRV_DMA_TYPE_DEV, + PAGE_SIZE, &chip->rb); + if (err < 0) + dev_err(chip->card->dev, "cannot allocate CORB/RIRB\n"); + return err; +} +EXPORT_SYMBOL_GPL(azx_alloc_cmd_io); + +static void azx_init_cmd_io(struct azx *chip) +{ + int timeout; + + spin_lock_irq(&chip->reg_lock); + /* CORB set up */ + chip->corb.addr = chip->rb.addr; + chip->corb.buf = (u32 *)chip->rb.area; + azx_writel(chip, CORBLBASE, (u32)chip->corb.addr); + azx_writel(chip, CORBUBASE, upper_32_bits(chip->corb.addr)); + + /* set the corb size to 256 entries (ULI requires explicitly) */ + azx_writeb(chip, CORBSIZE, 0x02); + /* set the corb write pointer to 0 */ + azx_writew(chip, CORBWP, 0); + + /* reset the corb hw read pointer */ + azx_writew(chip, CORBRP, ICH6_CORBRP_RST); + for (timeout = 1000; timeout > 0; timeout--) { + if ((azx_readw(chip, CORBRP) & ICH6_CORBRP_RST) == ICH6_CORBRP_RST) + break; + udelay(1); + } + if (timeout <= 0) + dev_err(chip->card->dev, "CORB reset timeout#1, CORBRP = %d\n", + azx_readw(chip, CORBRP)); + + azx_writew(chip, CORBRP, 0); + for (timeout = 1000; timeout > 0; timeout--) { + if (azx_readw(chip, CORBRP) == 0) + break; + udelay(1); + } + if (timeout <= 0) + dev_err(chip->card->dev, "CORB reset timeout#2, CORBRP = %d\n", + azx_readw(chip, CORBRP)); + + /* enable corb dma */ + azx_writeb(chip, CORBCTL, ICH6_CORBCTL_RUN); + + /* RIRB set up */ + chip->rirb.addr = chip->rb.addr + 2048; + chip->rirb.buf = (u32 *)(chip->rb.area + 2048); + chip->rirb.wp = chip->rirb.rp = 0; + memset(chip->rirb.cmds, 0, sizeof(chip->rirb.cmds)); + azx_writel(chip, RIRBLBASE, (u32)chip->rirb.addr); + azx_writel(chip, RIRBUBASE, upper_32_bits(chip->rirb.addr)); + + /* set the rirb size to 256 entries (ULI requires explicitly) */ + azx_writeb(chip, RIRBSIZE, 0x02); + /* reset the rirb hw write pointer */ + azx_writew(chip, RIRBWP, ICH6_RIRBWP_RST); + /* set N=1, get RIRB response interrupt for new entry */ + if (chip->driver_caps & AZX_DCAPS_CTX_WORKAROUND) + azx_writew(chip, RINTCNT, 0xc0); + else + azx_writew(chip, RINTCNT, 1); + /* enable rirb dma and response irq */ + azx_writeb(chip, RIRBCTL, ICH6_RBCTL_DMA_EN | ICH6_RBCTL_IRQ_EN); + spin_unlock_irq(&chip->reg_lock); +} +EXPORT_SYMBOL_GPL(azx_init_cmd_io); + +static void azx_free_cmd_io(struct azx *chip) +{ + spin_lock_irq(&chip->reg_lock); + /* disable ringbuffer DMAs */ + azx_writeb(chip, RIRBCTL, 0); + azx_writeb(chip, CORBCTL, 0); + spin_unlock_irq(&chip->reg_lock); +} +EXPORT_SYMBOL_GPL(azx_free_cmd_io); + +static unsigned int azx_command_addr(u32 cmd) +{ + unsigned int addr = cmd >> 28; + + if (addr >= AZX_MAX_CODECS) { + snd_BUG(); + addr = 0; + } + + return addr; +} + +/* send a command */ +static int azx_corb_send_cmd(struct hda_bus *bus, u32 val) +{ + struct azx *chip = bus->private_data; + unsigned int addr = azx_command_addr(val); + unsigned int wp, rp; + + spin_lock_irq(&chip->reg_lock); + + /* add command to corb */ + wp = azx_readw(chip, CORBWP); + if (wp == 0xffff) { + /* something wrong, controller likely turned to D3 */ + spin_unlock_irq(&chip->reg_lock); + return -EIO; + } + wp++; + wp %= ICH6_MAX_CORB_ENTRIES; + + rp = azx_readw(chip, CORBRP); + if (wp == rp) { + /* oops, it's full */ + spin_unlock_irq(&chip->reg_lock); + return -EAGAIN; + } + + chip->rirb.cmds[addr]++; + chip->corb.buf[wp] = cpu_to_le32(val); + azx_writew(chip, CORBWP, wp); + + spin_unlock_irq(&chip->reg_lock); + + return 0; +} + +#define ICH6_RIRB_EX_UNSOL_EV (1<<4) + +/* retrieve RIRB entry - called from interrupt handler */ +static void azx_update_rirb(struct azx *chip) +{ + unsigned int rp, wp; + unsigned int addr; + u32 res, res_ex; + + wp = azx_readw(chip, RIRBWP); + if (wp == 0xffff) { + /* something wrong, controller likely turned to D3 */ + return; + } + + if (wp == chip->rirb.wp) + return; + chip->rirb.wp = wp; + + while (chip->rirb.rp != wp) { + chip->rirb.rp++; + chip->rirb.rp %= ICH6_MAX_RIRB_ENTRIES; + + rp = chip->rirb.rp << 1; /* an RIRB entry is 8-bytes */ + res_ex = le32_to_cpu(chip->rirb.buf[rp + 1]); + res = le32_to_cpu(chip->rirb.buf[rp]); + addr = res_ex & 0xf; + if ((addr >= AZX_MAX_CODECS) || !(chip->codec_mask & (1 << addr))) { + dev_err(chip->card->dev, "spurious response %#x:%#x, rp = %d, wp = %d", + res, res_ex, + chip->rirb.rp, wp); + snd_BUG(); + } + else if (res_ex & ICH6_RIRB_EX_UNSOL_EV) + snd_hda_queue_unsol_event(chip->bus, res, res_ex); + else if (chip->rirb.cmds[addr]) { + chip->rirb.res[addr] = res; + smp_wmb(); + chip->rirb.cmds[addr]--; + } else if (printk_ratelimit()) { + dev_err(chip->card->dev, "spurious response %#x:%#x, last cmd=%#08x\n", + res, res_ex, + chip->last_cmd[addr]); + } + } +} + +/* receive a response */ +static unsigned int azx_rirb_get_response(struct hda_bus *bus, + unsigned int addr) +{ + struct azx *chip = bus->private_data; + unsigned long timeout; + unsigned long loopcounter; + int do_poll = 0; + + again: + timeout = jiffies + msecs_to_jiffies(1000); + + for (loopcounter = 0;; loopcounter++) { + if (chip->polling_mode || do_poll) { + spin_lock_irq(&chip->reg_lock); + azx_update_rirb(chip); + spin_unlock_irq(&chip->reg_lock); + } + if (!chip->rirb.cmds[addr]) { + smp_rmb(); + bus->rirb_error = 0; + + if (!do_poll) + chip->poll_count = 0; + return chip->rirb.res[addr]; /* the last value */ + } + if (time_after(jiffies, timeout)) + break; + if (bus->needs_damn_long_delay || loopcounter > 3000) + msleep(2); /* temporary workaround */ + else { + udelay(10); + cond_resched(); + } + } + + if (!bus->no_response_fallback) + return -1; + + if (!chip->polling_mode && chip->poll_count < 2) { + dev_dbg(chip->card->dev, + "azx_get_response timeout, polling the codec once: last cmd=0x%08x\n", + chip->last_cmd[addr]); + do_poll = 1; + chip->poll_count++; + goto again; + } + + + if (!chip->polling_mode) { + dev_warn(chip->card->dev, + "azx_get_response timeout, switching to polling mode: last cmd=0x%08x\n", + chip->last_cmd[addr]); + chip->polling_mode = 1; + goto again; + } + + if (chip->msi) { + dev_warn(chip->card->dev, + "No response from codec, disabling MSI: last cmd=0x%08x\n", + chip->last_cmd[addr]); + if (chip->ops->disable_msi_reset_irq(chip) && + chip->ops->disable_msi_reset_irq(chip) < 0) { + bus->rirb_error = 1; + return -1; + } + goto again; + } + + if (chip->probing) { + /* If this critical timeout happens during the codec probing + * phase, this is likely an access to a non-existing codec + * slot. Better to return an error and reset the system. + */ + return -1; + } + + /* a fatal communication error; need either to reset or to fallback + * to the single_cmd mode + */ + bus->rirb_error = 1; + if (bus->allow_bus_reset && !bus->response_reset && !bus->in_reset) { + bus->response_reset = 1; + return -1; /* give a chance to retry */ + } + + dev_err(chip->card->dev, + "azx_get_response timeout, switching to single_cmd mode: last cmd=0x%08x\n", + chip->last_cmd[addr]); + chip->single_cmd = 1; + bus->response_reset = 0; + /* release CORB/RIRB */ + azx_free_cmd_io(chip); + /* disable unsolicited responses */ + azx_writel(chip, GCTL, azx_readl(chip, GCTL) & ~ICH6_GCTL_UNSOL); + return -1; +} + +/* + * Use the single immediate command instead of CORB/RIRB for simplicity + * + * Note: according to Intel, this is not preferred use. The command was + * intended for the BIOS only, and may get confused with unsolicited + * responses. So, we shouldn't use it for normal operation from the + * driver. + * I left the codes, however, for debugging/testing purposes. + */ + +/* receive a response */ +static int azx_single_wait_for_response(struct azx *chip, unsigned int addr) +{ + int timeout = 50; + + while (timeout--) { + /* check IRV busy bit */ + if (azx_readw(chip, IRS) & ICH6_IRS_VALID) { + /* reuse rirb.res as the response return value */ + chip->rirb.res[addr] = azx_readl(chip, IR); + return 0; + } + udelay(1); + } + if (printk_ratelimit()) + dev_dbg(chip->card->dev, "get_response timeout: IRS=0x%x\n", + azx_readw(chip, IRS)); + chip->rirb.res[addr] = -1; + return -EIO; +} + +/* send a command */ +static int azx_single_send_cmd(struct hda_bus *bus, u32 val) +{ + struct azx *chip = bus->private_data; + unsigned int addr = azx_command_addr(val); + int timeout = 50; + + bus->rirb_error = 0; + while (timeout--) { + /* check ICB busy bit */ + if (!((azx_readw(chip, IRS) & ICH6_IRS_BUSY))) { + /* Clear IRV valid bit */ + azx_writew(chip, IRS, azx_readw(chip, IRS) | + ICH6_IRS_VALID); + azx_writel(chip, IC, val); + azx_writew(chip, IRS, azx_readw(chip, IRS) | + ICH6_IRS_BUSY); + return azx_single_wait_for_response(chip, addr); + } + udelay(1); + } + if (printk_ratelimit()) + dev_dbg(chip->card->dev, + "send_cmd timeout: IRS=0x%x, val=0x%x\n", + azx_readw(chip, IRS), val); + return -EIO; +} + +/* receive a response */ +static unsigned int azx_single_get_response(struct hda_bus *bus, + unsigned int addr) +{ + struct azx *chip = bus->private_data; + return chip->rirb.res[addr]; +} + +/* + * The below are the main callbacks from hda_codec. + * + * They are just the skeleton to call sub-callbacks according to the + * current setting of chip->single_cmd. + */ + +/* send a command */ +static int azx_send_cmd(struct hda_bus *bus, unsigned int val) +{ + struct azx *chip = bus->private_data; + + if (chip->disabled) + return 0; + chip->last_cmd[azx_command_addr(val)] = val; + if (chip->single_cmd) + return azx_single_send_cmd(bus, val); + else + return azx_corb_send_cmd(bus, val); +} +EXPORT_SYMBOL_GPL(azx_send_cmd); + +/* get a response */ +static unsigned int azx_get_response(struct hda_bus *bus, + unsigned int addr) +{ + struct azx *chip = bus->private_data; + if (chip->disabled) + return 0; + if (chip->single_cmd) + return azx_single_get_response(bus, addr); + else + return azx_rirb_get_response(bus, addr); +} +EXPORT_SYMBOL_GPL(azx_get_response); + +#ifdef CONFIG_SND_HDA_DSP_LOADER +/* + * DSP loading code (e.g. for CA0132) + */ + +/* use the first stream for loading DSP */ +static struct azx_dev * +azx_get_dsp_loader_dev(struct azx *chip) +{ + return &chip->azx_dev[chip->playback_index_offset]; +} + +static int azx_load_dsp_prepare(struct hda_bus *bus, unsigned int format, + unsigned int byte_size, + struct snd_dma_buffer *bufp) +{ + u32 *bdl; + struct azx *chip = bus->private_data; + struct azx_dev *azx_dev; + int err; + + azx_dev = azx_get_dsp_loader_dev(chip); + + dsp_lock(azx_dev); + spin_lock_irq(&chip->reg_lock); + if (azx_dev->running || azx_dev->locked) { + spin_unlock_irq(&chip->reg_lock); + err = -EBUSY; + goto unlock; + } + azx_dev->prepared = 0; + chip->saved_azx_dev = *azx_dev; + azx_dev->locked = 1; + spin_unlock_irq(&chip->reg_lock); + + err = chip->ops->dma_alloc_pages(chip, SNDRV_DMA_TYPE_DEV_SG, + byte_size, bufp); + if (err < 0) + goto err_alloc; + + azx_dev->bufsize = byte_size; + azx_dev->period_bytes = byte_size; + azx_dev->format_val = format; + + azx_stream_reset(chip, azx_dev); + + /* reset BDL address */ + azx_sd_writel(chip, azx_dev, SD_BDLPL, 0); + azx_sd_writel(chip, azx_dev, SD_BDLPU, 0); + + azx_dev->frags = 0; + bdl = (u32 *)azx_dev->bdl.area; + err = setup_bdle(chip, bufp, azx_dev, &bdl, 0, byte_size, 0); + if (err < 0) + goto error; + + azx_setup_controller(chip, azx_dev); + dsp_unlock(azx_dev); + return azx_dev->stream_tag; + + error: + chip->ops->dma_free_pages(chip, bufp); + err_alloc: + spin_lock_irq(&chip->reg_lock); + if (azx_dev->opened) + *azx_dev = chip->saved_azx_dev; + azx_dev->locked = 0; + spin_unlock_irq(&chip->reg_lock); + unlock: + dsp_unlock(azx_dev); + return err; +} + +static void azx_load_dsp_trigger(struct hda_bus *bus, bool start) +{ + struct azx *chip = bus->private_data; + struct azx_dev *azx_dev = azx_get_dsp_loader_dev(chip); + + if (start) + azx_stream_start(chip, azx_dev); + else + azx_stream_stop(chip, azx_dev); + azx_dev->running = start; +} + +static void azx_load_dsp_cleanup(struct hda_bus *bus, + struct snd_dma_buffer *dmab) +{ + struct azx *chip = bus->private_data; + struct azx_dev *azx_dev = azx_get_dsp_loader_dev(chip); + + if (!dmab->area || !azx_dev->locked) + return; + + dsp_lock(azx_dev); + /* reset BDL address */ + azx_sd_writel(chip, azx_dev, SD_BDLPL, 0); + azx_sd_writel(chip, azx_dev, SD_BDLPU, 0); + azx_sd_writel(chip, azx_dev, SD_CTL, 0); + azx_dev->bufsize = 0; + azx_dev->period_bytes = 0; + azx_dev->format_val = 0; + + chip->ops->dma_free_pages(chip, dmab); + dmab->area = NULL; + + spin_lock_irq(&chip->reg_lock); + if (azx_dev->opened) + *azx_dev = chip->saved_azx_dev; + azx_dev->locked = 0; + spin_unlock_irq(&chip->reg_lock); + dsp_unlock(azx_dev); +} +#endif /* CONFIG_SND_HDA_DSP_LOADER */ + +int azx_alloc_stream_pages(struct azx *chip) +{ + int i, err; + struct snd_card *card = chip->card; + + for (i = 0; i < chip->num_streams; i++) { + dsp_lock_init(&chip->azx_dev[i]); + /* allocate memory for the BDL for each stream */ + err = chip->ops->dma_alloc_pages(chip, SNDRV_DMA_TYPE_DEV, + BDL_SIZE, + &chip->azx_dev[i].bdl); + if (err < 0) { + dev_err(card->dev, "cannot allocate BDL\n"); + return -ENOMEM; + } + } + /* allocate memory for the position buffer */ + err = chip->ops->dma_alloc_pages(chip, SNDRV_DMA_TYPE_DEV, + chip->num_streams * 8, &chip->posbuf); + if (err < 0) { + dev_err(card->dev, "cannot allocate posbuf\n"); + return -ENOMEM; + } + + /* allocate CORB/RIRB */ + err = azx_alloc_cmd_io(chip); + if (err < 0) + return err; + return 0; +} +EXPORT_SYMBOL_GPL(azx_alloc_stream_pages); + +void azx_free_stream_pages(struct azx *chip) +{ + int i; + if (chip->azx_dev) { + for (i = 0; i < chip->num_streams; i++) + if (chip->azx_dev[i].bdl.area) + chip->ops->dma_free_pages( + chip, &chip->azx_dev[i].bdl); + } + if (chip->rb.area) + chip->ops->dma_free_pages(chip, &chip->rb); + if (chip->posbuf.area) + chip->ops->dma_free_pages(chip, &chip->posbuf); +} +EXPORT_SYMBOL_GPL(azx_free_stream_pages); + +/* + * Lowlevel interface + */ + +/* enter link reset */ +void azx_enter_link_reset(struct azx *chip) +{ + unsigned long timeout; + + /* reset controller */ + azx_writel(chip, GCTL, azx_readl(chip, GCTL) & ~ICH6_GCTL_RESET); + + timeout = jiffies + msecs_to_jiffies(100); + while ((azx_readb(chip, GCTL) & ICH6_GCTL_RESET) && + time_before(jiffies, timeout)) + usleep_range(500, 1000); +} +EXPORT_SYMBOL_GPL(azx_enter_link_reset); + +/* exit link reset */ +static void azx_exit_link_reset(struct azx *chip) +{ + unsigned long timeout; + + azx_writeb(chip, GCTL, azx_readb(chip, GCTL) | ICH6_GCTL_RESET); + + timeout = jiffies + msecs_to_jiffies(100); + while (!azx_readb(chip, GCTL) && + time_before(jiffies, timeout)) + usleep_range(500, 1000); +} + +/* reset codec link */ +static int azx_reset(struct azx *chip, int full_reset) +{ + if (!full_reset) + goto __skip; + + /* clear STATESTS */ + azx_writew(chip, STATESTS, STATESTS_INT_MASK); + + /* reset controller */ + azx_enter_link_reset(chip); + + /* delay for >= 100us for codec PLL to settle per spec + * Rev 0.9 section 5.5.1 + */ + usleep_range(500, 1000); + + /* Bring controller out of reset */ + azx_exit_link_reset(chip); + + /* Brent Chartrand said to wait >= 540us for codecs to initialize */ + usleep_range(1000, 1200); + + __skip: + /* check to see if controller is ready */ + if (!azx_readb(chip, GCTL)) { + dev_dbg(chip->card->dev, "azx_reset: controller not ready!\n"); + return -EBUSY; + } + + /* Accept unsolicited responses */ + if (!chip->single_cmd) + azx_writel(chip, GCTL, azx_readl(chip, GCTL) | + ICH6_GCTL_UNSOL); + + /* detect codecs */ + if (!chip->codec_mask) { + chip->codec_mask = azx_readw(chip, STATESTS); + dev_dbg(chip->card->dev, "codec_mask = 0x%x\n", + chip->codec_mask); + } + + return 0; +} + +/* enable interrupts */ +static void azx_int_enable(struct azx *chip) +{ + /* enable controller CIE and GIE */ + azx_writel(chip, INTCTL, azx_readl(chip, INTCTL) | + ICH6_INT_CTRL_EN | ICH6_INT_GLOBAL_EN); +} + +/* disable interrupts */ +static void azx_int_disable(struct azx *chip) +{ + int i; + + /* disable interrupts in stream descriptor */ + for (i = 0; i < chip->num_streams; i++) { + struct azx_dev *azx_dev = &chip->azx_dev[i]; + azx_sd_writeb(chip, azx_dev, SD_CTL, + azx_sd_readb(chip, azx_dev, SD_CTL) & + ~SD_INT_MASK); + } + + /* disable SIE for all streams */ + azx_writeb(chip, INTCTL, 0); + + /* disable controller CIE and GIE */ + azx_writel(chip, INTCTL, azx_readl(chip, INTCTL) & + ~(ICH6_INT_CTRL_EN | ICH6_INT_GLOBAL_EN)); +} + +/* clear interrupts */ +static void azx_int_clear(struct azx *chip) +{ + int i; + + /* clear stream status */ + for (i = 0; i < chip->num_streams; i++) { + struct azx_dev *azx_dev = &chip->azx_dev[i]; + azx_sd_writeb(chip, azx_dev, SD_STS, SD_INT_MASK); + } + + /* clear STATESTS */ + azx_writew(chip, STATESTS, STATESTS_INT_MASK); + + /* clear rirb status */ + azx_writeb(chip, RIRBSTS, RIRB_INT_MASK); + + /* clear int status */ + azx_writel(chip, INTSTS, ICH6_INT_CTRL_EN | ICH6_INT_ALL_STREAM); +} + +/* + * reset and start the controller registers + */ +void azx_init_chip(struct azx *chip, int full_reset) +{ + if (chip->initialized) + return; + + /* reset controller */ + azx_reset(chip, full_reset); + + /* initialize interrupts */ + azx_int_clear(chip); + azx_int_enable(chip); + + /* initialize the codec command I/O */ + if (!chip->single_cmd) + azx_init_cmd_io(chip); + + /* program the position buffer */ + azx_writel(chip, DPLBASE, (u32)chip->posbuf.addr); + azx_writel(chip, DPUBASE, upper_32_bits(chip->posbuf.addr)); + + chip->initialized = 1; +} +EXPORT_SYMBOL_GPL(azx_init_chip); + +void azx_stop_chip(struct azx *chip) +{ + if (!chip->initialized) + return; + + /* disable interrupts */ + azx_int_disable(chip); + azx_int_clear(chip); + + /* disable CORB/RIRB */ + azx_free_cmd_io(chip); + + /* disable position buffer */ + azx_writel(chip, DPLBASE, 0); + azx_writel(chip, DPUBASE, 0); + + chip->initialized = 0; +} +EXPORT_SYMBOL_GPL(azx_stop_chip); + +/* + * interrupt handler + */ +irqreturn_t azx_interrupt(int irq, void *dev_id) +{ + struct azx *chip = dev_id; + struct azx_dev *azx_dev; + u32 status; + u8 sd_status; + int i; + +#ifdef CONFIG_PM_RUNTIME + if (chip->driver_caps & AZX_DCAPS_PM_RUNTIME) + if (chip->card->dev->power.runtime_status != RPM_ACTIVE) + return IRQ_NONE; +#endif + + spin_lock(&chip->reg_lock); + + if (chip->disabled) { + spin_unlock(&chip->reg_lock); + return IRQ_NONE; + } + + status = azx_readl(chip, INTSTS); + if (status == 0 || status == 0xffffffff) { + spin_unlock(&chip->reg_lock); + return IRQ_NONE; + } + + for (i = 0; i < chip->num_streams; i++) { + azx_dev = &chip->azx_dev[i]; + if (status & azx_dev->sd_int_sta_mask) { + sd_status = azx_sd_readb(chip, azx_dev, SD_STS); + azx_sd_writeb(chip, azx_dev, SD_STS, SD_INT_MASK); + if (!azx_dev->substream || !azx_dev->running || + !(sd_status & SD_INT_COMPLETE)) + continue; + /* check whether this IRQ is really acceptable */ + if (!chip->ops->position_check || + chip->ops->position_check(chip, azx_dev)) { + spin_unlock(&chip->reg_lock); + snd_pcm_period_elapsed(azx_dev->substream); + spin_lock(&chip->reg_lock); + } + } + } + + /* clear rirb int */ + status = azx_readb(chip, RIRBSTS); + if (status & RIRB_INT_MASK) { + if (status & RIRB_INT_RESPONSE) { + if (chip->driver_caps & AZX_DCAPS_RIRB_PRE_DELAY) + udelay(80); + azx_update_rirb(chip); + } + azx_writeb(chip, RIRBSTS, RIRB_INT_MASK); + } + + spin_unlock(&chip->reg_lock); + + return IRQ_HANDLED; +} +EXPORT_SYMBOL_GPL(azx_interrupt); + +/* + * Codec initerface + */ + +/* + * Probe the given codec address + */ +static int probe_codec(struct azx *chip, int addr) +{ + unsigned int cmd = (addr << 28) | (AC_NODE_ROOT << 20) | + (AC_VERB_PARAMETERS << 8) | AC_PAR_VENDOR_ID; + unsigned int res; + + mutex_lock(&chip->bus->cmd_mutex); + chip->probing = 1; + azx_send_cmd(chip->bus, cmd); + res = azx_get_response(chip->bus, addr); + chip->probing = 0; + mutex_unlock(&chip->bus->cmd_mutex); + if (res == -1) + return -EIO; + dev_dbg(chip->card->dev, "codec #%d probed OK\n", addr); + return 0; +} + +static void azx_bus_reset(struct hda_bus *bus) +{ + struct azx *chip = bus->private_data; + + bus->in_reset = 1; + azx_stop_chip(chip); + azx_init_chip(chip, 1); +#ifdef CONFIG_PM + if (chip->initialized) { + struct azx_pcm *p; + list_for_each_entry(p, &chip->pcm_list, list) + snd_pcm_suspend_all(p->pcm); + snd_hda_suspend(chip->bus); + snd_hda_resume(chip->bus); + } +#endif + bus->in_reset = 0; +} + +#ifdef CONFIG_PM +/* power-up/down the controller */ +static void azx_power_notify(struct hda_bus *bus, bool power_up) +{ + struct azx *chip = bus->private_data; + + if (!(chip->driver_caps & AZX_DCAPS_PM_RUNTIME)) + return; + + if (power_up) + pm_runtime_get_sync(chip->card->dev); + else + pm_runtime_put_sync(chip->card->dev); +} +#endif + +static int get_jackpoll_interval(struct azx *chip) +{ + int i; + unsigned int j; + + if (!chip->jackpoll_ms) + return 0; + + i = chip->jackpoll_ms[chip->dev_index]; + if (i == 0) + return 0; + if (i < 50 || i > 60000) + j = 0; + else + j = msecs_to_jiffies(i); + if (j == 0) + dev_warn(chip->card->dev, + "jackpoll_ms value out of range: %d\n", i); + return j; +} + +/* Codec initialization */ +int azx_codec_create(struct azx *chip, const char *model, + unsigned int max_slots, + int *power_save_to) +{ + struct hda_bus_template bus_temp; + int c, codecs, err; + + memset(&bus_temp, 0, sizeof(bus_temp)); + bus_temp.private_data = chip; + bus_temp.modelname = model; + bus_temp.pci = chip->pci; + bus_temp.ops.command = azx_send_cmd; + bus_temp.ops.get_response = azx_get_response; + bus_temp.ops.attach_pcm = azx_attach_pcm_stream; + bus_temp.ops.bus_reset = azx_bus_reset; +#ifdef CONFIG_PM + bus_temp.power_save = power_save_to; + bus_temp.ops.pm_notify = azx_power_notify; +#endif +#ifdef CONFIG_SND_HDA_DSP_LOADER + bus_temp.ops.load_dsp_prepare = azx_load_dsp_prepare; + bus_temp.ops.load_dsp_trigger = azx_load_dsp_trigger; + bus_temp.ops.load_dsp_cleanup = azx_load_dsp_cleanup; +#endif + + err = snd_hda_bus_new(chip->card, &bus_temp, &chip->bus); + if (err < 0) + return err; + + if (chip->driver_caps & AZX_DCAPS_RIRB_DELAY) { + dev_dbg(chip->card->dev, "Enable delay in RIRB handling\n"); + chip->bus->needs_damn_long_delay = 1; + } + + codecs = 0; + if (!max_slots) + max_slots = AZX_DEFAULT_CODECS; + + /* First try to probe all given codec slots */ + for (c = 0; c < max_slots; c++) { + if ((chip->codec_mask & (1 << c)) & chip->codec_probe_mask) { + if (probe_codec(chip, c) < 0) { + /* Some BIOSen give you wrong codec addresses + * that don't exist + */ + dev_warn(chip->card->dev, + "Codec #%d probe error; disabling it...\n", c); + chip->codec_mask &= ~(1 << c); + /* More badly, accessing to a non-existing + * codec often screws up the controller chip, + * and disturbs the further communications. + * Thus if an error occurs during probing, + * better to reset the controller chip to + * get back to the sanity state. + */ + azx_stop_chip(chip); + azx_init_chip(chip, 1); + } + } + } + + /* AMD chipsets often cause the communication stalls upon certain + * sequence like the pin-detection. It seems that forcing the synced + * access works around the stall. Grrr... + */ + if (chip->driver_caps & AZX_DCAPS_SYNC_WRITE) { + dev_dbg(chip->card->dev, "Enable sync_write for stable communication\n"); + chip->bus->sync_write = 1; + chip->bus->allow_bus_reset = 1; + } + + /* Then create codec instances */ + for (c = 0; c < max_slots; c++) { + if ((chip->codec_mask & (1 << c)) & chip->codec_probe_mask) { + struct hda_codec *codec; + err = snd_hda_codec_new(chip->bus, c, &codec); + if (err < 0) + continue; + codec->jackpoll_interval = get_jackpoll_interval(chip); + codec->beep_mode = chip->beep_mode; + codecs++; + } + } + if (!codecs) { + dev_err(chip->card->dev, "no codecs initialized\n"); + return -ENXIO; + } + return 0; +} +EXPORT_SYMBOL_GPL(azx_codec_create); + +/* configure each codec instance */ +int azx_codec_configure(struct azx *chip) +{ + struct hda_codec *codec; + list_for_each_entry(codec, &chip->bus->codec_list, list) { + snd_hda_codec_configure(codec); + } + return 0; +} +EXPORT_SYMBOL_GPL(azx_codec_configure); + +/* mixer creation - all stuff is implemented in hda module */ +int azx_mixer_create(struct azx *chip) +{ + return snd_hda_build_controls(chip->bus); +} +EXPORT_SYMBOL_GPL(azx_mixer_create); + + +/* initialize SD streams */ +int azx_init_stream(struct azx *chip) +{ + int i; + + /* initialize each stream (aka device) + * assign the starting bdl address to each stream (device) + * and initialize + */ + for (i = 0; i < chip->num_streams; i++) { + struct azx_dev *azx_dev = &chip->azx_dev[i]; + azx_dev->posbuf = (u32 __iomem *)(chip->posbuf.area + i * 8); + /* offset: SDI0=0x80, SDI1=0xa0, ... SDO3=0x160 */ + azx_dev->sd_addr = chip->remap_addr + (0x20 * i + 0x80); + /* int mask: SDI0=0x01, SDI1=0x02, ... SDO3=0x80 */ + azx_dev->sd_int_sta_mask = 1 << i; + /* stream tag: must be non-zero and unique */ + azx_dev->index = i; + azx_dev->stream_tag = i + 1; + } + + return 0; +} +EXPORT_SYMBOL_GPL(azx_init_stream); + +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("Common HDA driver funcitons"); diff --git a/sound/pci/hda/hda_controller.h b/sound/pci/hda/hda_controller.h new file mode 100644 index 00000000000..1d2e3be2bae --- /dev/null +++ b/sound/pci/hda/hda_controller.h @@ -0,0 +1,53 @@ +/* + * Common functionality for the alsa driver code base for HD Audio. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the Free + * Software Foundation; either version 2 of the License, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + */ + +#ifndef __SOUND_HDA_CONTROLLER_H +#define __SOUND_HDA_CONTROLLER_H + +#include <sound/core.h> +#include <sound/initval.h> +#include "hda_codec.h" +#include "hda_priv.h" + +/* PCM setup */ +static inline struct azx_dev *get_azx_dev(struct snd_pcm_substream *substream) +{ + return substream->runtime->private_data; +} +unsigned int azx_get_position(struct azx *chip, + struct azx_dev *azx_dev, + bool with_check); + +/* Stream control. */ +void azx_stream_stop(struct azx *chip, struct azx_dev *azx_dev); + +/* Allocation functions. */ +int azx_alloc_stream_pages(struct azx *chip); +void azx_free_stream_pages(struct azx *chip); + +/* Low level azx interface */ +void azx_init_chip(struct azx *chip, int full_reset); +void azx_stop_chip(struct azx *chip); +void azx_enter_link_reset(struct azx *chip); +irqreturn_t azx_interrupt(int irq, void *dev_id); + +/* Codec interface */ +int azx_codec_create(struct azx *chip, const char *model, + unsigned int max_slots, + int *power_save_to); +int azx_codec_configure(struct azx *chip); +int azx_mixer_create(struct azx *chip); +int azx_init_stream(struct azx *chip); + +#endif /* __SOUND_HDA_CONTROLLER_H */ diff --git a/sound/pci/hda/hda_eld.c b/sound/pci/hda/hda_eld.c index 79ca80f6c77..46690a7f48f 100644 --- a/sound/pci/hda/hda_eld.c +++ b/sound/pci/hda/hda_eld.c @@ -153,7 +153,7 @@ static unsigned int hdmi_get_eld_data(struct hda_codec *codec, hda_nid_t nid, val = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_HDMI_ELDD, byte_index); #ifdef BE_PARANOID - printk(KERN_INFO "HDMI: ELD data byte %d: 0x%x\n", byte_index, val); + codec_info(codec, "HDMI: ELD data byte %d: 0x%x\n", byte_index, val); #endif return val; } @@ -332,11 +332,11 @@ int snd_hdmi_get_eld(struct hda_codec *codec, hda_nid_t nid, size = snd_hdmi_get_eld_size(codec, nid); if (size == 0) { /* wfg: workaround for ASUS P5E-VM HDMI board */ - snd_printd(KERN_INFO "HDMI: ELD buf size is 0, force 128\n"); + codec_info(codec, "HDMI: ELD buf size is 0, force 128\n"); size = 128; } if (size < ELD_FIXED_BYTES || size > ELD_MAX_SIZE) { - snd_printd(KERN_INFO "HDMI: invalid ELD buf size %d\n", size); + codec_info(codec, "HDMI: invalid ELD buf size %d\n", size); return -ERANGE; } @@ -348,8 +348,7 @@ int snd_hdmi_get_eld(struct hda_codec *codec, hda_nid_t nid, * Just abort. The caller will repoll after a while. */ if (!(val & AC_ELDD_ELD_VALID)) { - snd_printd(KERN_INFO - "HDMI: invalid ELD data byte %d\n", i); + codec_info(codec, "HDMI: invalid ELD data byte %d\n", i); ret = -EINVAL; goto error; } @@ -361,7 +360,7 @@ int snd_hdmi_get_eld(struct hda_codec *codec, hda_nid_t nid, * correctly writes ELD content before setting ELD_valid bit. */ if (!val && !i) { - snd_printdd(KERN_INFO "HDMI: 0 ELD data\n"); + codec_dbg(codec, "HDMI: 0 ELD data\n"); ret = -EINVAL; goto error; } @@ -681,7 +680,7 @@ int snd_hdmi_get_eld_ati(struct hda_codec *codec, hda_nid_t nid, spkalloc = snd_hda_codec_read(codec, nid, 0, ATI_VERB_GET_SPEAKER_ALLOCATION, 0); if (spkalloc <= 0) { - snd_printd(KERN_INFO "HDMI ATI/AMD: no speaker allocation for ELD\n"); + codec_info(codec, "HDMI ATI/AMD: no speaker allocation for ELD\n"); return -EINVAL; } @@ -722,7 +721,7 @@ int snd_hdmi_get_eld_ati(struct hda_codec *codec, hda_nid_t nid, sink_desc_len = snd_hda_codec_read(codec, nid, 0, ATI_VERB_GET_SINK_INFO_DATA, 0); if (sink_desc_len > ELD_MAX_MNL) { - snd_printd(KERN_INFO "HDMI ATI/AMD: Truncating HDMI sink description with length %d\n", + codec_info(codec, "HDMI ATI/AMD: Truncating HDMI sink description with length %d\n", sink_desc_len); sink_desc_len = ELD_MAX_MNL; } @@ -764,7 +763,7 @@ int snd_hdmi_get_eld_ati(struct hda_codec *codec, hda_nid_t nid, } if (pos == ELD_FIXED_BYTES + sink_desc_len) { - snd_printd(KERN_INFO "HDMI ATI/AMD: no audio descriptors for ELD\n"); + codec_info(codec, "HDMI ATI/AMD: no audio descriptors for ELD\n"); return -EINVAL; } diff --git a/sound/pci/hda/hda_generic.c b/sound/pci/hda/hda_generic.c index d9a09bdd09d..16133881e96 100644 --- a/sound/pci/hda/hda_generic.c +++ b/sound/pci/hda/hda_generic.c @@ -79,7 +79,7 @@ static void free_kctls(struct hda_gen_spec *spec) snd_array_free(&spec->kctls); } -void snd_hda_gen_spec_free(struct hda_gen_spec *spec) +static void snd_hda_gen_spec_free(struct hda_gen_spec *spec) { if (!spec) return; @@ -87,7 +87,6 @@ void snd_hda_gen_spec_free(struct hda_gen_spec *spec) snd_array_free(&spec->paths); snd_array_free(&spec->loopback_list); } -EXPORT_SYMBOL_GPL(snd_hda_gen_spec_free); /* * store user hints @@ -347,7 +346,8 @@ static bool is_ctl_associated(struct hda_codec *codec, hda_nid_t nid, return is_ctl_used(codec, val, type); } -static void print_nid_path(const char *pfx, struct nid_path *path) +static void print_nid_path(struct hda_codec *codec, + const char *pfx, struct nid_path *path) { char buf[40]; int i; @@ -359,7 +359,7 @@ static void print_nid_path(const char *pfx, struct nid_path *path) sprintf(tmp, ":%02x", path->path[i]); strlcat(buf, tmp, sizeof(buf)); } - snd_printdd("%s path: depth=%d %s\n", pfx, path->depth, buf); + codec_dbg(codec, "%s path: depth=%d %s\n", pfx, path->depth, buf); } /* called recursively */ @@ -762,7 +762,7 @@ void snd_hda_activate_path(struct hda_codec *codec, struct nid_path *path, AC_PWRST_D0); } if (enable && path->multi[i]) - snd_hda_codec_write_cache(codec, nid, 0, + snd_hda_codec_update_cache(codec, nid, 0, AC_VERB_SET_CONNECT_SEL, path->idx[i]); if (has_amp_in(codec, path, i)) @@ -1261,7 +1261,7 @@ static int try_assign_dacs(struct hda_codec *codec, int num_outs, dac = dacs[i] = 0; badness += bad->no_dac; } else { - /* print_nid_path("output", path); */ + /* print_nid_path(codec, "output", path); */ path->active = true; path_idx[i] = snd_hda_get_path_idx(codec, path); badness += assign_out_path_ctls(codec, path); @@ -1388,7 +1388,7 @@ static int fill_multi_ios(struct hda_codec *codec, badness++; continue; } - /* print_nid_path("multiio", path); */ + /* print_nid_path(codec, "multiio", path); */ spec->multi_io[spec->multi_ios].pin = nid; spec->multi_io[spec->multi_ios].dac = dac; spec->out_paths[cfg->line_outs + spec->multi_ios] = @@ -1445,7 +1445,7 @@ static bool map_singles(struct hda_codec *codec, int outs, if (path) { dacs[i] = dac; found = true; - /* print_nid_path("output", path); */ + /* print_nid_path(codec, "output", path); */ path->active = true; path_idx[i] = snd_hda_get_path_idx(codec, path); } @@ -1483,7 +1483,7 @@ static int check_aamix_out_path(struct hda_codec *codec, int path_idx) } if (!path) return 0; - /* print_nid_path("output-aamix", path); */ + /* print_nid_path(codec, "output-aamix", path); */ path->active = false; /* unused as default */ return snd_hda_get_path_idx(codec, path); } @@ -1700,7 +1700,7 @@ static int fill_and_eval_dacs(struct hda_codec *codec, #define DEBUG_BADNESS #ifdef DEBUG_BADNESS -#define debug_badness snd_printdd +#define debug_badness(fmt, args...) codec_dbg(codec, fmt, ##args) #else #define debug_badness(...) #endif @@ -1713,7 +1713,7 @@ static inline void print_nid_path_idx(struct hda_codec *codec, path = snd_hda_get_path_from_idx(codec, idx); if (path) - print_nid_path(pfx, path); + print_nid_path(codec, pfx, path); } static void debug_show_configs(struct hda_codec *codec, @@ -1781,7 +1781,7 @@ static void fill_all_dac_nids(struct hda_codec *codec) if (get_wcaps_type(get_wcaps(codec, nid)) != AC_WID_AUD_OUT) continue; if (spec->num_all_dacs >= ARRAY_SIZE(spec->all_dacs)) { - snd_printk(KERN_ERR "hda: Too many DACs!\n"); + codec_err(codec, "Too many DACs!\n"); break; } spec->all_dacs[spec->num_all_dacs++] = nid; @@ -2430,7 +2430,7 @@ static int create_hp_mic(struct hda_codec *codec) spec->hp_mic_pin = nid; /* we can't handle auto-mic together with HP-mic */ spec->suppress_auto_mic = 1; - snd_printdd("hda-codec: Enable shared I/O jack on NID 0x%x\n", nid); + codec_dbg(codec, "Enable shared I/O jack on NID 0x%x\n", nid); return 0; } @@ -2884,7 +2884,7 @@ static int new_analog_input(struct hda_codec *codec, int input_idx, path = snd_hda_add_new_path(codec, pin, mix_nid, 0); if (!path) return -EINVAL; - print_nid_path("loopback", path); + print_nid_path(codec, "loopback", path); spec->loopback_paths[input_idx] = snd_hda_get_path_idx(codec, path); idx = path->idx[path->depth - 1]; @@ -2912,7 +2912,7 @@ static int new_analog_input(struct hda_codec *codec, int input_idx, path = snd_hda_add_new_path(codec, spec->mixer_nid, spec->mixer_merge_nid, 0); if (path) { - print_nid_path("loopback-merge", path); + print_nid_path(codec, "loopback-merge", path); path->active = true; spec->loopback_merge_path = snd_hda_get_path_idx(codec, path); @@ -2991,7 +2991,7 @@ static int check_dyn_adc_switch(struct hda_codec *codec) } } - snd_printdd("hda-codec: enabling ADC switching\n"); + codec_dbg(codec, "enabling ADC switching\n"); spec->dyn_adc_switch = 1; } else if (nums != spec->num_adc_nids) { /* shrink the invalid adcs and input paths */ @@ -3015,7 +3015,7 @@ static int check_dyn_adc_switch(struct hda_codec *codec) if (imux->num_items == 1 || (imux->num_items == 2 && spec->hp_mic)) { - snd_printdd("hda-codec: reducing to a single ADC\n"); + codec_dbg(codec, "reducing to a single ADC\n"); spec->num_adc_nids = 1; /* reduce to a single ADC */ } @@ -3046,7 +3046,7 @@ static int parse_capture_source(struct hda_codec *codec, hda_nid_t pin, path = snd_hda_add_new_path(codec, pin, adc, anchor); if (!path) continue; - print_nid_path("input", path); + print_nid_path(codec, "input", path); spec->input_paths[imux_idx][c] = snd_hda_get_path_idx(codec, path); @@ -3712,7 +3712,7 @@ static void parse_digital(struct hda_codec *codec) path = snd_hda_add_new_path(codec, dig_nid, pin, 0); if (!path) continue; - print_nid_path("digout", path); + print_nid_path(codec, "digout", path); path->active = true; spec->digout_paths[i] = snd_hda_get_path_idx(codec, path); set_pin_target(codec, pin, PIN_OUT, false); @@ -3739,7 +3739,7 @@ static void parse_digital(struct hda_codec *codec) continue; path = snd_hda_add_new_path(codec, pin, dig_nid, 0); if (path) { - print_nid_path("digin", path); + print_nid_path(codec, "digin", path); path->active = true; spec->dig_in_nid = dig_nid; spec->digin_path = snd_hda_get_path_idx(codec, path); @@ -4170,8 +4170,7 @@ static int check_auto_mute_availability(struct hda_codec *codec) hda_nid_t nid = cfg->hp_pins[i]; if (!is_jack_detectable(codec, nid)) continue; - snd_printdd("hda-codec: Enable HP auto-muting on NID 0x%x\n", - nid); + 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, call_hp_automute); spec->detect_hp = 1; @@ -4183,7 +4182,7 @@ static int check_auto_mute_availability(struct hda_codec *codec) hda_nid_t nid = cfg->line_out_pins[i]; if (!is_jack_detectable(codec, nid)) continue; - snd_printdd("hda-codec: Enable Line-Out auto-muting on NID 0x%x\n", nid); + 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); @@ -4303,7 +4302,7 @@ static int check_auto_mic_availability(struct hda_codec *codec) spec->auto_mic = 1; spec->num_adc_nids = 1; spec->cur_mux[0] = spec->am_entry[0].idx; - snd_printdd("hda-codec: Enable auto-mic switch on NID 0x%x/0x%x/0x%x\n", + codec_dbg(codec, "Enable auto-mic switch on NID 0x%x/0x%x/0x%x\n", spec->am_entry[0].pin, spec->am_entry[1].pin, spec->am_entry[2].pin); @@ -5350,7 +5349,7 @@ EXPORT_SYMBOL_GPL(snd_hda_gen_init); */ void snd_hda_gen_free(struct hda_codec *codec) { - snd_hda_detach_beep_device(codec); + snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_FREE); snd_hda_gen_spec_free(codec->spec); kfree(codec->spec); codec->spec = NULL; diff --git a/sound/pci/hda/hda_generic.h b/sound/pci/hda/hda_generic.h index c908afbe4d9..bb2dea74398 100644 --- a/sound/pci/hda/hda_generic.h +++ b/sound/pci/hda/hda_generic.h @@ -297,7 +297,6 @@ struct hda_gen_spec { }; int snd_hda_gen_spec_init(struct hda_gen_spec *spec); -void snd_hda_gen_spec_free(struct hda_gen_spec *spec); int snd_hda_gen_init(struct hda_codec *codec); void snd_hda_gen_free(struct hda_codec *codec); diff --git a/sound/pci/hda/hda_hwdep.c b/sound/pci/hda/hda_hwdep.c index 72d8389fb39..014a7849e8f 100644 --- a/sound/pci/hda/hda_hwdep.c +++ b/sound/pci/hda/hda_hwdep.c @@ -20,24 +20,13 @@ #include <linux/init.h> #include <linux/slab.h> -#include <linux/pci.h> #include <linux/compat.h> -#include <linux/mutex.h> -#include <linux/ctype.h> -#include <linux/string.h> -#include <linux/export.h> #include <sound/core.h> #include "hda_codec.h" #include "hda_local.h" #include <sound/hda_hwdep.h> #include <sound/minors.h> -/* hint string pair */ -struct hda_hint { - const char *key; - const char *val; /* contained in the same alloc as key */ -}; - /* * write/read an out-of-bound verb */ @@ -105,26 +94,6 @@ static int hda_hwdep_open(struct snd_hwdep *hw, struct file *file) return 0; } -static void clear_hwdep_elements(struct hda_codec *codec) -{ - int i; - - /* clear init verbs */ - snd_array_free(&codec->init_verbs); - /* clear hints */ - for (i = 0; i < codec->hints.used; i++) { - struct hda_hint *hint = snd_array_elem(&codec->hints, i); - kfree(hint->key); /* we don't need to free hint->val */ - } - snd_array_free(&codec->hints); - snd_array_free(&codec->user_pins); -} - -static void hwdep_free(struct snd_hwdep *hwdep) -{ - clear_hwdep_elements(hwdep->private_data); -} - int snd_hda_create_hwdep(struct hda_codec *codec) { char hwname[16]; @@ -139,8 +108,8 @@ int snd_hda_create_hwdep(struct hda_codec *codec) sprintf(hwdep->name, "HDA Codec %d", codec->addr); hwdep->iface = SNDRV_HWDEP_IFACE_HDA; hwdep->private_data = codec; - hwdep->private_free = hwdep_free; hwdep->exclusive = 1; + hwdep->groups = snd_hda_dev_attr_groups; hwdep->ops.open = hda_hwdep_open; hwdep->ops.ioctl = hda_hwdep_ioctl; @@ -148,740 +117,8 @@ int snd_hda_create_hwdep(struct hda_codec *codec) hwdep->ops.ioctl_compat = hda_hwdep_ioctl_compat; #endif - mutex_init(&codec->user_mutex); - snd_array_init(&codec->init_verbs, sizeof(struct hda_verb), 32); - snd_array_init(&codec->hints, sizeof(struct hda_hint), 32); - snd_array_init(&codec->user_pins, sizeof(struct hda_pincfg), 16); - - return 0; -} - -#ifdef CONFIG_PM -static ssize_t power_on_acct_show(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - struct snd_hwdep *hwdep = dev_get_drvdata(dev); - struct hda_codec *codec = hwdep->private_data; - snd_hda_update_power_acct(codec); - return sprintf(buf, "%u\n", jiffies_to_msecs(codec->power_on_acct)); -} - -static ssize_t power_off_acct_show(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - struct snd_hwdep *hwdep = dev_get_drvdata(dev); - struct hda_codec *codec = hwdep->private_data; - snd_hda_update_power_acct(codec); - return sprintf(buf, "%u\n", jiffies_to_msecs(codec->power_off_acct)); -} - -static struct device_attribute power_attrs[] = { - __ATTR_RO(power_on_acct), - __ATTR_RO(power_off_acct), -}; - -int snd_hda_hwdep_add_power_sysfs(struct hda_codec *codec) -{ - struct snd_hwdep *hwdep = codec->hwdep; - int i; - - for (i = 0; i < ARRAY_SIZE(power_attrs); i++) - snd_add_device_sysfs_file(SNDRV_DEVICE_TYPE_HWDEP, hwdep->card, - hwdep->device, &power_attrs[i]); - return 0; -} -#endif /* CONFIG_PM */ - -#ifdef CONFIG_SND_HDA_RECONFIG - -/* - * sysfs interface - */ - -static int clear_codec(struct hda_codec *codec) -{ - int err; - - err = snd_hda_codec_reset(codec); - if (err < 0) { - snd_printk(KERN_ERR "The codec is being used, can't free.\n"); - return err; - } - clear_hwdep_elements(codec); - return 0; -} - -static int reconfig_codec(struct hda_codec *codec) -{ - int err; - - snd_hda_power_up(codec); - snd_printk(KERN_INFO "hda-codec: reconfiguring\n"); - err = snd_hda_codec_reset(codec); - if (err < 0) { - snd_printk(KERN_ERR - "The codec is being used, can't reconfigure.\n"); - goto error; - } - err = snd_hda_codec_configure(codec); - if (err < 0) - goto error; - /* rebuild PCMs */ - err = snd_hda_codec_build_pcms(codec); - if (err < 0) - goto error; - /* rebuild mixers */ - err = snd_hda_codec_build_controls(codec); - if (err < 0) - goto error; - err = snd_card_register(codec->bus->card); - error: - snd_hda_power_down(codec); - return err; -} - -/* - * allocate a string at most len chars, and remove the trailing EOL - */ -static char *kstrndup_noeol(const char *src, size_t len) -{ - char *s = kstrndup(src, len, GFP_KERNEL); - char *p; - if (!s) - return NULL; - p = strchr(s, '\n'); - if (p) - *p = 0; - return s; -} - -#define CODEC_INFO_SHOW(type) \ -static ssize_t type##_show(struct device *dev, \ - struct device_attribute *attr, \ - char *buf) \ -{ \ - struct snd_hwdep *hwdep = dev_get_drvdata(dev); \ - struct hda_codec *codec = hwdep->private_data; \ - return sprintf(buf, "0x%x\n", codec->type); \ -} - -#define CODEC_INFO_STR_SHOW(type) \ -static ssize_t type##_show(struct device *dev, \ - struct device_attribute *attr, \ - char *buf) \ -{ \ - struct snd_hwdep *hwdep = dev_get_drvdata(dev); \ - struct hda_codec *codec = hwdep->private_data; \ - return sprintf(buf, "%s\n", \ - codec->type ? codec->type : ""); \ -} - -CODEC_INFO_SHOW(vendor_id); -CODEC_INFO_SHOW(subsystem_id); -CODEC_INFO_SHOW(revision_id); -CODEC_INFO_SHOW(afg); -CODEC_INFO_SHOW(mfg); -CODEC_INFO_STR_SHOW(vendor_name); -CODEC_INFO_STR_SHOW(chip_name); -CODEC_INFO_STR_SHOW(modelname); - -#define CODEC_INFO_STORE(type) \ -static ssize_t type##_store(struct device *dev, \ - struct device_attribute *attr, \ - const char *buf, size_t count) \ -{ \ - struct snd_hwdep *hwdep = dev_get_drvdata(dev); \ - struct hda_codec *codec = hwdep->private_data; \ - unsigned long val; \ - int err = kstrtoul(buf, 0, &val); \ - if (err < 0) \ - return err; \ - codec->type = val; \ - return count; \ -} - -#define CODEC_INFO_STR_STORE(type) \ -static ssize_t type##_store(struct device *dev, \ - struct device_attribute *attr, \ - const char *buf, size_t count) \ -{ \ - struct snd_hwdep *hwdep = dev_get_drvdata(dev); \ - struct hda_codec *codec = hwdep->private_data; \ - char *s = kstrndup_noeol(buf, 64); \ - if (!s) \ - return -ENOMEM; \ - kfree(codec->type); \ - codec->type = s; \ - return count; \ -} - -CODEC_INFO_STORE(vendor_id); -CODEC_INFO_STORE(subsystem_id); -CODEC_INFO_STORE(revision_id); -CODEC_INFO_STR_STORE(vendor_name); -CODEC_INFO_STR_STORE(chip_name); -CODEC_INFO_STR_STORE(modelname); - -#define CODEC_ACTION_STORE(type) \ -static ssize_t type##_store(struct device *dev, \ - struct device_attribute *attr, \ - const char *buf, size_t count) \ -{ \ - struct snd_hwdep *hwdep = dev_get_drvdata(dev); \ - struct hda_codec *codec = hwdep->private_data; \ - int err = 0; \ - if (*buf) \ - err = type##_codec(codec); \ - return err < 0 ? err : count; \ -} - -CODEC_ACTION_STORE(reconfig); -CODEC_ACTION_STORE(clear); - -static ssize_t init_verbs_show(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - struct snd_hwdep *hwdep = dev_get_drvdata(dev); - struct hda_codec *codec = hwdep->private_data; - int i, len = 0; - mutex_lock(&codec->user_mutex); - for (i = 0; i < codec->init_verbs.used; i++) { - struct hda_verb *v = snd_array_elem(&codec->init_verbs, i); - len += snprintf(buf + len, PAGE_SIZE - len, - "0x%02x 0x%03x 0x%04x\n", - v->nid, v->verb, v->param); - } - mutex_unlock(&codec->user_mutex); - return len; -} - -static int parse_init_verbs(struct hda_codec *codec, const char *buf) -{ - struct hda_verb *v; - int nid, verb, param; - - if (sscanf(buf, "%i %i %i", &nid, &verb, ¶m) != 3) - return -EINVAL; - if (!nid || !verb) - return -EINVAL; - mutex_lock(&codec->user_mutex); - v = snd_array_new(&codec->init_verbs); - if (!v) { - mutex_unlock(&codec->user_mutex); - return -ENOMEM; - } - v->nid = nid; - v->verb = verb; - v->param = param; - mutex_unlock(&codec->user_mutex); - return 0; -} - -static ssize_t init_verbs_store(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t count) -{ - struct snd_hwdep *hwdep = dev_get_drvdata(dev); - struct hda_codec *codec = hwdep->private_data; - int err = parse_init_verbs(codec, buf); - if (err < 0) - return err; - return count; -} - -static ssize_t hints_show(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - struct snd_hwdep *hwdep = dev_get_drvdata(dev); - struct hda_codec *codec = hwdep->private_data; - int i, len = 0; - mutex_lock(&codec->user_mutex); - for (i = 0; i < codec->hints.used; i++) { - struct hda_hint *hint = snd_array_elem(&codec->hints, i); - len += snprintf(buf + len, PAGE_SIZE - len, - "%s = %s\n", hint->key, hint->val); - } - mutex_unlock(&codec->user_mutex); - return len; -} - -static struct hda_hint *get_hint(struct hda_codec *codec, const char *key) -{ - int i; - - for (i = 0; i < codec->hints.used; i++) { - struct hda_hint *hint = snd_array_elem(&codec->hints, i); - if (!strcmp(hint->key, key)) - return hint; - } - return NULL; -} - -static void remove_trail_spaces(char *str) -{ - char *p; - if (!*str) - return; - p = str + strlen(str) - 1; - for (; isspace(*p); p--) { - *p = 0; - if (p == str) - return; - } -} - -#define MAX_HINTS 1024 - -static int parse_hints(struct hda_codec *codec, const char *buf) -{ - char *key, *val; - struct hda_hint *hint; - int err = 0; - - buf = skip_spaces(buf); - if (!*buf || *buf == '#' || *buf == '\n') - return 0; - if (*buf == '=') - return -EINVAL; - key = kstrndup_noeol(buf, 1024); - if (!key) - return -ENOMEM; - /* extract key and val */ - val = strchr(key, '='); - if (!val) { - kfree(key); - return -EINVAL; - } - *val++ = 0; - val = skip_spaces(val); - remove_trail_spaces(key); - remove_trail_spaces(val); - mutex_lock(&codec->user_mutex); - hint = get_hint(codec, key); - if (hint) { - /* replace */ - kfree(hint->key); - hint->key = key; - hint->val = val; - goto unlock; - } - /* allocate a new hint entry */ - if (codec->hints.used >= MAX_HINTS) - hint = NULL; - else - hint = snd_array_new(&codec->hints); - if (hint) { - hint->key = key; - hint->val = val; - } else { - err = -ENOMEM; - } - unlock: - mutex_unlock(&codec->user_mutex); - if (err) - kfree(key); - return err; -} - -static ssize_t hints_store(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t count) -{ - struct snd_hwdep *hwdep = dev_get_drvdata(dev); - struct hda_codec *codec = hwdep->private_data; - int err = parse_hints(codec, buf); - if (err < 0) - return err; - return count; -} - -static ssize_t pin_configs_show(struct hda_codec *codec, - struct snd_array *list, - char *buf) -{ - int i, len = 0; - mutex_lock(&codec->user_mutex); - for (i = 0; i < list->used; i++) { - struct hda_pincfg *pin = snd_array_elem(list, i); - len += sprintf(buf + len, "0x%02x 0x%08x\n", - pin->nid, pin->cfg); - } - mutex_unlock(&codec->user_mutex); - return len; -} - -static ssize_t init_pin_configs_show(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - struct snd_hwdep *hwdep = dev_get_drvdata(dev); - struct hda_codec *codec = hwdep->private_data; - return pin_configs_show(codec, &codec->init_pins, buf); -} - -static ssize_t user_pin_configs_show(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - struct snd_hwdep *hwdep = dev_get_drvdata(dev); - struct hda_codec *codec = hwdep->private_data; - return pin_configs_show(codec, &codec->user_pins, buf); -} - -static ssize_t driver_pin_configs_show(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - struct snd_hwdep *hwdep = dev_get_drvdata(dev); - struct hda_codec *codec = hwdep->private_data; - return pin_configs_show(codec, &codec->driver_pins, buf); -} - -#define MAX_PIN_CONFIGS 32 - -static int parse_user_pin_configs(struct hda_codec *codec, const char *buf) -{ - int nid, cfg, err; - - if (sscanf(buf, "%i %i", &nid, &cfg) != 2) - return -EINVAL; - if (!nid) - return -EINVAL; - mutex_lock(&codec->user_mutex); - err = snd_hda_add_pincfg(codec, &codec->user_pins, nid, cfg); - mutex_unlock(&codec->user_mutex); - return err; -} - -static ssize_t user_pin_configs_store(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t count) -{ - struct snd_hwdep *hwdep = dev_get_drvdata(dev); - struct hda_codec *codec = hwdep->private_data; - int err = parse_user_pin_configs(codec, buf); - if (err < 0) - return err; - return count; -} - -#define CODEC_ATTR_RW(type) \ - __ATTR(type, 0644, type##_show, type##_store) -#define CODEC_ATTR_RO(type) \ - __ATTR_RO(type) -#define CODEC_ATTR_WO(type) \ - __ATTR(type, 0200, NULL, type##_store) - -static struct device_attribute codec_attrs[] = { - CODEC_ATTR_RW(vendor_id), - CODEC_ATTR_RW(subsystem_id), - CODEC_ATTR_RW(revision_id), - CODEC_ATTR_RO(afg), - CODEC_ATTR_RO(mfg), - CODEC_ATTR_RW(vendor_name), - CODEC_ATTR_RW(chip_name), - CODEC_ATTR_RW(modelname), - CODEC_ATTR_RW(init_verbs), - CODEC_ATTR_RW(hints), - CODEC_ATTR_RO(init_pin_configs), - CODEC_ATTR_RW(user_pin_configs), - CODEC_ATTR_RO(driver_pin_configs), - CODEC_ATTR_WO(reconfig), - CODEC_ATTR_WO(clear), -}; - -/* - * create sysfs files on hwdep directory - */ -int snd_hda_hwdep_add_sysfs(struct hda_codec *codec) -{ - struct snd_hwdep *hwdep = codec->hwdep; - int i; - - for (i = 0; i < ARRAY_SIZE(codec_attrs); i++) - snd_add_device_sysfs_file(SNDRV_DEVICE_TYPE_HWDEP, hwdep->card, - hwdep->device, &codec_attrs[i]); - return 0; -} - -/* - * Look for hint string - */ -const char *snd_hda_get_hint(struct hda_codec *codec, const char *key) -{ - struct hda_hint *hint = get_hint(codec, key); - return hint ? hint->val : NULL; -} -EXPORT_SYMBOL_GPL(snd_hda_get_hint); - -int snd_hda_get_bool_hint(struct hda_codec *codec, const char *key) -{ - const char *p; - int ret; - - mutex_lock(&codec->user_mutex); - p = snd_hda_get_hint(codec, key); - if (!p || !*p) - ret = -ENOENT; - else { - switch (toupper(*p)) { - case 'T': /* true */ - case 'Y': /* yes */ - case '1': - ret = 1; - break; - default: - ret = 0; - break; - } - } - mutex_unlock(&codec->user_mutex); - return ret; -} -EXPORT_SYMBOL_GPL(snd_hda_get_bool_hint); - -int snd_hda_get_int_hint(struct hda_codec *codec, const char *key, int *valp) -{ - const char *p; - unsigned long val; - int ret; - - mutex_lock(&codec->user_mutex); - p = snd_hda_get_hint(codec, key); - if (!p) - ret = -ENOENT; - else if (kstrtoul(p, 0, &val)) - ret = -EINVAL; - else { - *valp = val; - ret = 0; - } - mutex_unlock(&codec->user_mutex); - return ret; -} -EXPORT_SYMBOL_GPL(snd_hda_get_int_hint); -#endif /* CONFIG_SND_HDA_RECONFIG */ - -#ifdef CONFIG_SND_HDA_PATCH_LOADER + /* link to codec */ + hwdep->dev = &codec->dev; -/* parser mode */ -enum { - LINE_MODE_NONE, - LINE_MODE_CODEC, - LINE_MODE_MODEL, - LINE_MODE_PINCFG, - LINE_MODE_VERB, - LINE_MODE_HINT, - LINE_MODE_VENDOR_ID, - LINE_MODE_SUBSYSTEM_ID, - LINE_MODE_REVISION_ID, - LINE_MODE_CHIP_NAME, - NUM_LINE_MODES, -}; - -static inline int strmatch(const char *a, const char *b) -{ - return strnicmp(a, b, strlen(b)) == 0; -} - -/* parse the contents after the line "[codec]" - * accept only the line with three numbers, and assign the current codec - */ -static void parse_codec_mode(char *buf, struct hda_bus *bus, - struct hda_codec **codecp) -{ - int vendorid, subid, caddr; - struct hda_codec *codec; - - *codecp = NULL; - if (sscanf(buf, "%i %i %i", &vendorid, &subid, &caddr) == 3) { - list_for_each_entry(codec, &bus->codec_list, list) { - if ((vendorid <= 0 || codec->vendor_id == vendorid) && - (subid <= 0 || codec->subsystem_id == subid) && - codec->addr == caddr) { - *codecp = codec; - break; - } - } - } -} - -/* parse the contents after the other command tags, [pincfg], [verb], - * [vendor_id], [subsystem_id], [revision_id], [chip_name], [hint] and [model] - * just pass to the sysfs helper (only when any codec was specified) - */ -static void parse_pincfg_mode(char *buf, struct hda_bus *bus, - struct hda_codec **codecp) -{ - parse_user_pin_configs(*codecp, buf); -} - -static void parse_verb_mode(char *buf, struct hda_bus *bus, - struct hda_codec **codecp) -{ - parse_init_verbs(*codecp, buf); -} - -static void parse_hint_mode(char *buf, struct hda_bus *bus, - struct hda_codec **codecp) -{ - parse_hints(*codecp, buf); -} - -static void parse_model_mode(char *buf, struct hda_bus *bus, - struct hda_codec **codecp) -{ - kfree((*codecp)->modelname); - (*codecp)->modelname = kstrdup(buf, GFP_KERNEL); -} - -static void parse_chip_name_mode(char *buf, struct hda_bus *bus, - struct hda_codec **codecp) -{ - kfree((*codecp)->chip_name); - (*codecp)->chip_name = kstrdup(buf, GFP_KERNEL); -} - -#define DEFINE_PARSE_ID_MODE(name) \ -static void parse_##name##_mode(char *buf, struct hda_bus *bus, \ - struct hda_codec **codecp) \ -{ \ - unsigned long val; \ - if (!kstrtoul(buf, 0, &val)) \ - (*codecp)->name = val; \ -} - -DEFINE_PARSE_ID_MODE(vendor_id); -DEFINE_PARSE_ID_MODE(subsystem_id); -DEFINE_PARSE_ID_MODE(revision_id); - - -struct hda_patch_item { - const char *tag; - const char *alias; - void (*parser)(char *buf, struct hda_bus *bus, struct hda_codec **retc); -}; - -static struct hda_patch_item patch_items[NUM_LINE_MODES] = { - [LINE_MODE_CODEC] = { - .tag = "[codec]", - .parser = parse_codec_mode, - }, - [LINE_MODE_MODEL] = { - .tag = "[model]", - .parser = parse_model_mode, - }, - [LINE_MODE_VERB] = { - .tag = "[verb]", - .alias = "[init_verbs]", - .parser = parse_verb_mode, - }, - [LINE_MODE_PINCFG] = { - .tag = "[pincfg]", - .alias = "[user_pin_configs]", - .parser = parse_pincfg_mode, - }, - [LINE_MODE_HINT] = { - .tag = "[hint]", - .alias = "[hints]", - .parser = parse_hint_mode - }, - [LINE_MODE_VENDOR_ID] = { - .tag = "[vendor_id]", - .parser = parse_vendor_id_mode, - }, - [LINE_MODE_SUBSYSTEM_ID] = { - .tag = "[subsystem_id]", - .parser = parse_subsystem_id_mode, - }, - [LINE_MODE_REVISION_ID] = { - .tag = "[revision_id]", - .parser = parse_revision_id_mode, - }, - [LINE_MODE_CHIP_NAME] = { - .tag = "[chip_name]", - .parser = parse_chip_name_mode, - }, -}; - -/* check the line starting with '[' -- change the parser mode accodingly */ -static int parse_line_mode(char *buf, struct hda_bus *bus) -{ - int i; - for (i = 0; i < ARRAY_SIZE(patch_items); i++) { - if (!patch_items[i].tag) - continue; - if (strmatch(buf, patch_items[i].tag)) - return i; - if (patch_items[i].alias && strmatch(buf, patch_items[i].alias)) - return i; - } - return LINE_MODE_NONE; -} - -/* copy one line from the buffer in fw, and update the fields in fw - * return zero if it reaches to the end of the buffer, or non-zero - * if successfully copied a line - * - * the spaces at the beginning and the end of the line are stripped - */ -static int get_line_from_fw(char *buf, int size, size_t *fw_size_p, - const void **fw_data_p) -{ - int len; - size_t fw_size = *fw_size_p; - const char *p = *fw_data_p; - - while (isspace(*p) && fw_size) { - p++; - fw_size--; - } - if (!fw_size) - return 0; - - for (len = 0; len < fw_size; len++) { - if (!*p) - break; - if (*p == '\n') { - p++; - len++; - break; - } - if (len < size) - *buf++ = *p++; - } - *buf = 0; - *fw_size_p = fw_size - len; - *fw_data_p = p; - remove_trail_spaces(buf); - return 1; -} - -/* - * load a "patch" firmware file and parse it - */ -int snd_hda_load_patch(struct hda_bus *bus, size_t fw_size, const void *fw_buf) -{ - char buf[128]; - struct hda_codec *codec; - int line_mode; - - line_mode = LINE_MODE_NONE; - codec = NULL; - while (get_line_from_fw(buf, sizeof(buf) - 1, &fw_size, &fw_buf)) { - if (!*buf || *buf == '#' || *buf == '\n') - continue; - if (*buf == '[') - line_mode = parse_line_mode(buf, bus); - else if (patch_items[line_mode].parser && - (codec || line_mode <= LINE_MODE_CODEC)) - patch_items[line_mode].parser(buf, bus, &codec); - } return 0; } -EXPORT_SYMBOL_GPL(snd_hda_load_patch); -#endif /* CONFIG_SND_HDA_PATCH_LOADER */ diff --git a/sound/pci/hda/hda_i915.c b/sound/pci/hda/hda_i915.c index 76c13d5b3ca..9d07e4edacd 100644 --- a/sound/pci/hda/hda_i915.c +++ b/sound/pci/hda/hda_i915.c @@ -30,7 +30,7 @@ void hda_display_power(bool enable) if (!get_power || !put_power) return; - snd_printdd("HDA display power %s \n", + pr_debug("HDA display power %s \n", enable ? "Enable" : "Disable"); if (enable) get_power(); @@ -44,7 +44,7 @@ int hda_i915_init(void) get_power = symbol_request(i915_request_power_well); if (!get_power) { - snd_printk(KERN_WARNING "hda-i915: get_power symbol get fail\n"); + pr_warn("hda-i915: get_power symbol get fail\n"); return -ENODEV; } @@ -55,7 +55,7 @@ int hda_i915_init(void) return -ENODEV; } - snd_printd("HDA driver get symbol successfully from i915 module\n"); + pr_debug("HDA driver get symbol successfully from i915 module\n"); return err; } diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c index e354ab1ec20..77ca894f828 100644 --- a/sound/pci/hda/hda_intel.c +++ b/sound/pci/hda/hda_intel.c @@ -63,6 +63,8 @@ #include <linux/firmware.h> #include "hda_codec.h" #include "hda_i915.h" +#include "hda_controller.h" +#include "hda_priv.h" static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; @@ -127,6 +129,7 @@ static struct kernel_param_ops param_ops_xint = { #define param_check_xint param_check_int static int power_save = CONFIG_SND_HDA_POWER_SAVE_DEFAULT; +static int *power_save_addr = &power_save; module_param(power_save, xint, 0644); MODULE_PARM_DESC(power_save, "Automatic power-saving timeout " "(in second, 0 = disable)."); @@ -138,6 +141,8 @@ MODULE_PARM_DESC(power_save, "Automatic power-saving timeout " static bool power_save_controller = 1; module_param(power_save_controller, bool, 0644); MODULE_PARM_DESC(power_save_controller, "Reset controller in power save mode."); +#else +static int *power_save_addr; #endif /* CONFIG_PM */ static int align_buffer_size = -1; @@ -149,10 +154,8 @@ MODULE_PARM_DESC(align_buffer_size, static bool hda_snoop = true; module_param_named(snoop, hda_snoop, bool, 0444); MODULE_PARM_DESC(snoop, "Enable/disable snooping"); -#define azx_snoop(chip) (chip)->snoop #else #define hda_snoop true -#define azx_snoop(chip) true #endif @@ -191,12 +194,6 @@ MODULE_SUPPORTED_DEVICE("{{Intel, ICH6}," "{ULI, M5461}}"); MODULE_DESCRIPTION("Intel HDA driver"); -#ifdef CONFIG_SND_VERBOSE_PRINTK -#define SFX /* nop */ -#else -#define SFX "hda-intel " -#endif - #if defined(CONFIG_PM) && defined(CONFIG_VGA_SWITCHEROO) #if IS_ENABLED(CONFIG_SND_HDA_CODEC_HDMI) #define SUPPORT_VGA_SWITCHEROO @@ -205,365 +202,8 @@ MODULE_DESCRIPTION("Intel HDA driver"); /* - * registers - */ -#define ICH6_REG_GCAP 0x00 -#define ICH6_GCAP_64OK (1 << 0) /* 64bit address support */ -#define ICH6_GCAP_NSDO (3 << 1) /* # of serial data out signals */ -#define ICH6_GCAP_BSS (31 << 3) /* # of bidirectional streams */ -#define ICH6_GCAP_ISS (15 << 8) /* # of input streams */ -#define ICH6_GCAP_OSS (15 << 12) /* # of output streams */ -#define ICH6_REG_VMIN 0x02 -#define ICH6_REG_VMAJ 0x03 -#define ICH6_REG_OUTPAY 0x04 -#define ICH6_REG_INPAY 0x06 -#define ICH6_REG_GCTL 0x08 -#define ICH6_GCTL_RESET (1 << 0) /* controller reset */ -#define ICH6_GCTL_FCNTRL (1 << 1) /* flush control */ -#define ICH6_GCTL_UNSOL (1 << 8) /* accept unsol. response enable */ -#define ICH6_REG_WAKEEN 0x0c -#define ICH6_REG_STATESTS 0x0e -#define ICH6_REG_GSTS 0x10 -#define ICH6_GSTS_FSTS (1 << 1) /* flush status */ -#define ICH6_REG_INTCTL 0x20 -#define ICH6_REG_INTSTS 0x24 -#define ICH6_REG_WALLCLK 0x30 /* 24Mhz source */ -#define ICH6_REG_OLD_SSYNC 0x34 /* SSYNC for old ICH */ -#define ICH6_REG_SSYNC 0x38 -#define ICH6_REG_CORBLBASE 0x40 -#define ICH6_REG_CORBUBASE 0x44 -#define ICH6_REG_CORBWP 0x48 -#define ICH6_REG_CORBRP 0x4a -#define ICH6_CORBRP_RST (1 << 15) /* read pointer reset */ -#define ICH6_REG_CORBCTL 0x4c -#define ICH6_CORBCTL_RUN (1 << 1) /* enable DMA */ -#define ICH6_CORBCTL_CMEIE (1 << 0) /* enable memory error irq */ -#define ICH6_REG_CORBSTS 0x4d -#define ICH6_CORBSTS_CMEI (1 << 0) /* memory error indication */ -#define ICH6_REG_CORBSIZE 0x4e - -#define ICH6_REG_RIRBLBASE 0x50 -#define ICH6_REG_RIRBUBASE 0x54 -#define ICH6_REG_RIRBWP 0x58 -#define ICH6_RIRBWP_RST (1 << 15) /* write pointer reset */ -#define ICH6_REG_RINTCNT 0x5a -#define ICH6_REG_RIRBCTL 0x5c -#define ICH6_RBCTL_IRQ_EN (1 << 0) /* enable IRQ */ -#define ICH6_RBCTL_DMA_EN (1 << 1) /* enable DMA */ -#define ICH6_RBCTL_OVERRUN_EN (1 << 2) /* enable overrun irq */ -#define ICH6_REG_RIRBSTS 0x5d -#define ICH6_RBSTS_IRQ (1 << 0) /* response irq */ -#define ICH6_RBSTS_OVERRUN (1 << 2) /* overrun irq */ -#define ICH6_REG_RIRBSIZE 0x5e - -#define ICH6_REG_IC 0x60 -#define ICH6_REG_IR 0x64 -#define ICH6_REG_IRS 0x68 -#define ICH6_IRS_VALID (1<<1) -#define ICH6_IRS_BUSY (1<<0) - -#define ICH6_REG_DPLBASE 0x70 -#define ICH6_REG_DPUBASE 0x74 -#define ICH6_DPLBASE_ENABLE 0x1 /* Enable position buffer */ - -/* SD offset: SDI0=0x80, SDI1=0xa0, ... SDO3=0x160 */ -enum { SDI0, SDI1, SDI2, SDI3, SDO0, SDO1, SDO2, SDO3 }; - -/* stream register offsets from stream base */ -#define ICH6_REG_SD_CTL 0x00 -#define ICH6_REG_SD_STS 0x03 -#define ICH6_REG_SD_LPIB 0x04 -#define ICH6_REG_SD_CBL 0x08 -#define ICH6_REG_SD_LVI 0x0c -#define ICH6_REG_SD_FIFOW 0x0e -#define ICH6_REG_SD_FIFOSIZE 0x10 -#define ICH6_REG_SD_FORMAT 0x12 -#define ICH6_REG_SD_BDLPL 0x18 -#define ICH6_REG_SD_BDLPU 0x1c - -/* PCI space */ -#define ICH6_PCIREG_TCSEL 0x44 - -/* - * other constants */ -/* max number of SDs */ -/* ICH, ATI and VIA have 4 playback and 4 capture */ -#define ICH6_NUM_CAPTURE 4 -#define ICH6_NUM_PLAYBACK 4 - -/* ULI has 6 playback and 5 capture */ -#define ULI_NUM_CAPTURE 5 -#define ULI_NUM_PLAYBACK 6 - -/* ATI HDMI may have up to 8 playbacks and 0 capture */ -#define ATIHDMI_NUM_CAPTURE 0 -#define ATIHDMI_NUM_PLAYBACK 8 - -/* TERA has 4 playback and 3 capture */ -#define TERA_NUM_CAPTURE 3 -#define TERA_NUM_PLAYBACK 4 - -/* this number is statically defined for simplicity */ -#define MAX_AZX_DEV 16 - -/* max number of fragments - we may use more if allocating more pages for BDL */ -#define BDL_SIZE 4096 -#define AZX_MAX_BDL_ENTRIES (BDL_SIZE / 16) -#define AZX_MAX_FRAG 32 -/* max buffer size - no h/w limit, you can increase as you like */ -#define AZX_MAX_BUF_SIZE (1024*1024*1024) - -/* RIRB int mask: overrun[2], response[0] */ -#define RIRB_INT_RESPONSE 0x01 -#define RIRB_INT_OVERRUN 0x04 -#define RIRB_INT_MASK 0x05 - -/* STATESTS int mask: S3,SD2,SD1,SD0 */ -#define AZX_MAX_CODECS 8 -#define AZX_DEFAULT_CODECS 4 -#define STATESTS_INT_MASK ((1 << AZX_MAX_CODECS) - 1) - -/* SD_CTL bits */ -#define SD_CTL_STREAM_RESET 0x01 /* stream reset bit */ -#define SD_CTL_DMA_START 0x02 /* stream DMA start bit */ -#define SD_CTL_STRIPE (3 << 16) /* stripe control */ -#define SD_CTL_TRAFFIC_PRIO (1 << 18) /* traffic priority */ -#define SD_CTL_DIR (1 << 19) /* bi-directional stream */ -#define SD_CTL_STREAM_TAG_MASK (0xf << 20) -#define SD_CTL_STREAM_TAG_SHIFT 20 - -/* SD_CTL and SD_STS */ -#define SD_INT_DESC_ERR 0x10 /* descriptor error interrupt */ -#define SD_INT_FIFO_ERR 0x08 /* FIFO error interrupt */ -#define SD_INT_COMPLETE 0x04 /* completion interrupt */ -#define SD_INT_MASK (SD_INT_DESC_ERR|SD_INT_FIFO_ERR|\ - SD_INT_COMPLETE) - -/* SD_STS */ -#define SD_STS_FIFO_READY 0x20 /* FIFO ready */ - -/* INTCTL and INTSTS */ -#define ICH6_INT_ALL_STREAM 0xff /* all stream interrupts */ -#define ICH6_INT_CTRL_EN 0x40000000 /* controller interrupt enable bit */ -#define ICH6_INT_GLOBAL_EN 0x80000000 /* global interrupt enable bit */ - -/* below are so far hardcoded - should read registers in future */ -#define ICH6_MAX_CORB_ENTRIES 256 -#define ICH6_MAX_RIRB_ENTRIES 256 - -/* position fix mode */ -enum { - POS_FIX_AUTO, - POS_FIX_LPIB, - POS_FIX_POSBUF, - POS_FIX_VIACOMBO, - POS_FIX_COMBO, -}; - -/* Defines for ATI HD Audio support in SB450 south bridge */ -#define ATI_SB450_HDAUDIO_MISC_CNTR2_ADDR 0x42 -#define ATI_SB450_HDAUDIO_ENABLE_SNOOP 0x02 - -/* Defines for Nvidia HDA support */ -#define NVIDIA_HDA_TRANSREG_ADDR 0x4e -#define NVIDIA_HDA_ENABLE_COHBITS 0x0f -#define NVIDIA_HDA_ISTRM_COH 0x4d -#define NVIDIA_HDA_OSTRM_COH 0x4c -#define NVIDIA_HDA_ENABLE_COHBIT 0x01 - -/* Defines for Intel SCH HDA snoop control */ -#define INTEL_SCH_HDA_DEVC 0x78 -#define INTEL_SCH_HDA_DEVC_NOSNOOP (0x1<<11) - -/* Define IN stream 0 FIFO size offset in VIA controller */ -#define VIA_IN_STREAM0_FIFO_SIZE_OFFSET 0x90 -/* Define VIA HD Audio Device ID*/ -#define VIA_HDAC_DEVICE_ID 0x3288 - -/* HD Audio class code */ -#define PCI_CLASS_MULTIMEDIA_HD_AUDIO 0x0403 - -/* - */ - -struct azx_dev { - struct snd_dma_buffer bdl; /* BDL buffer */ - u32 *posbuf; /* position buffer pointer */ - - unsigned int bufsize; /* size of the play buffer in bytes */ - unsigned int period_bytes; /* size of the period in bytes */ - unsigned int frags; /* number for period in the play buffer */ - unsigned int fifo_size; /* FIFO size */ - unsigned long start_wallclk; /* start + minimum wallclk */ - unsigned long period_wallclk; /* wallclk for period */ - - void __iomem *sd_addr; /* stream descriptor pointer */ - - u32 sd_int_sta_mask; /* stream int status mask */ - - /* pcm support */ - struct snd_pcm_substream *substream; /* assigned substream, - * set in PCM open - */ - unsigned int format_val; /* format value to be set in the - * controller and the codec - */ - unsigned char stream_tag; /* assigned stream */ - unsigned char index; /* stream index */ - int assigned_key; /* last device# key assigned to */ - - unsigned int opened :1; - unsigned int running :1; - unsigned int irq_pending :1; - unsigned int prepared:1; - unsigned int locked:1; - /* - * For VIA: - * A flag to ensure DMA position is 0 - * when link position is not greater than FIFO size - */ - unsigned int insufficient :1; - unsigned int wc_marked:1; - unsigned int no_period_wakeup:1; - - struct timecounter azx_tc; - struct cyclecounter azx_cc; - - int delay_negative_threshold; - -#ifdef CONFIG_SND_HDA_DSP_LOADER - struct mutex dsp_mutex; -#endif -}; - -/* DSP lock helpers */ -#ifdef CONFIG_SND_HDA_DSP_LOADER -#define dsp_lock_init(dev) mutex_init(&(dev)->dsp_mutex) -#define dsp_lock(dev) mutex_lock(&(dev)->dsp_mutex) -#define dsp_unlock(dev) mutex_unlock(&(dev)->dsp_mutex) -#define dsp_is_locked(dev) ((dev)->locked) -#else -#define dsp_lock_init(dev) do {} while (0) -#define dsp_lock(dev) do {} while (0) -#define dsp_unlock(dev) do {} while (0) -#define dsp_is_locked(dev) 0 -#endif - -/* CORB/RIRB */ -struct azx_rb { - u32 *buf; /* CORB/RIRB buffer - * Each CORB entry is 4byte, RIRB is 8byte - */ - dma_addr_t addr; /* physical address of CORB/RIRB buffer */ - /* for RIRB */ - unsigned short rp, wp; /* read/write pointers */ - int cmds[AZX_MAX_CODECS]; /* number of pending requests */ - u32 res[AZX_MAX_CODECS]; /* last read value */ -}; - -struct azx_pcm { - struct azx *chip; - struct snd_pcm *pcm; - struct hda_codec *codec; - struct hda_pcm_stream *hinfo[2]; - struct list_head list; -}; - -struct azx { - struct snd_card *card; - struct pci_dev *pci; - int dev_index; - - /* chip type specific */ - int driver_type; - unsigned int driver_caps; - int playback_streams; - int playback_index_offset; - int capture_streams; - int capture_index_offset; - int num_streams; - - /* pci resources */ - unsigned long addr; - void __iomem *remap_addr; - int irq; - - /* locks */ - spinlock_t reg_lock; - struct mutex open_mutex; - struct completion probe_wait; - - /* streams (x num_streams) */ - struct azx_dev *azx_dev; - - /* PCM */ - struct list_head pcm_list; /* azx_pcm list */ - - /* HD codec */ - unsigned short codec_mask; - int codec_probe_mask; /* copied from probe_mask option */ - struct hda_bus *bus; - unsigned int beep_mode; - - /* CORB/RIRB */ - struct azx_rb corb; - struct azx_rb rirb; - - /* CORB/RIRB and position buffers */ - struct snd_dma_buffer rb; - struct snd_dma_buffer posbuf; - -#ifdef CONFIG_SND_HDA_PATCH_LOADER - const struct firmware *fw; -#endif - - /* flags */ - int position_fix[2]; /* for both playback/capture streams */ - int poll_count; - unsigned int running :1; - unsigned int initialized :1; - unsigned int single_cmd :1; - unsigned int polling_mode :1; - unsigned int msi :1; - unsigned int irq_pending_warned :1; - unsigned int probing :1; /* codec probing phase */ - unsigned int snoop:1; - unsigned int align_buffer_size:1; - unsigned int region_requested:1; - - /* VGA-switcheroo setup */ - unsigned int use_vga_switcheroo:1; - unsigned int vga_switcheroo_registered:1; - unsigned int init_failed:1; /* delayed init failed */ - unsigned int disabled:1; /* disabled by VGA-switcher */ - - /* for debugging */ - unsigned int last_cmd[AZX_MAX_CODECS]; - - /* for pending irqs */ - struct work_struct irq_pending_work; - - struct work_struct probe_work; - - /* reboot notifier (for mysterious hangup problem at power-down) */ - struct notifier_block reboot_notifier; - - /* card list (for power_save trigger) */ - struct list_head list; - -#ifdef CONFIG_SND_HDA_DSP_LOADER - struct azx_dev saved_azx_dev; -#endif - - /* secondary power domain for hdmi audio under vga device */ - struct dev_pm_domain hdmi_pm_domain; -}; - -#define CREATE_TRACE_POINTS -#include "hda_intel_trace.h" - /* driver types */ enum { AZX_DRIVER_ICH, @@ -584,28 +224,6 @@ enum { AZX_NUM_DRIVERS, /* keep this as last entry */ }; -/* driver quirks (capabilities) */ -/* bits 0-7 are used for indicating driver type */ -#define AZX_DCAPS_NO_TCSEL (1 << 8) /* No Intel TCSEL bit */ -#define AZX_DCAPS_NO_MSI (1 << 9) /* No MSI support */ -#define AZX_DCAPS_ATI_SNOOP (1 << 10) /* ATI snoop enable */ -#define AZX_DCAPS_NVIDIA_SNOOP (1 << 11) /* Nvidia snoop enable */ -#define AZX_DCAPS_SCH_SNOOP (1 << 12) /* SCH/PCH snoop enable */ -#define AZX_DCAPS_RIRB_DELAY (1 << 13) /* Long delay in read loop */ -#define AZX_DCAPS_RIRB_PRE_DELAY (1 << 14) /* Put a delay before read */ -#define AZX_DCAPS_CTX_WORKAROUND (1 << 15) /* X-Fi workaround */ -#define AZX_DCAPS_POSFIX_LPIB (1 << 16) /* Use LPIB as default */ -#define AZX_DCAPS_POSFIX_VIA (1 << 17) /* Use VIACOMBO as default */ -#define AZX_DCAPS_NO_64BIT (1 << 18) /* No 64bit address */ -#define AZX_DCAPS_SYNC_WRITE (1 << 19) /* sync each cmd write */ -#define AZX_DCAPS_OLD_SSYNC (1 << 20) /* Old SSYNC reg for ICH */ -#define AZX_DCAPS_BUFSIZE (1 << 21) /* no buffer size alignment */ -#define AZX_DCAPS_ALIGN_BUFSIZE (1 << 22) /* buffer size alignment */ -#define AZX_DCAPS_4K_BDLE_BOUNDARY (1 << 23) /* BDLE in 4k boundary */ -#define AZX_DCAPS_COUNT_LPIB_DELAY (1 << 25) /* Take LPIB as delay */ -#define AZX_DCAPS_PM_RUNTIME (1 << 26) /* runtime PM support */ -#define AZX_DCAPS_I915_POWERWELL (1 << 27) /* HSW i915 power well support */ - /* quirks for Intel PCH */ #define AZX_DCAPS_INTEL_PCH_NOPM \ (AZX_DCAPS_SCH_SNOOP | AZX_DCAPS_BUFSIZE | \ @@ -663,38 +281,6 @@ static char *driver_short_names[] = { [AZX_DRIVER_GENERIC] = "HD-Audio Generic", }; -/* - * macros for easy use - */ -#define azx_writel(chip,reg,value) \ - writel(value, (chip)->remap_addr + ICH6_REG_##reg) -#define azx_readl(chip,reg) \ - readl((chip)->remap_addr + ICH6_REG_##reg) -#define azx_writew(chip,reg,value) \ - writew(value, (chip)->remap_addr + ICH6_REG_##reg) -#define azx_readw(chip,reg) \ - readw((chip)->remap_addr + ICH6_REG_##reg) -#define azx_writeb(chip,reg,value) \ - writeb(value, (chip)->remap_addr + ICH6_REG_##reg) -#define azx_readb(chip,reg) \ - readb((chip)->remap_addr + ICH6_REG_##reg) - -#define azx_sd_writel(dev,reg,value) \ - writel(value, (dev)->sd_addr + ICH6_REG_##reg) -#define azx_sd_readl(dev,reg) \ - readl((dev)->sd_addr + ICH6_REG_##reg) -#define azx_sd_writew(dev,reg,value) \ - writew(value, (dev)->sd_addr + ICH6_REG_##reg) -#define azx_sd_readw(dev,reg) \ - readw((dev)->sd_addr + ICH6_REG_##reg) -#define azx_sd_writeb(dev,reg,value) \ - writeb(value, (dev)->sd_addr + ICH6_REG_##reg) -#define azx_sd_readb(dev,reg) \ - readb((dev)->sd_addr + ICH6_REG_##reg) - -/* for pcm support */ -#define get_azx_dev(substream) (substream->runtime->private_data) - #ifdef CONFIG_X86 static void __mark_pages_wc(struct azx *chip, struct snd_dma_buffer *dmab, bool on) { @@ -749,578 +335,6 @@ static inline void mark_runtime_wc(struct azx *chip, struct azx_dev *azx_dev, #endif static int azx_acquire_irq(struct azx *chip, int do_disconnect); -static int azx_send_cmd(struct hda_bus *bus, unsigned int val); -/* - * Interface for HD codec - */ - -/* - * CORB / RIRB interface - */ -static int azx_alloc_cmd_io(struct azx *chip) -{ - int err; - - /* single page (at least 4096 bytes) must suffice for both ringbuffes */ - err = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, - snd_dma_pci_data(chip->pci), - PAGE_SIZE, &chip->rb); - if (err < 0) { - snd_printk(KERN_ERR SFX "%s: cannot allocate CORB/RIRB\n", pci_name(chip->pci)); - return err; - } - mark_pages_wc(chip, &chip->rb, true); - return 0; -} - -static void azx_init_cmd_io(struct azx *chip) -{ - spin_lock_irq(&chip->reg_lock); - /* CORB set up */ - chip->corb.addr = chip->rb.addr; - chip->corb.buf = (u32 *)chip->rb.area; - azx_writel(chip, CORBLBASE, (u32)chip->corb.addr); - azx_writel(chip, CORBUBASE, upper_32_bits(chip->corb.addr)); - - /* set the corb size to 256 entries (ULI requires explicitly) */ - azx_writeb(chip, CORBSIZE, 0x02); - /* set the corb write pointer to 0 */ - azx_writew(chip, CORBWP, 0); - /* reset the corb hw read pointer */ - azx_writew(chip, CORBRP, ICH6_CORBRP_RST); - /* enable corb dma */ - azx_writeb(chip, CORBCTL, ICH6_CORBCTL_RUN); - - /* RIRB set up */ - chip->rirb.addr = chip->rb.addr + 2048; - chip->rirb.buf = (u32 *)(chip->rb.area + 2048); - chip->rirb.wp = chip->rirb.rp = 0; - memset(chip->rirb.cmds, 0, sizeof(chip->rirb.cmds)); - azx_writel(chip, RIRBLBASE, (u32)chip->rirb.addr); - azx_writel(chip, RIRBUBASE, upper_32_bits(chip->rirb.addr)); - - /* set the rirb size to 256 entries (ULI requires explicitly) */ - azx_writeb(chip, RIRBSIZE, 0x02); - /* reset the rirb hw write pointer */ - azx_writew(chip, RIRBWP, ICH6_RIRBWP_RST); - /* set N=1, get RIRB response interrupt for new entry */ - if (chip->driver_caps & AZX_DCAPS_CTX_WORKAROUND) - azx_writew(chip, RINTCNT, 0xc0); - else - azx_writew(chip, RINTCNT, 1); - /* enable rirb dma and response irq */ - azx_writeb(chip, RIRBCTL, ICH6_RBCTL_DMA_EN | ICH6_RBCTL_IRQ_EN); - spin_unlock_irq(&chip->reg_lock); -} - -static void azx_free_cmd_io(struct azx *chip) -{ - spin_lock_irq(&chip->reg_lock); - /* disable ringbuffer DMAs */ - azx_writeb(chip, RIRBCTL, 0); - azx_writeb(chip, CORBCTL, 0); - spin_unlock_irq(&chip->reg_lock); -} - -static unsigned int azx_command_addr(u32 cmd) -{ - unsigned int addr = cmd >> 28; - - if (addr >= AZX_MAX_CODECS) { - snd_BUG(); - addr = 0; - } - - return addr; -} - -static unsigned int azx_response_addr(u32 res) -{ - unsigned int addr = res & 0xf; - - if (addr >= AZX_MAX_CODECS) { - snd_BUG(); - addr = 0; - } - - return addr; -} - -/* send a command */ -static int azx_corb_send_cmd(struct hda_bus *bus, u32 val) -{ - struct azx *chip = bus->private_data; - unsigned int addr = azx_command_addr(val); - unsigned int wp, rp; - - spin_lock_irq(&chip->reg_lock); - - /* add command to corb */ - wp = azx_readw(chip, CORBWP); - if (wp == 0xffff) { - /* something wrong, controller likely turned to D3 */ - spin_unlock_irq(&chip->reg_lock); - return -EIO; - } - wp++; - wp %= ICH6_MAX_CORB_ENTRIES; - - rp = azx_readw(chip, CORBRP); - if (wp == rp) { - /* oops, it's full */ - spin_unlock_irq(&chip->reg_lock); - return -EAGAIN; - } - - chip->rirb.cmds[addr]++; - chip->corb.buf[wp] = cpu_to_le32(val); - azx_writel(chip, CORBWP, wp); - - spin_unlock_irq(&chip->reg_lock); - - return 0; -} - -#define ICH6_RIRB_EX_UNSOL_EV (1<<4) - -/* retrieve RIRB entry - called from interrupt handler */ -static void azx_update_rirb(struct azx *chip) -{ - unsigned int rp, wp; - unsigned int addr; - u32 res, res_ex; - - wp = azx_readw(chip, RIRBWP); - if (wp == 0xffff) { - /* something wrong, controller likely turned to D3 */ - return; - } - - if (wp == chip->rirb.wp) - return; - chip->rirb.wp = wp; - - while (chip->rirb.rp != wp) { - chip->rirb.rp++; - chip->rirb.rp %= ICH6_MAX_RIRB_ENTRIES; - - rp = chip->rirb.rp << 1; /* an RIRB entry is 8-bytes */ - res_ex = le32_to_cpu(chip->rirb.buf[rp + 1]); - res = le32_to_cpu(chip->rirb.buf[rp]); - addr = azx_response_addr(res_ex); - if (res_ex & ICH6_RIRB_EX_UNSOL_EV) - snd_hda_queue_unsol_event(chip->bus, res, res_ex); - else if (chip->rirb.cmds[addr]) { - chip->rirb.res[addr] = res; - smp_wmb(); - chip->rirb.cmds[addr]--; - } else if (printk_ratelimit()) { - snd_printk(KERN_ERR SFX "%s: spurious response %#x:%#x, last cmd=%#08x\n", - pci_name(chip->pci), - res, res_ex, - chip->last_cmd[addr]); - } - } -} - -/* receive a response */ -static unsigned int azx_rirb_get_response(struct hda_bus *bus, - unsigned int addr) -{ - struct azx *chip = bus->private_data; - unsigned long timeout; - unsigned long loopcounter; - int do_poll = 0; - - again: - timeout = jiffies + msecs_to_jiffies(1000); - - for (loopcounter = 0;; loopcounter++) { - if (chip->polling_mode || do_poll) { - spin_lock_irq(&chip->reg_lock); - azx_update_rirb(chip); - spin_unlock_irq(&chip->reg_lock); - } - if (!chip->rirb.cmds[addr]) { - smp_rmb(); - bus->rirb_error = 0; - - if (!do_poll) - chip->poll_count = 0; - return chip->rirb.res[addr]; /* the last value */ - } - if (time_after(jiffies, timeout)) - break; - if (bus->needs_damn_long_delay || loopcounter > 3000) - msleep(2); /* temporary workaround */ - else { - udelay(10); - cond_resched(); - } - } - - if (!bus->no_response_fallback) - return -1; - - if (!chip->polling_mode && chip->poll_count < 2) { - snd_printdd(SFX "%s: azx_get_response timeout, " - "polling the codec once: last cmd=0x%08x\n", - pci_name(chip->pci), chip->last_cmd[addr]); - do_poll = 1; - chip->poll_count++; - goto again; - } - - - if (!chip->polling_mode) { - snd_printk(KERN_WARNING SFX "%s: azx_get_response timeout, " - "switching to polling mode: last cmd=0x%08x\n", - pci_name(chip->pci), chip->last_cmd[addr]); - chip->polling_mode = 1; - goto again; - } - - if (chip->msi) { - snd_printk(KERN_WARNING SFX "%s: No response from codec, " - "disabling MSI: last cmd=0x%08x\n", - pci_name(chip->pci), chip->last_cmd[addr]); - free_irq(chip->irq, chip); - chip->irq = -1; - pci_disable_msi(chip->pci); - chip->msi = 0; - if (azx_acquire_irq(chip, 1) < 0) { - bus->rirb_error = 1; - return -1; - } - goto again; - } - - if (chip->probing) { - /* If this critical timeout happens during the codec probing - * phase, this is likely an access to a non-existing codec - * slot. Better to return an error and reset the system. - */ - return -1; - } - - /* a fatal communication error; need either to reset or to fallback - * to the single_cmd mode - */ - bus->rirb_error = 1; - if (bus->allow_bus_reset && !bus->response_reset && !bus->in_reset) { - bus->response_reset = 1; - return -1; /* give a chance to retry */ - } - - snd_printk(KERN_ERR "hda_intel: azx_get_response timeout, " - "switching to single_cmd mode: last cmd=0x%08x\n", - chip->last_cmd[addr]); - chip->single_cmd = 1; - bus->response_reset = 0; - /* release CORB/RIRB */ - azx_free_cmd_io(chip); - /* disable unsolicited responses */ - azx_writel(chip, GCTL, azx_readl(chip, GCTL) & ~ICH6_GCTL_UNSOL); - return -1; -} - -/* - * Use the single immediate command instead of CORB/RIRB for simplicity - * - * Note: according to Intel, this is not preferred use. The command was - * intended for the BIOS only, and may get confused with unsolicited - * responses. So, we shouldn't use it for normal operation from the - * driver. - * I left the codes, however, for debugging/testing purposes. - */ - -/* receive a response */ -static int azx_single_wait_for_response(struct azx *chip, unsigned int addr) -{ - int timeout = 50; - - while (timeout--) { - /* check IRV busy bit */ - if (azx_readw(chip, IRS) & ICH6_IRS_VALID) { - /* reuse rirb.res as the response return value */ - chip->rirb.res[addr] = azx_readl(chip, IR); - return 0; - } - udelay(1); - } - if (printk_ratelimit()) - snd_printd(SFX "%s: get_response timeout: IRS=0x%x\n", - pci_name(chip->pci), azx_readw(chip, IRS)); - chip->rirb.res[addr] = -1; - return -EIO; -} - -/* send a command */ -static int azx_single_send_cmd(struct hda_bus *bus, u32 val) -{ - struct azx *chip = bus->private_data; - unsigned int addr = azx_command_addr(val); - int timeout = 50; - - bus->rirb_error = 0; - while (timeout--) { - /* check ICB busy bit */ - if (!((azx_readw(chip, IRS) & ICH6_IRS_BUSY))) { - /* Clear IRV valid bit */ - azx_writew(chip, IRS, azx_readw(chip, IRS) | - ICH6_IRS_VALID); - azx_writel(chip, IC, val); - azx_writew(chip, IRS, azx_readw(chip, IRS) | - ICH6_IRS_BUSY); - return azx_single_wait_for_response(chip, addr); - } - udelay(1); - } - if (printk_ratelimit()) - snd_printd(SFX "%s: send_cmd timeout: IRS=0x%x, val=0x%x\n", - pci_name(chip->pci), azx_readw(chip, IRS), val); - return -EIO; -} - -/* receive a response */ -static unsigned int azx_single_get_response(struct hda_bus *bus, - unsigned int addr) -{ - struct azx *chip = bus->private_data; - return chip->rirb.res[addr]; -} - -/* - * The below are the main callbacks from hda_codec. - * - * They are just the skeleton to call sub-callbacks according to the - * current setting of chip->single_cmd. - */ - -/* send a command */ -static int azx_send_cmd(struct hda_bus *bus, unsigned int val) -{ - struct azx *chip = bus->private_data; - - if (chip->disabled) - return 0; - chip->last_cmd[azx_command_addr(val)] = val; - if (chip->single_cmd) - return azx_single_send_cmd(bus, val); - else - return azx_corb_send_cmd(bus, val); -} - -/* get a response */ -static unsigned int azx_get_response(struct hda_bus *bus, - unsigned int addr) -{ - struct azx *chip = bus->private_data; - if (chip->disabled) - return 0; - if (chip->single_cmd) - return azx_single_get_response(bus, addr); - else - return azx_rirb_get_response(bus, addr); -} - -#ifdef CONFIG_PM -static void azx_power_notify(struct hda_bus *bus, bool power_up); -#endif - -#ifdef CONFIG_SND_HDA_DSP_LOADER -static int azx_load_dsp_prepare(struct hda_bus *bus, unsigned int format, - unsigned int byte_size, - struct snd_dma_buffer *bufp); -static void azx_load_dsp_trigger(struct hda_bus *bus, bool start); -static void azx_load_dsp_cleanup(struct hda_bus *bus, - struct snd_dma_buffer *dmab); -#endif - -/* enter link reset */ -static void azx_enter_link_reset(struct azx *chip) -{ - unsigned long timeout; - - /* reset controller */ - azx_writel(chip, GCTL, azx_readl(chip, GCTL) & ~ICH6_GCTL_RESET); - - timeout = jiffies + msecs_to_jiffies(100); - while ((azx_readb(chip, GCTL) & ICH6_GCTL_RESET) && - time_before(jiffies, timeout)) - usleep_range(500, 1000); -} - -/* exit link reset */ -static void azx_exit_link_reset(struct azx *chip) -{ - unsigned long timeout; - - azx_writeb(chip, GCTL, azx_readb(chip, GCTL) | ICH6_GCTL_RESET); - - timeout = jiffies + msecs_to_jiffies(100); - while (!azx_readb(chip, GCTL) && - time_before(jiffies, timeout)) - usleep_range(500, 1000); -} - -/* reset codec link */ -static int azx_reset(struct azx *chip, int full_reset) -{ - if (!full_reset) - goto __skip; - - /* clear STATESTS */ - azx_writew(chip, STATESTS, STATESTS_INT_MASK); - - /* reset controller */ - azx_enter_link_reset(chip); - - /* delay for >= 100us for codec PLL to settle per spec - * Rev 0.9 section 5.5.1 - */ - usleep_range(500, 1000); - - /* Bring controller out of reset */ - azx_exit_link_reset(chip); - - /* Brent Chartrand said to wait >= 540us for codecs to initialize */ - usleep_range(1000, 1200); - - __skip: - /* check to see if controller is ready */ - if (!azx_readb(chip, GCTL)) { - snd_printd(SFX "%s: azx_reset: controller not ready!\n", pci_name(chip->pci)); - return -EBUSY; - } - - /* Accept unsolicited responses */ - if (!chip->single_cmd) - azx_writel(chip, GCTL, azx_readl(chip, GCTL) | - ICH6_GCTL_UNSOL); - - /* detect codecs */ - if (!chip->codec_mask) { - chip->codec_mask = azx_readw(chip, STATESTS); - snd_printdd(SFX "%s: codec_mask = 0x%x\n", pci_name(chip->pci), chip->codec_mask); - } - - return 0; -} - - -/* - * Lowlevel interface - */ - -/* enable interrupts */ -static void azx_int_enable(struct azx *chip) -{ - /* enable controller CIE and GIE */ - azx_writel(chip, INTCTL, azx_readl(chip, INTCTL) | - ICH6_INT_CTRL_EN | ICH6_INT_GLOBAL_EN); -} - -/* disable interrupts */ -static void azx_int_disable(struct azx *chip) -{ - int i; - - /* disable interrupts in stream descriptor */ - for (i = 0; i < chip->num_streams; i++) { - struct azx_dev *azx_dev = &chip->azx_dev[i]; - azx_sd_writeb(azx_dev, SD_CTL, - azx_sd_readb(azx_dev, SD_CTL) & ~SD_INT_MASK); - } - - /* disable SIE for all streams */ - azx_writeb(chip, INTCTL, 0); - - /* disable controller CIE and GIE */ - azx_writel(chip, INTCTL, azx_readl(chip, INTCTL) & - ~(ICH6_INT_CTRL_EN | ICH6_INT_GLOBAL_EN)); -} - -/* clear interrupts */ -static void azx_int_clear(struct azx *chip) -{ - int i; - - /* clear stream status */ - for (i = 0; i < chip->num_streams; i++) { - struct azx_dev *azx_dev = &chip->azx_dev[i]; - azx_sd_writeb(azx_dev, SD_STS, SD_INT_MASK); - } - - /* clear STATESTS */ - azx_writew(chip, STATESTS, STATESTS_INT_MASK); - - /* clear rirb status */ - azx_writeb(chip, RIRBSTS, RIRB_INT_MASK); - - /* clear int status */ - azx_writel(chip, INTSTS, ICH6_INT_CTRL_EN | ICH6_INT_ALL_STREAM); -} - -/* start a stream */ -static void azx_stream_start(struct azx *chip, struct azx_dev *azx_dev) -{ - /* - * Before stream start, initialize parameter - */ - azx_dev->insufficient = 1; - - /* enable SIE */ - azx_writel(chip, INTCTL, - azx_readl(chip, INTCTL) | (1 << azx_dev->index)); - /* set DMA start and interrupt mask */ - azx_sd_writeb(azx_dev, SD_CTL, azx_sd_readb(azx_dev, SD_CTL) | - SD_CTL_DMA_START | SD_INT_MASK); -} - -/* stop DMA */ -static void azx_stream_clear(struct azx *chip, struct azx_dev *azx_dev) -{ - azx_sd_writeb(azx_dev, SD_CTL, azx_sd_readb(azx_dev, SD_CTL) & - ~(SD_CTL_DMA_START | SD_INT_MASK)); - azx_sd_writeb(azx_dev, SD_STS, SD_INT_MASK); /* to be sure */ -} - -/* stop a stream */ -static void azx_stream_stop(struct azx *chip, struct azx_dev *azx_dev) -{ - azx_stream_clear(chip, azx_dev); - /* disable SIE */ - azx_writel(chip, INTCTL, - azx_readl(chip, INTCTL) & ~(1 << azx_dev->index)); -} - - -/* - * reset and start the controller registers - */ -static void azx_init_chip(struct azx *chip, int full_reset) -{ - if (chip->initialized) - return; - - /* reset controller */ - azx_reset(chip, full_reset); - - /* initialize interrupts */ - azx_int_clear(chip); - azx_int_enable(chip); - - /* initialize the codec command I/O */ - if (!chip->single_cmd) - azx_init_cmd_io(chip); - - /* program the position buffer */ - azx_writel(chip, DPLBASE, (u32)chip->posbuf.addr); - azx_writel(chip, DPUBASE, upper_32_bits(chip->posbuf.addr)); - - chip->initialized = 1; -} /* * initialize the PCI registers @@ -1346,7 +360,7 @@ static void azx_init_pci(struct azx *chip) * The PCI register TCSEL is defined in the Intel manuals. */ if (!(chip->driver_caps & AZX_DCAPS_NO_TCSEL)) { - snd_printdd(SFX "%s: Clearing TCSEL\n", pci_name(chip->pci)); + dev_dbg(chip->card->dev, "Clearing TCSEL\n"); update_pci_byte(chip->pci, ICH6_PCIREG_TCSEL, 0x07, 0); } @@ -1354,7 +368,8 @@ static void azx_init_pci(struct azx *chip) * we need to enable snoop. */ if (chip->driver_caps & AZX_DCAPS_ATI_SNOOP) { - snd_printdd(SFX "%s: Setting ATI snoop: %d\n", pci_name(chip->pci), azx_snoop(chip)); + dev_dbg(chip->card->dev, "Setting ATI snoop: %d\n", + azx_snoop(chip)); update_pci_byte(chip->pci, ATI_SB450_HDAUDIO_MISC_CNTR2_ADDR, 0x07, azx_snoop(chip) ? ATI_SB450_HDAUDIO_ENABLE_SNOOP : 0); @@ -1362,7 +377,8 @@ static void azx_init_pci(struct azx *chip) /* For NVIDIA HDA, enable snoop */ if (chip->driver_caps & AZX_DCAPS_NVIDIA_SNOOP) { - snd_printdd(SFX "%s: Setting Nvidia snoop: %d\n", pci_name(chip->pci), azx_snoop(chip)); + dev_dbg(chip->card->dev, "Setting Nvidia snoop: %d\n", + azx_snoop(chip)); update_pci_byte(chip->pci, NVIDIA_HDA_TRANSREG_ADDR, 0x0f, NVIDIA_HDA_ENABLE_COHBITS); @@ -1387,1114 +403,31 @@ static void azx_init_pci(struct azx *chip) pci_read_config_word(chip->pci, INTEL_SCH_HDA_DEVC, &snoop); } - snd_printdd(SFX "%s: SCH snoop: %s\n", - pci_name(chip->pci), (snoop & INTEL_SCH_HDA_DEVC_NOSNOOP) - ? "Disabled" : "Enabled"); + dev_dbg(chip->card->dev, "SCH snoop: %s\n", + (snoop & INTEL_SCH_HDA_DEVC_NOSNOOP) ? + "Disabled" : "Enabled"); } } - static int azx_position_ok(struct azx *chip, struct azx_dev *azx_dev); -/* - * interrupt handler - */ -static irqreturn_t azx_interrupt(int irq, void *dev_id) -{ - struct azx *chip = dev_id; - struct azx_dev *azx_dev; - u32 status; - u8 sd_status; - int i, ok; - -#ifdef CONFIG_PM_RUNTIME - if (chip->driver_caps & AZX_DCAPS_PM_RUNTIME) - if (chip->pci->dev.power.runtime_status != RPM_ACTIVE) - return IRQ_NONE; -#endif - - spin_lock(&chip->reg_lock); - - if (chip->disabled) { - spin_unlock(&chip->reg_lock); - return IRQ_NONE; - } - - status = azx_readl(chip, INTSTS); - if (status == 0 || status == 0xffffffff) { - spin_unlock(&chip->reg_lock); - return IRQ_NONE; - } - - for (i = 0; i < chip->num_streams; i++) { - azx_dev = &chip->azx_dev[i]; - if (status & azx_dev->sd_int_sta_mask) { - sd_status = azx_sd_readb(azx_dev, SD_STS); - azx_sd_writeb(azx_dev, SD_STS, SD_INT_MASK); - if (!azx_dev->substream || !azx_dev->running || - !(sd_status & SD_INT_COMPLETE)) - continue; - /* check whether this IRQ is really acceptable */ - ok = azx_position_ok(chip, azx_dev); - if (ok == 1) { - azx_dev->irq_pending = 0; - spin_unlock(&chip->reg_lock); - snd_pcm_period_elapsed(azx_dev->substream); - spin_lock(&chip->reg_lock); - } else if (ok == 0 && chip->bus && chip->bus->workq) { - /* bogus IRQ, process it later */ - azx_dev->irq_pending = 1; - queue_work(chip->bus->workq, - &chip->irq_pending_work); - } - } - } - - /* clear rirb int */ - status = azx_readb(chip, RIRBSTS); - if (status & RIRB_INT_MASK) { - if (status & RIRB_INT_RESPONSE) { - if (chip->driver_caps & AZX_DCAPS_RIRB_PRE_DELAY) - udelay(80); - azx_update_rirb(chip); - } - azx_writeb(chip, RIRBSTS, RIRB_INT_MASK); - } - -#if 0 - /* clear state status int */ - if (azx_readw(chip, STATESTS) & 0x04) - azx_writew(chip, STATESTS, 0x04); -#endif - spin_unlock(&chip->reg_lock); - - return IRQ_HANDLED; -} - - -/* - * set up a BDL entry - */ -static int setup_bdle(struct azx *chip, - struct snd_dma_buffer *dmab, - struct azx_dev *azx_dev, u32 **bdlp, - int ofs, int size, int with_ioc) -{ - u32 *bdl = *bdlp; - - while (size > 0) { - dma_addr_t addr; - int chunk; - - if (azx_dev->frags >= AZX_MAX_BDL_ENTRIES) - return -EINVAL; - - addr = snd_sgbuf_get_addr(dmab, ofs); - /* program the address field of the BDL entry */ - bdl[0] = cpu_to_le32((u32)addr); - bdl[1] = cpu_to_le32(upper_32_bits(addr)); - /* program the size field of the BDL entry */ - chunk = snd_sgbuf_get_chunk_size(dmab, ofs, size); - /* one BDLE cannot cross 4K boundary on CTHDA chips */ - if (chip->driver_caps & AZX_DCAPS_4K_BDLE_BOUNDARY) { - u32 remain = 0x1000 - (ofs & 0xfff); - if (chunk > remain) - chunk = remain; - } - bdl[2] = cpu_to_le32(chunk); - /* program the IOC to enable interrupt - * only when the whole fragment is processed - */ - size -= chunk; - bdl[3] = (size || !with_ioc) ? 0 : cpu_to_le32(0x01); - bdl += 4; - azx_dev->frags++; - ofs += chunk; - } - *bdlp = bdl; - return ofs; -} - -/* - * set up BDL entries - */ -static int azx_setup_periods(struct azx *chip, - struct snd_pcm_substream *substream, - struct azx_dev *azx_dev) -{ - u32 *bdl; - int i, ofs, periods, period_bytes; - int pos_adj; - - /* reset BDL address */ - azx_sd_writel(azx_dev, SD_BDLPL, 0); - azx_sd_writel(azx_dev, SD_BDLPU, 0); - - period_bytes = azx_dev->period_bytes; - periods = azx_dev->bufsize / period_bytes; - - /* program the initial BDL entries */ - bdl = (u32 *)azx_dev->bdl.area; - ofs = 0; - azx_dev->frags = 0; - pos_adj = bdl_pos_adj[chip->dev_index]; - if (!azx_dev->no_period_wakeup && pos_adj > 0) { - struct snd_pcm_runtime *runtime = substream->runtime; - int pos_align = pos_adj; - pos_adj = (pos_adj * runtime->rate + 47999) / 48000; - if (!pos_adj) - pos_adj = pos_align; - else - pos_adj = ((pos_adj + pos_align - 1) / pos_align) * - pos_align; - pos_adj = frames_to_bytes(runtime, pos_adj); - if (pos_adj >= period_bytes) { - snd_printk(KERN_WARNING SFX "%s: Too big adjustment %d\n", - pci_name(chip->pci), bdl_pos_adj[chip->dev_index]); - pos_adj = 0; - } else { - ofs = setup_bdle(chip, snd_pcm_get_dma_buf(substream), - azx_dev, - &bdl, ofs, pos_adj, true); - if (ofs < 0) - goto error; - } - } else - pos_adj = 0; - for (i = 0; i < periods; i++) { - if (i == periods - 1 && pos_adj) - ofs = setup_bdle(chip, snd_pcm_get_dma_buf(substream), - azx_dev, &bdl, ofs, - period_bytes - pos_adj, 0); - else - ofs = setup_bdle(chip, snd_pcm_get_dma_buf(substream), - azx_dev, &bdl, ofs, - period_bytes, - !azx_dev->no_period_wakeup); - if (ofs < 0) - goto error; - } - return 0; - - error: - snd_printk(KERN_ERR SFX "%s: Too many BDL entries: buffer=%d, period=%d\n", - pci_name(chip->pci), azx_dev->bufsize, period_bytes); - return -EINVAL; -} - -/* reset stream */ -static void azx_stream_reset(struct azx *chip, struct azx_dev *azx_dev) -{ - unsigned char val; - int timeout; - - azx_stream_clear(chip, azx_dev); - - azx_sd_writeb(azx_dev, SD_CTL, azx_sd_readb(azx_dev, SD_CTL) | - SD_CTL_STREAM_RESET); - udelay(3); - timeout = 300; - while (!((val = azx_sd_readb(azx_dev, SD_CTL)) & SD_CTL_STREAM_RESET) && - --timeout) - ; - val &= ~SD_CTL_STREAM_RESET; - azx_sd_writeb(azx_dev, SD_CTL, val); - udelay(3); - - timeout = 300; - /* waiting for hardware to report that the stream is out of reset */ - while (((val = azx_sd_readb(azx_dev, SD_CTL)) & SD_CTL_STREAM_RESET) && - --timeout) - ; - - /* reset first position - may not be synced with hw at this time */ - *azx_dev->posbuf = 0; -} - -/* - * set up the SD for streaming - */ -static int azx_setup_controller(struct azx *chip, struct azx_dev *azx_dev) -{ - unsigned int val; - /* make sure the run bit is zero for SD */ - azx_stream_clear(chip, azx_dev); - /* program the stream_tag */ - val = azx_sd_readl(azx_dev, SD_CTL); - val = (val & ~SD_CTL_STREAM_TAG_MASK) | - (azx_dev->stream_tag << SD_CTL_STREAM_TAG_SHIFT); - if (!azx_snoop(chip)) - val |= SD_CTL_TRAFFIC_PRIO; - azx_sd_writel(azx_dev, SD_CTL, val); - - /* program the length of samples in cyclic buffer */ - azx_sd_writel(azx_dev, SD_CBL, azx_dev->bufsize); - - /* program the stream format */ - /* this value needs to be the same as the one programmed */ - azx_sd_writew(azx_dev, SD_FORMAT, azx_dev->format_val); - - /* program the stream LVI (last valid index) of the BDL */ - azx_sd_writew(azx_dev, SD_LVI, azx_dev->frags - 1); - - /* program the BDL address */ - /* lower BDL address */ - azx_sd_writel(azx_dev, SD_BDLPL, (u32)azx_dev->bdl.addr); - /* upper BDL address */ - azx_sd_writel(azx_dev, SD_BDLPU, upper_32_bits(azx_dev->bdl.addr)); - - /* enable the position buffer */ - if (chip->position_fix[0] != POS_FIX_LPIB || - chip->position_fix[1] != POS_FIX_LPIB) { - if (!(azx_readl(chip, DPLBASE) & ICH6_DPLBASE_ENABLE)) - azx_writel(chip, DPLBASE, - (u32)chip->posbuf.addr | ICH6_DPLBASE_ENABLE); - } - - /* set the interrupt enable bits in the descriptor control register */ - azx_sd_writel(azx_dev, SD_CTL, - azx_sd_readl(azx_dev, SD_CTL) | SD_INT_MASK); - - return 0; -} - -/* - * Probe the given codec address - */ -static int probe_codec(struct azx *chip, int addr) -{ - unsigned int cmd = (addr << 28) | (AC_NODE_ROOT << 20) | - (AC_VERB_PARAMETERS << 8) | AC_PAR_VENDOR_ID; - unsigned int res; - - mutex_lock(&chip->bus->cmd_mutex); - chip->probing = 1; - azx_send_cmd(chip->bus, cmd); - res = azx_get_response(chip->bus, addr); - chip->probing = 0; - mutex_unlock(&chip->bus->cmd_mutex); - if (res == -1) - return -EIO; - snd_printdd(SFX "%s: codec #%d probed OK\n", pci_name(chip->pci), addr); - return 0; -} - -static int azx_attach_pcm_stream(struct hda_bus *bus, struct hda_codec *codec, - struct hda_pcm *cpcm); -static void azx_stop_chip(struct azx *chip); - -static void azx_bus_reset(struct hda_bus *bus) -{ - struct azx *chip = bus->private_data; - - bus->in_reset = 1; - azx_stop_chip(chip); - azx_init_chip(chip, 1); -#ifdef CONFIG_PM - if (chip->initialized) { - struct azx_pcm *p; - list_for_each_entry(p, &chip->pcm_list, list) - snd_pcm_suspend_all(p->pcm); - snd_hda_suspend(chip->bus); - snd_hda_resume(chip->bus); - } -#endif - bus->in_reset = 0; -} - -static int get_jackpoll_interval(struct azx *chip) -{ - int i = jackpoll_ms[chip->dev_index]; - unsigned int j; - if (i == 0) - return 0; - if (i < 50 || i > 60000) - j = 0; - else - j = msecs_to_jiffies(i); - if (j == 0) - snd_printk(KERN_WARNING SFX - "jackpoll_ms value out of range: %d\n", i); - return j; -} - -/* - * Codec initialization - */ - -/* number of codec slots for each chipset: 0 = default slots (i.e. 4) */ -static unsigned int azx_max_codecs[AZX_NUM_DRIVERS] = { - [AZX_DRIVER_NVIDIA] = 8, - [AZX_DRIVER_TERA] = 1, -}; - -static int azx_codec_create(struct azx *chip, const char *model) -{ - struct hda_bus_template bus_temp; - int c, codecs, err; - int max_slots; - - memset(&bus_temp, 0, sizeof(bus_temp)); - bus_temp.private_data = chip; - bus_temp.modelname = model; - bus_temp.pci = chip->pci; - bus_temp.ops.command = azx_send_cmd; - bus_temp.ops.get_response = azx_get_response; - bus_temp.ops.attach_pcm = azx_attach_pcm_stream; - bus_temp.ops.bus_reset = azx_bus_reset; -#ifdef CONFIG_PM - bus_temp.power_save = &power_save; - bus_temp.ops.pm_notify = azx_power_notify; -#endif -#ifdef CONFIG_SND_HDA_DSP_LOADER - bus_temp.ops.load_dsp_prepare = azx_load_dsp_prepare; - bus_temp.ops.load_dsp_trigger = azx_load_dsp_trigger; - bus_temp.ops.load_dsp_cleanup = azx_load_dsp_cleanup; -#endif - - err = snd_hda_bus_new(chip->card, &bus_temp, &chip->bus); - if (err < 0) - return err; - - if (chip->driver_caps & AZX_DCAPS_RIRB_DELAY) { - snd_printd(SFX "%s: Enable delay in RIRB handling\n", pci_name(chip->pci)); - chip->bus->needs_damn_long_delay = 1; - } - - codecs = 0; - max_slots = azx_max_codecs[chip->driver_type]; - if (!max_slots) - max_slots = AZX_DEFAULT_CODECS; - - /* First try to probe all given codec slots */ - for (c = 0; c < max_slots; c++) { - if ((chip->codec_mask & (1 << c)) & chip->codec_probe_mask) { - if (probe_codec(chip, c) < 0) { - /* Some BIOSen give you wrong codec addresses - * that don't exist - */ - snd_printk(KERN_WARNING SFX - "%s: Codec #%d probe error; " - "disabling it...\n", pci_name(chip->pci), c); - chip->codec_mask &= ~(1 << c); - /* More badly, accessing to a non-existing - * codec often screws up the controller chip, - * and disturbs the further communications. - * Thus if an error occurs during probing, - * better to reset the controller chip to - * get back to the sanity state. - */ - azx_stop_chip(chip); - azx_init_chip(chip, 1); - } - } - } - - /* AMD chipsets often cause the communication stalls upon certain - * sequence like the pin-detection. It seems that forcing the synced - * access works around the stall. Grrr... - */ - if (chip->driver_caps & AZX_DCAPS_SYNC_WRITE) { - snd_printd(SFX "%s: Enable sync_write for stable communication\n", - pci_name(chip->pci)); - chip->bus->sync_write = 1; - chip->bus->allow_bus_reset = 1; - } - - /* Then create codec instances */ - for (c = 0; c < max_slots; c++) { - if ((chip->codec_mask & (1 << c)) & chip->codec_probe_mask) { - struct hda_codec *codec; - err = snd_hda_codec_new(chip->bus, c, &codec); - if (err < 0) - continue; - codec->jackpoll_interval = get_jackpoll_interval(chip); - codec->beep_mode = chip->beep_mode; - codecs++; - } - } - if (!codecs) { - snd_printk(KERN_ERR SFX "%s: no codecs initialized\n", pci_name(chip->pci)); - return -ENXIO; - } - return 0; -} - -/* configure each codec instance */ -static int azx_codec_configure(struct azx *chip) -{ - struct hda_codec *codec; - list_for_each_entry(codec, &chip->bus->codec_list, list) { - snd_hda_codec_configure(codec); - } - return 0; -} - - -/* - * PCM support - */ - -/* assign a stream for the PCM */ -static inline struct azx_dev * -azx_assign_device(struct azx *chip, struct snd_pcm_substream *substream) -{ - int dev, i, nums; - struct azx_dev *res = NULL; - /* make a non-zero unique key for the substream */ - int key = (substream->pcm->device << 16) | (substream->number << 2) | - (substream->stream + 1); - - if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { - dev = chip->playback_index_offset; - nums = chip->playback_streams; - } else { - dev = chip->capture_index_offset; - nums = chip->capture_streams; - } - for (i = 0; i < nums; i++, dev++) { - struct azx_dev *azx_dev = &chip->azx_dev[dev]; - dsp_lock(azx_dev); - if (!azx_dev->opened && !dsp_is_locked(azx_dev)) { - res = azx_dev; - if (res->assigned_key == key) { - res->opened = 1; - res->assigned_key = key; - dsp_unlock(azx_dev); - return azx_dev; - } - } - dsp_unlock(azx_dev); - } - if (res) { - dsp_lock(res); - res->opened = 1; - res->assigned_key = key; - dsp_unlock(res); - } - return res; -} - -/* release the assigned stream */ -static inline void azx_release_device(struct azx_dev *azx_dev) +/* called from IRQ */ +static int azx_position_check(struct azx *chip, struct azx_dev *azx_dev) { - azx_dev->opened = 0; -} - -static cycle_t azx_cc_read(const struct cyclecounter *cc) -{ - struct azx_dev *azx_dev = container_of(cc, struct azx_dev, azx_cc); - struct snd_pcm_substream *substream = azx_dev->substream; - struct azx_pcm *apcm = snd_pcm_substream_chip(substream); - struct azx *chip = apcm->chip; - - return azx_readl(chip, WALLCLK); -} - -static void azx_timecounter_init(struct snd_pcm_substream *substream, - bool force, cycle_t last) -{ - struct azx_dev *azx_dev = get_azx_dev(substream); - struct timecounter *tc = &azx_dev->azx_tc; - struct cyclecounter *cc = &azx_dev->azx_cc; - u64 nsec; - - cc->read = azx_cc_read; - cc->mask = CLOCKSOURCE_MASK(32); - - /* - * Converting from 24 MHz to ns means applying a 125/3 factor. - * To avoid any saturation issues in intermediate operations, - * the 125 factor is applied first. The division is applied - * last after reading the timecounter value. - * Applying the 1/3 factor as part of the multiplication - * requires at least 20 bits for a decent precision, however - * overflows occur after about 4 hours or less, not a option. - */ - - cc->mult = 125; /* saturation after 195 years */ - cc->shift = 0; - - nsec = 0; /* audio time is elapsed time since trigger */ - timecounter_init(tc, cc, nsec); - if (force) - /* - * force timecounter to use predefined value, - * used for synchronized starts - */ - tc->cycle_last = last; -} - -static u64 azx_adjust_codec_delay(struct snd_pcm_substream *substream, - u64 nsec) -{ - struct azx_pcm *apcm = snd_pcm_substream_chip(substream); - struct hda_pcm_stream *hinfo = apcm->hinfo[substream->stream]; - u64 codec_frames, codec_nsecs; - - if (!hinfo->ops.get_delay) - return nsec; - - codec_frames = hinfo->ops.get_delay(hinfo, apcm->codec, substream); - codec_nsecs = div_u64(codec_frames * 1000000000LL, - substream->runtime->rate); - - if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) - return nsec + codec_nsecs; - - return (nsec > codec_nsecs) ? nsec - codec_nsecs : 0; -} - -static int azx_get_wallclock_tstamp(struct snd_pcm_substream *substream, - struct timespec *ts) -{ - struct azx_dev *azx_dev = get_azx_dev(substream); - u64 nsec; - - nsec = timecounter_read(&azx_dev->azx_tc); - nsec = div_u64(nsec, 3); /* can be optimized */ - nsec = azx_adjust_codec_delay(substream, nsec); - - *ts = ns_to_timespec(nsec); - - return 0; -} - -static struct snd_pcm_hardware azx_pcm_hw = { - .info = (SNDRV_PCM_INFO_MMAP | - SNDRV_PCM_INFO_INTERLEAVED | - SNDRV_PCM_INFO_BLOCK_TRANSFER | - SNDRV_PCM_INFO_MMAP_VALID | - /* No full-resume yet implemented */ - /* SNDRV_PCM_INFO_RESUME |*/ - SNDRV_PCM_INFO_PAUSE | - SNDRV_PCM_INFO_SYNC_START | - SNDRV_PCM_INFO_HAS_WALL_CLOCK | - SNDRV_PCM_INFO_NO_PERIOD_WAKEUP), - .formats = SNDRV_PCM_FMTBIT_S16_LE, - .rates = SNDRV_PCM_RATE_48000, - .rate_min = 48000, - .rate_max = 48000, - .channels_min = 2, - .channels_max = 2, - .buffer_bytes_max = AZX_MAX_BUF_SIZE, - .period_bytes_min = 128, - .period_bytes_max = AZX_MAX_BUF_SIZE / 2, - .periods_min = 2, - .periods_max = AZX_MAX_FRAG, - .fifo_size = 0, -}; - -static int azx_pcm_open(struct snd_pcm_substream *substream) -{ - struct azx_pcm *apcm = snd_pcm_substream_chip(substream); - struct hda_pcm_stream *hinfo = apcm->hinfo[substream->stream]; - struct azx *chip = apcm->chip; - struct azx_dev *azx_dev; - struct snd_pcm_runtime *runtime = substream->runtime; - unsigned long flags; - int err; - int buff_step; + int ok; - mutex_lock(&chip->open_mutex); - azx_dev = azx_assign_device(chip, substream); - if (azx_dev == NULL) { - mutex_unlock(&chip->open_mutex); - return -EBUSY; - } - runtime->hw = azx_pcm_hw; - runtime->hw.channels_min = hinfo->channels_min; - runtime->hw.channels_max = hinfo->channels_max; - runtime->hw.formats = hinfo->formats; - runtime->hw.rates = hinfo->rates; - snd_pcm_limit_hw_rates(runtime); - snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS); - - /* avoid wrap-around with wall-clock */ - snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_BUFFER_TIME, - 20, - 178000000); - - if (chip->align_buffer_size) - /* constrain buffer sizes to be multiple of 128 - bytes. This is more efficient in terms of memory - access but isn't required by the HDA spec and - prevents users from specifying exact period/buffer - sizes. For example for 44.1kHz, a period size set - to 20ms will be rounded to 19.59ms. */ - buff_step = 128; - else - /* Don't enforce steps on buffer sizes, still need to - be multiple of 4 bytes (HDA spec). Tested on Intel - HDA controllers, may not work on all devices where - option needs to be disabled */ - buff_step = 4; - - snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_BUFFER_BYTES, - buff_step); - snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_BYTES, - buff_step); - snd_hda_power_up_d3wait(apcm->codec); - err = hinfo->ops.open(hinfo, apcm->codec, substream); - if (err < 0) { - azx_release_device(azx_dev); - snd_hda_power_down(apcm->codec); - mutex_unlock(&chip->open_mutex); - return err; + ok = azx_position_ok(chip, azx_dev); + if (ok == 1) { + azx_dev->irq_pending = 0; + return ok; + } else if (ok == 0 && chip->bus && chip->bus->workq) { + /* bogus IRQ, process it later */ + azx_dev->irq_pending = 1; + queue_work(chip->bus->workq, &chip->irq_pending_work); } - snd_pcm_limit_hw_rates(runtime); - /* sanity check */ - if (snd_BUG_ON(!runtime->hw.channels_min) || - snd_BUG_ON(!runtime->hw.channels_max) || - snd_BUG_ON(!runtime->hw.formats) || - snd_BUG_ON(!runtime->hw.rates)) { - azx_release_device(azx_dev); - hinfo->ops.close(hinfo, apcm->codec, substream); - snd_hda_power_down(apcm->codec); - mutex_unlock(&chip->open_mutex); - return -EINVAL; - } - - /* disable WALLCLOCK timestamps for capture streams - until we figure out how to handle digital inputs */ - if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) - runtime->hw.info &= ~SNDRV_PCM_INFO_HAS_WALL_CLOCK; - - spin_lock_irqsave(&chip->reg_lock, flags); - azx_dev->substream = substream; - azx_dev->running = 0; - spin_unlock_irqrestore(&chip->reg_lock, flags); - - runtime->private_data = azx_dev; - snd_pcm_set_sync(substream); - mutex_unlock(&chip->open_mutex); return 0; } -static int azx_pcm_close(struct snd_pcm_substream *substream) -{ - struct azx_pcm *apcm = snd_pcm_substream_chip(substream); - struct hda_pcm_stream *hinfo = apcm->hinfo[substream->stream]; - struct azx *chip = apcm->chip; - struct azx_dev *azx_dev = get_azx_dev(substream); - unsigned long flags; - - mutex_lock(&chip->open_mutex); - spin_lock_irqsave(&chip->reg_lock, flags); - azx_dev->substream = NULL; - azx_dev->running = 0; - spin_unlock_irqrestore(&chip->reg_lock, flags); - azx_release_device(azx_dev); - hinfo->ops.close(hinfo, apcm->codec, substream); - snd_hda_power_down(apcm->codec); - mutex_unlock(&chip->open_mutex); - return 0; -} - -static int azx_pcm_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *hw_params) -{ - struct azx_pcm *apcm = snd_pcm_substream_chip(substream); - struct azx *chip = apcm->chip; - struct azx_dev *azx_dev = get_azx_dev(substream); - int ret; - - dsp_lock(azx_dev); - if (dsp_is_locked(azx_dev)) { - ret = -EBUSY; - goto unlock; - } - - mark_runtime_wc(chip, azx_dev, substream, false); - azx_dev->bufsize = 0; - azx_dev->period_bytes = 0; - azx_dev->format_val = 0; - ret = snd_pcm_lib_malloc_pages(substream, - params_buffer_bytes(hw_params)); - if (ret < 0) - goto unlock; - mark_runtime_wc(chip, azx_dev, substream, true); - unlock: - dsp_unlock(azx_dev); - return ret; -} - -static int azx_pcm_hw_free(struct snd_pcm_substream *substream) -{ - struct azx_pcm *apcm = snd_pcm_substream_chip(substream); - struct azx_dev *azx_dev = get_azx_dev(substream); - struct azx *chip = apcm->chip; - struct hda_pcm_stream *hinfo = apcm->hinfo[substream->stream]; - - /* reset BDL address */ - dsp_lock(azx_dev); - if (!dsp_is_locked(azx_dev)) { - azx_sd_writel(azx_dev, SD_BDLPL, 0); - azx_sd_writel(azx_dev, SD_BDLPU, 0); - azx_sd_writel(azx_dev, SD_CTL, 0); - azx_dev->bufsize = 0; - azx_dev->period_bytes = 0; - azx_dev->format_val = 0; - } - - snd_hda_codec_cleanup(apcm->codec, hinfo, substream); - - mark_runtime_wc(chip, azx_dev, substream, false); - azx_dev->prepared = 0; - dsp_unlock(azx_dev); - return snd_pcm_lib_free_pages(substream); -} - -static int azx_pcm_prepare(struct snd_pcm_substream *substream) -{ - struct azx_pcm *apcm = snd_pcm_substream_chip(substream); - struct azx *chip = apcm->chip; - struct azx_dev *azx_dev = get_azx_dev(substream); - struct hda_pcm_stream *hinfo = apcm->hinfo[substream->stream]; - struct snd_pcm_runtime *runtime = substream->runtime; - unsigned int bufsize, period_bytes, format_val, stream_tag; - int err; - struct hda_spdif_out *spdif = - snd_hda_spdif_out_of_nid(apcm->codec, hinfo->nid); - unsigned short ctls = spdif ? spdif->ctls : 0; - - dsp_lock(azx_dev); - if (dsp_is_locked(azx_dev)) { - err = -EBUSY; - goto unlock; - } - - azx_stream_reset(chip, azx_dev); - format_val = snd_hda_calc_stream_format(runtime->rate, - runtime->channels, - runtime->format, - hinfo->maxbps, - ctls); - if (!format_val) { - snd_printk(KERN_ERR SFX - "%s: invalid format_val, rate=%d, ch=%d, format=%d\n", - pci_name(chip->pci), runtime->rate, runtime->channels, runtime->format); - err = -EINVAL; - goto unlock; - } - - bufsize = snd_pcm_lib_buffer_bytes(substream); - period_bytes = snd_pcm_lib_period_bytes(substream); - - snd_printdd(SFX "%s: azx_pcm_prepare: bufsize=0x%x, format=0x%x\n", - pci_name(chip->pci), bufsize, format_val); - - if (bufsize != azx_dev->bufsize || - period_bytes != azx_dev->period_bytes || - format_val != azx_dev->format_val || - runtime->no_period_wakeup != azx_dev->no_period_wakeup) { - azx_dev->bufsize = bufsize; - azx_dev->period_bytes = period_bytes; - azx_dev->format_val = format_val; - azx_dev->no_period_wakeup = runtime->no_period_wakeup; - err = azx_setup_periods(chip, substream, azx_dev); - if (err < 0) - goto unlock; - } - - /* when LPIB delay correction gives a small negative value, - * we ignore it; currently set the threshold statically to - * 64 frames - */ - if (runtime->period_size > 64) - azx_dev->delay_negative_threshold = -frames_to_bytes(runtime, 64); - else - azx_dev->delay_negative_threshold = 0; - - /* wallclk has 24Mhz clock source */ - azx_dev->period_wallclk = (((runtime->period_size * 24000) / - runtime->rate) * 1000); - azx_setup_controller(chip, azx_dev); - if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) - azx_dev->fifo_size = azx_sd_readw(azx_dev, SD_FIFOSIZE) + 1; - else - azx_dev->fifo_size = 0; - - stream_tag = azx_dev->stream_tag; - /* CA-IBG chips need the playback stream starting from 1 */ - if ((chip->driver_caps & AZX_DCAPS_CTX_WORKAROUND) && - stream_tag > chip->capture_streams) - stream_tag -= chip->capture_streams; - err = snd_hda_codec_prepare(apcm->codec, hinfo, stream_tag, - azx_dev->format_val, substream); - - unlock: - if (!err) - azx_dev->prepared = 1; - dsp_unlock(azx_dev); - return err; -} - -static int azx_pcm_trigger(struct snd_pcm_substream *substream, int cmd) -{ - struct azx_pcm *apcm = snd_pcm_substream_chip(substream); - struct azx *chip = apcm->chip; - struct azx_dev *azx_dev; - struct snd_pcm_substream *s; - int rstart = 0, start, nsync = 0, sbits = 0; - int nwait, timeout; - - azx_dev = get_azx_dev(substream); - trace_azx_pcm_trigger(chip, azx_dev, cmd); - - if (dsp_is_locked(azx_dev) || !azx_dev->prepared) - return -EPIPE; - - switch (cmd) { - case SNDRV_PCM_TRIGGER_START: - rstart = 1; - case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: - case SNDRV_PCM_TRIGGER_RESUME: - start = 1; - break; - case SNDRV_PCM_TRIGGER_PAUSE_PUSH: - case SNDRV_PCM_TRIGGER_SUSPEND: - case SNDRV_PCM_TRIGGER_STOP: - start = 0; - break; - default: - return -EINVAL; - } - - snd_pcm_group_for_each_entry(s, substream) { - if (s->pcm->card != substream->pcm->card) - continue; - azx_dev = get_azx_dev(s); - sbits |= 1 << azx_dev->index; - nsync++; - snd_pcm_trigger_done(s, substream); - } - - spin_lock(&chip->reg_lock); - - /* first, set SYNC bits of corresponding streams */ - if (chip->driver_caps & AZX_DCAPS_OLD_SSYNC) - azx_writel(chip, OLD_SSYNC, - azx_readl(chip, OLD_SSYNC) | sbits); - else - azx_writel(chip, SSYNC, azx_readl(chip, SSYNC) | sbits); - - snd_pcm_group_for_each_entry(s, substream) { - if (s->pcm->card != substream->pcm->card) - continue; - azx_dev = get_azx_dev(s); - if (start) { - azx_dev->start_wallclk = azx_readl(chip, WALLCLK); - if (!rstart) - azx_dev->start_wallclk -= - azx_dev->period_wallclk; - azx_stream_start(chip, azx_dev); - } else { - azx_stream_stop(chip, azx_dev); - } - azx_dev->running = start; - } - spin_unlock(&chip->reg_lock); - if (start) { - /* wait until all FIFOs get ready */ - for (timeout = 5000; timeout; timeout--) { - nwait = 0; - snd_pcm_group_for_each_entry(s, substream) { - if (s->pcm->card != substream->pcm->card) - continue; - azx_dev = get_azx_dev(s); - if (!(azx_sd_readb(azx_dev, SD_STS) & - SD_STS_FIFO_READY)) - nwait++; - } - if (!nwait) - break; - cpu_relax(); - } - } else { - /* wait until all RUN bits are cleared */ - for (timeout = 5000; timeout; timeout--) { - nwait = 0; - snd_pcm_group_for_each_entry(s, substream) { - if (s->pcm->card != substream->pcm->card) - continue; - azx_dev = get_azx_dev(s); - if (azx_sd_readb(azx_dev, SD_CTL) & - SD_CTL_DMA_START) - nwait++; - } - if (!nwait) - break; - cpu_relax(); - } - } - spin_lock(&chip->reg_lock); - /* reset SYNC bits */ - if (chip->driver_caps & AZX_DCAPS_OLD_SSYNC) - azx_writel(chip, OLD_SSYNC, - azx_readl(chip, OLD_SSYNC) & ~sbits); - else - azx_writel(chip, SSYNC, azx_readl(chip, SSYNC) & ~sbits); - if (start) { - azx_timecounter_init(substream, 0, 0); - if (nsync > 1) { - cycle_t cycle_last; - - /* same start cycle for master and group */ - azx_dev = get_azx_dev(substream); - cycle_last = azx_dev->azx_tc.cycle_last; - - snd_pcm_group_for_each_entry(s, substream) { - if (s->pcm->card != substream->pcm->card) - continue; - azx_timecounter_init(s, 1, cycle_last); - } - } - } - spin_unlock(&chip->reg_lock); - return 0; -} - -/* get the current DMA position with correction on VIA chips */ -static unsigned int azx_via_get_position(struct azx *chip, - struct azx_dev *azx_dev) -{ - unsigned int link_pos, mini_pos, bound_pos; - unsigned int mod_link_pos, mod_dma_pos, mod_mini_pos; - unsigned int fifo_size; - - link_pos = azx_sd_readl(azx_dev, SD_LPIB); - if (azx_dev->substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { - /* Playback, no problem using link position */ - return link_pos; - } - - /* Capture */ - /* For new chipset, - * use mod to get the DMA position just like old chipset - */ - mod_dma_pos = le32_to_cpu(*azx_dev->posbuf); - mod_dma_pos %= azx_dev->period_bytes; - - /* azx_dev->fifo_size can't get FIFO size of in stream. - * Get from base address + offset. - */ - fifo_size = readw(chip->remap_addr + VIA_IN_STREAM0_FIFO_SIZE_OFFSET); - - if (azx_dev->insufficient) { - /* Link position never gather than FIFO size */ - if (link_pos <= fifo_size) - return 0; - - azx_dev->insufficient = 0; - } - - if (link_pos <= fifo_size) - mini_pos = azx_dev->bufsize + link_pos - fifo_size; - else - mini_pos = link_pos - fifo_size; - - /* Find nearest previous boudary */ - mod_mini_pos = mini_pos % azx_dev->period_bytes; - mod_link_pos = link_pos % azx_dev->period_bytes; - if (mod_link_pos >= fifo_size) - bound_pos = link_pos - mod_link_pos; - else if (mod_dma_pos >= mod_mini_pos) - bound_pos = mini_pos - mod_mini_pos; - else { - bound_pos = mini_pos - mod_mini_pos + azx_dev->period_bytes; - if (bound_pos >= azx_dev->bufsize) - bound_pos = 0; - } - - /* Calculate real DMA position we want */ - return bound_pos + mod_dma_pos; -} - -static unsigned int azx_get_position(struct azx *chip, - struct azx_dev *azx_dev, - bool with_check) -{ - struct snd_pcm_substream *substream = azx_dev->substream; - struct azx_pcm *apcm = snd_pcm_substream_chip(substream); - unsigned int pos; - int stream = substream->stream; - struct hda_pcm_stream *hinfo = apcm->hinfo[stream]; - int delay = 0; - - switch (chip->position_fix[stream]) { - case POS_FIX_LPIB: - /* read LPIB */ - pos = azx_sd_readl(azx_dev, SD_LPIB); - break; - case POS_FIX_VIACOMBO: - pos = azx_via_get_position(chip, azx_dev); - break; - default: - /* use the position buffer */ - pos = le32_to_cpu(*azx_dev->posbuf); - if (with_check && chip->position_fix[stream] == POS_FIX_AUTO) { - if (!pos || pos == (u32)-1) { - printk(KERN_WARNING - "hda-intel: Invalid position buffer, " - "using LPIB read method instead.\n"); - chip->position_fix[stream] = POS_FIX_LPIB; - pos = azx_sd_readl(azx_dev, SD_LPIB); - } else - chip->position_fix[stream] = POS_FIX_POSBUF; - } - break; - } - - if (pos >= azx_dev->bufsize) - pos = 0; - - /* calculate runtime delay from LPIB */ - if (substream->runtime && - chip->position_fix[stream] == POS_FIX_POSBUF && - (chip->driver_caps & AZX_DCAPS_COUNT_LPIB_DELAY)) { - unsigned int lpib_pos = azx_sd_readl(azx_dev, SD_LPIB); - if (stream == SNDRV_PCM_STREAM_PLAYBACK) - delay = pos - lpib_pos; - else - delay = lpib_pos - pos; - if (delay < 0) { - if (delay >= azx_dev->delay_negative_threshold) - delay = 0; - else - delay += azx_dev->bufsize; - } - if (delay >= azx_dev->period_bytes) { - snd_printk(KERN_WARNING SFX - "%s: Unstable LPIB (%d >= %d); " - "disabling LPIB delay counting\n", - pci_name(chip->pci), delay, azx_dev->period_bytes); - delay = 0; - chip->driver_caps &= ~AZX_DCAPS_COUNT_LPIB_DELAY; - } - delay = bytes_to_frames(substream->runtime, delay); - } - - if (substream->runtime) { - if (hinfo->ops.get_delay) - delay += hinfo->ops.get_delay(hinfo, apcm->codec, - substream); - substream->runtime->delay = delay; - } - - trace_azx_get_position(chip, azx_dev, pos, delay); - return pos; -} - -static snd_pcm_uframes_t azx_pcm_pointer(struct snd_pcm_substream *substream) -{ - struct azx_pcm *apcm = snd_pcm_substream_chip(substream); - struct azx *chip = apcm->chip; - struct azx_dev *azx_dev = get_azx_dev(substream); - return bytes_to_frames(substream->runtime, - azx_get_position(chip, azx_dev, false)); -} - /* * Check whether the current DMA position is acceptable for updating * periods. Returns non-zero if it's OK. @@ -2521,7 +454,7 @@ static int azx_position_ok(struct azx *chip, struct azx_dev *azx_dev) if (wallclk < (azx_dev->period_wallclk * 5) / 4 && pos % azx_dev->period_bytes > azx_dev->period_bytes / 2) /* NG - it's below the first next period boundary */ - return bdl_pos_adj[chip->dev_index] ? 0 : -1; + return chip->bdl_pos_adj[chip->dev_index] ? 0 : -1; azx_dev->start_wallclk += wallclk; return 1; /* OK, it's fine */ } @@ -2535,10 +468,9 @@ static void azx_irq_pending_work(struct work_struct *work) int i, pending, ok; if (!chip->irq_pending_warned) { - printk(KERN_WARNING - "hda-intel: IRQ timing workaround is activated " - "for card #%d. Suggest a bigger bdl_pos_adj.\n", - chip->card->number); + dev_info(chip->card->dev, + "IRQ timing workaround is activated for card #%d. Suggest a bigger bdl_pos_adj.\n", + chip->card->number); chip->irq_pending_warned = 1; } @@ -2580,139 +512,14 @@ static void azx_clear_irq_pending(struct azx *chip) spin_unlock_irq(&chip->reg_lock); } -#ifdef CONFIG_X86 -static int azx_pcm_mmap(struct snd_pcm_substream *substream, - struct vm_area_struct *area) -{ - struct azx_pcm *apcm = snd_pcm_substream_chip(substream); - struct azx *chip = apcm->chip; - if (!azx_snoop(chip)) - area->vm_page_prot = pgprot_writecombine(area->vm_page_prot); - return snd_pcm_lib_default_mmap(substream, area); -} -#else -#define azx_pcm_mmap NULL -#endif - -static struct snd_pcm_ops azx_pcm_ops = { - .open = azx_pcm_open, - .close = azx_pcm_close, - .ioctl = snd_pcm_lib_ioctl, - .hw_params = azx_pcm_hw_params, - .hw_free = azx_pcm_hw_free, - .prepare = azx_pcm_prepare, - .trigger = azx_pcm_trigger, - .pointer = azx_pcm_pointer, - .wall_clock = azx_get_wallclock_tstamp, - .mmap = azx_pcm_mmap, - .page = snd_pcm_sgbuf_ops_page, -}; - -static void azx_pcm_free(struct snd_pcm *pcm) -{ - struct azx_pcm *apcm = pcm->private_data; - if (apcm) { - list_del(&apcm->list); - kfree(apcm); - } -} - -#define MAX_PREALLOC_SIZE (32 * 1024 * 1024) - -static int -azx_attach_pcm_stream(struct hda_bus *bus, struct hda_codec *codec, - struct hda_pcm *cpcm) -{ - struct azx *chip = bus->private_data; - struct snd_pcm *pcm; - struct azx_pcm *apcm; - int pcm_dev = cpcm->device; - unsigned int size; - int s, err; - - list_for_each_entry(apcm, &chip->pcm_list, list) { - if (apcm->pcm->device == pcm_dev) { - snd_printk(KERN_ERR SFX "%s: PCM %d already exists\n", - pci_name(chip->pci), pcm_dev); - return -EBUSY; - } - } - err = snd_pcm_new(chip->card, cpcm->name, pcm_dev, - cpcm->stream[SNDRV_PCM_STREAM_PLAYBACK].substreams, - cpcm->stream[SNDRV_PCM_STREAM_CAPTURE].substreams, - &pcm); - if (err < 0) - return err; - strlcpy(pcm->name, cpcm->name, sizeof(pcm->name)); - apcm = kzalloc(sizeof(*apcm), GFP_KERNEL); - if (apcm == NULL) - return -ENOMEM; - apcm->chip = chip; - apcm->pcm = pcm; - apcm->codec = codec; - pcm->private_data = apcm; - pcm->private_free = azx_pcm_free; - if (cpcm->pcm_type == HDA_PCM_TYPE_MODEM) - pcm->dev_class = SNDRV_PCM_CLASS_MODEM; - list_add_tail(&apcm->list, &chip->pcm_list); - cpcm->pcm = pcm; - for (s = 0; s < 2; s++) { - apcm->hinfo[s] = &cpcm->stream[s]; - if (cpcm->stream[s].substreams) - snd_pcm_set_ops(pcm, s, &azx_pcm_ops); - } - /* buffer pre-allocation */ - size = CONFIG_SND_HDA_PREALLOC_SIZE * 1024; - if (size > MAX_PREALLOC_SIZE) - size = MAX_PREALLOC_SIZE; - snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV_SG, - snd_dma_pci_data(chip->pci), - size, MAX_PREALLOC_SIZE); - return 0; -} - -/* - * mixer creation - all stuff is implemented in hda module - */ -static int azx_mixer_create(struct azx *chip) -{ - return snd_hda_build_controls(chip->bus); -} - - -/* - * initialize SD streams - */ -static int azx_init_stream(struct azx *chip) -{ - int i; - - /* initialize each stream (aka device) - * assign the starting bdl address to each stream (device) - * and initialize - */ - for (i = 0; i < chip->num_streams; i++) { - struct azx_dev *azx_dev = &chip->azx_dev[i]; - azx_dev->posbuf = (u32 __iomem *)(chip->posbuf.area + i * 8); - /* offset: SDI0=0x80, SDI1=0xa0, ... SDO3=0x160 */ - azx_dev->sd_addr = chip->remap_addr + (0x20 * i + 0x80); - /* int mask: SDI0=0x01, SDI1=0x02, ... SDO3=0x80 */ - azx_dev->sd_int_sta_mask = 1 << i; - /* stream tag: must be non-zero and unique */ - azx_dev->index = i; - azx_dev->stream_tag = i + 1; - } - - return 0; -} - static int azx_acquire_irq(struct azx *chip, int do_disconnect) { if (request_irq(chip->pci->irq, azx_interrupt, chip->msi ? 0 : IRQF_SHARED, KBUILD_MODNAME, chip)) { - printk(KERN_ERR "hda-intel: unable to grab IRQ %d, " - "disabling device\n", chip->pci->irq); + dev_err(chip->card->dev, + "unable to grab IRQ %d, disabling device\n", + chip->pci->irq); if (do_disconnect) snd_card_disconnect(chip->card); return -1; @@ -2722,160 +529,7 @@ static int azx_acquire_irq(struct azx *chip, int do_disconnect) return 0; } - -static void azx_stop_chip(struct azx *chip) -{ - if (!chip->initialized) - return; - - /* disable interrupts */ - azx_int_disable(chip); - azx_int_clear(chip); - - /* disable CORB/RIRB */ - azx_free_cmd_io(chip); - - /* disable position buffer */ - azx_writel(chip, DPLBASE, 0); - azx_writel(chip, DPUBASE, 0); - - chip->initialized = 0; -} - -#ifdef CONFIG_SND_HDA_DSP_LOADER -/* - * DSP loading code (e.g. for CA0132) - */ - -/* use the first stream for loading DSP */ -static struct azx_dev * -azx_get_dsp_loader_dev(struct azx *chip) -{ - return &chip->azx_dev[chip->playback_index_offset]; -} - -static int azx_load_dsp_prepare(struct hda_bus *bus, unsigned int format, - unsigned int byte_size, - struct snd_dma_buffer *bufp) -{ - u32 *bdl; - struct azx *chip = bus->private_data; - struct azx_dev *azx_dev; - int err; - - azx_dev = azx_get_dsp_loader_dev(chip); - - dsp_lock(azx_dev); - spin_lock_irq(&chip->reg_lock); - if (azx_dev->running || azx_dev->locked) { - spin_unlock_irq(&chip->reg_lock); - err = -EBUSY; - goto unlock; - } - azx_dev->prepared = 0; - chip->saved_azx_dev = *azx_dev; - azx_dev->locked = 1; - spin_unlock_irq(&chip->reg_lock); - - err = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV_SG, - snd_dma_pci_data(chip->pci), - byte_size, bufp); - if (err < 0) - goto err_alloc; - - mark_pages_wc(chip, bufp, true); - azx_dev->bufsize = byte_size; - azx_dev->period_bytes = byte_size; - azx_dev->format_val = format; - - azx_stream_reset(chip, azx_dev); - - /* reset BDL address */ - azx_sd_writel(azx_dev, SD_BDLPL, 0); - azx_sd_writel(azx_dev, SD_BDLPU, 0); - - azx_dev->frags = 0; - bdl = (u32 *)azx_dev->bdl.area; - err = setup_bdle(chip, bufp, azx_dev, &bdl, 0, byte_size, 0); - if (err < 0) - goto error; - - azx_setup_controller(chip, azx_dev); - dsp_unlock(azx_dev); - return azx_dev->stream_tag; - - error: - mark_pages_wc(chip, bufp, false); - snd_dma_free_pages(bufp); - err_alloc: - spin_lock_irq(&chip->reg_lock); - if (azx_dev->opened) - *azx_dev = chip->saved_azx_dev; - azx_dev->locked = 0; - spin_unlock_irq(&chip->reg_lock); - unlock: - dsp_unlock(azx_dev); - return err; -} - -static void azx_load_dsp_trigger(struct hda_bus *bus, bool start) -{ - struct azx *chip = bus->private_data; - struct azx_dev *azx_dev = azx_get_dsp_loader_dev(chip); - - if (start) - azx_stream_start(chip, azx_dev); - else - azx_stream_stop(chip, azx_dev); - azx_dev->running = start; -} - -static void azx_load_dsp_cleanup(struct hda_bus *bus, - struct snd_dma_buffer *dmab) -{ - struct azx *chip = bus->private_data; - struct azx_dev *azx_dev = azx_get_dsp_loader_dev(chip); - - if (!dmab->area || !azx_dev->locked) - return; - - dsp_lock(azx_dev); - /* reset BDL address */ - azx_sd_writel(azx_dev, SD_BDLPL, 0); - azx_sd_writel(azx_dev, SD_BDLPU, 0); - azx_sd_writel(azx_dev, SD_CTL, 0); - azx_dev->bufsize = 0; - azx_dev->period_bytes = 0; - azx_dev->format_val = 0; - - mark_pages_wc(chip, dmab, false); - snd_dma_free_pages(dmab); - dmab->area = NULL; - - spin_lock_irq(&chip->reg_lock); - if (azx_dev->opened) - *azx_dev = chip->saved_azx_dev; - azx_dev->locked = 0; - spin_unlock_irq(&chip->reg_lock); - dsp_unlock(azx_dev); -} -#endif /* CONFIG_SND_HDA_DSP_LOADER */ - #ifdef CONFIG_PM -/* power-up/down the controller */ -static void azx_power_notify(struct hda_bus *bus, bool power_up) -{ - struct azx *chip = bus->private_data; - - if (!(chip->driver_caps & AZX_DCAPS_PM_RUNTIME)) - return; - - if (power_up) - pm_runtime_get_sync(&chip->pci->dev); - else - pm_runtime_put_sync(&chip->pci->dev); -} - static DEFINE_MUTEX(card_list_lock); static LIST_HEAD(card_list); @@ -2969,8 +623,8 @@ static int azx_resume(struct device *dev) pci_set_power_state(pci, PCI_D0); pci_restore_state(pci); if (pci_enable_device(pci) < 0) { - printk(KERN_ERR "hda-intel: pci_enable_device failed, " - "disabling device\n"); + dev_err(chip->card->dev, + "pci_enable_device failed, disabling device\n"); snd_card_disconnect(card); return -EIO; } @@ -3127,36 +781,32 @@ static void azx_vs_set_state(struct pci_dev *pci, if (!chip->bus) { chip->disabled = disabled; if (!disabled) { - snd_printk(KERN_INFO SFX - "%s: Start delayed initialization\n", - pci_name(chip->pci)); + dev_info(chip->card->dev, + "Start delayed initialization\n"); if (azx_probe_continue(chip) < 0) { - snd_printk(KERN_ERR SFX - "%s: initialization error\n", - pci_name(chip->pci)); + dev_err(chip->card->dev, "initialization error\n"); chip->init_failed = true; } } } else { - snd_printk(KERN_INFO SFX - "%s: %s via VGA-switcheroo\n", pci_name(chip->pci), - disabled ? "Disabling" : "Enabling"); + dev_info(chip->card->dev, "%s via VGA-switcheroo\n", + disabled ? "Disabling" : "Enabling"); if (disabled) { - pm_runtime_put_sync_suspend(&pci->dev); - azx_suspend(&pci->dev); + pm_runtime_put_sync_suspend(card->dev); + azx_suspend(card->dev); /* when we get suspended by vga switcheroo we end up in D3cold, * however we have no ACPI handle, so pci/acpi can't put us there, * put ourselves there */ pci->current_state = PCI_D3cold; chip->disabled = true; if (snd_hda_lock_devices(chip->bus)) - snd_printk(KERN_WARNING SFX "%s: Cannot lock devices!\n", - pci_name(chip->pci)); + dev_warn(chip->card->dev, + "Cannot lock devices!\n"); } else { snd_hda_unlock_devices(chip->bus); - pm_runtime_get_noresume(&pci->dev); + pm_runtime_get_noresume(card->dev); chip->disabled = false; - azx_resume(&pci->dev); + azx_resume(card->dev); } } } @@ -3181,9 +831,8 @@ static void init_vga_switcheroo(struct azx *chip) { struct pci_dev *p = get_bound_vga(chip->pci); if (p) { - snd_printk(KERN_INFO SFX - "%s: Handle VGA-switcheroo audio client\n", - pci_name(chip->pci)); + dev_info(chip->card->dev, + "Handle VGA-switcheroo audio client\n"); chip->use_vga_switcheroo = 1; pci_dev_put(p); } @@ -3211,7 +860,8 @@ static int register_vga_switcheroo(struct azx *chip) chip->vga_switcheroo_registered = 1; /* register as an optimus hdmi audio power domain */ - vga_switcheroo_init_domain_pm_optimus_hdmi_audio(&chip->pci->dev, &chip->hdmi_pm_domain); + vga_switcheroo_init_domain_pm_optimus_hdmi_audio(chip->card->dev, + &chip->hdmi_pm_domain); return 0; } #else @@ -3260,21 +910,7 @@ static int azx_free(struct azx *chip) if (chip->remap_addr) iounmap(chip->remap_addr); - if (chip->azx_dev) { - for (i = 0; i < chip->num_streams; i++) - if (chip->azx_dev[i].bdl.area) { - mark_pages_wc(chip, &chip->azx_dev[i].bdl, false); - snd_dma_free_pages(&chip->azx_dev[i].bdl); - } - } - if (chip->rb.area) { - mark_pages_wc(chip, &chip->rb, false); - snd_dma_free_pages(&chip->rb); - } - if (chip->posbuf.area) { - mark_pages_wc(chip, &chip->posbuf, false); - snd_dma_free_pages(&chip->posbuf); - } + azx_free_stream_pages(chip); if (chip->region_requested) pci_release_regions(chip->pci); pci_disable_device(chip->pci); @@ -3374,20 +1010,19 @@ static int check_position_fix(struct azx *chip, int fix) q = snd_pci_quirk_lookup(chip->pci, position_fix_list); if (q) { - printk(KERN_INFO - "hda_intel: position_fix set to %d " - "for device %04x:%04x\n", - q->value, q->subvendor, q->subdevice); + dev_info(chip->card->dev, + "position_fix set to %d for device %04x:%04x\n", + q->value, q->subvendor, q->subdevice); return q->value; } /* Check VIA/ATI HD Audio Controller exist */ if (chip->driver_caps & AZX_DCAPS_POSFIX_VIA) { - snd_printd(SFX "%s: Using VIACOMBO position fix\n", pci_name(chip->pci)); + dev_dbg(chip->card->dev, "Using VIACOMBO position fix\n"); return POS_FIX_VIACOMBO; } if (chip->driver_caps & AZX_DCAPS_POSFIX_LPIB) { - snd_printd(SFX "%s: Using LPIB position fix\n", pci_name(chip->pci)); + dev_dbg(chip->card->dev, "Using LPIB position fix\n"); return POS_FIX_LPIB; } return POS_FIX_AUTO; @@ -3425,10 +1060,9 @@ static void check_probe_mask(struct azx *chip, int dev) if (chip->codec_probe_mask == -1) { q = snd_pci_quirk_lookup(chip->pci, probe_mask_list); if (q) { - printk(KERN_INFO - "hda_intel: probe_mask set to 0x%x " - "for device %04x:%04x\n", - q->value, q->subvendor, q->subdevice); + dev_info(chip->card->dev, + "probe_mask set to 0x%x for device %04x:%04x\n", + q->value, q->subvendor, q->subdevice); chip->codec_probe_mask = q->value; } } @@ -3437,8 +1071,8 @@ static void check_probe_mask(struct azx *chip, int dev) if (chip->codec_probe_mask != -1 && (chip->codec_probe_mask & AZX_FORCE_CODEC_MASK)) { chip->codec_mask = chip->codec_probe_mask & 0xff; - printk(KERN_INFO "hda_intel: codec_mask forced to 0x%x\n", - chip->codec_mask); + dev_info(chip->card->dev, "codec_mask forced to 0x%x\n", + chip->codec_mask); } } @@ -3470,16 +1104,16 @@ static void check_msi(struct azx *chip) chip->msi = 1; /* enable MSI as default */ q = snd_pci_quirk_lookup(chip->pci, msi_black_list); if (q) { - printk(KERN_INFO - "hda_intel: msi for device %04x:%04x set to %d\n", - q->subvendor, q->subdevice, q->value); + dev_info(chip->card->dev, + "msi for device %04x:%04x set to %d\n", + q->subvendor, q->subdevice, q->value); chip->msi = q->value; return; } /* NVidia chipsets seem to cause troubles with MSI */ if (chip->driver_caps & AZX_DCAPS_NO_MSI) { - printk(KERN_INFO "hda_intel: Disabling MSI\n"); + dev_info(chip->card->dev, "Disabling MSI\n"); chip->msi = 0; } } @@ -3511,8 +1145,8 @@ static void azx_check_snoop_available(struct azx *chip) } if (snoop != chip->snoop) { - snd_printk(KERN_INFO SFX "%s: Force to %s mode\n", - pci_name(chip->pci), snoop ? "snoop" : "non-snoop"); + dev_info(chip->card->dev, "Force to %s mode\n", + snoop ? "snoop" : "non-snoop"); chip->snoop = snoop; } } @@ -3527,6 +1161,7 @@ static void azx_probe_work(struct work_struct *work) */ static int azx_create(struct snd_card *card, struct pci_dev *pci, int dev, unsigned int driver_caps, + const struct hda_controller_ops *hda_ops, struct azx **rchip) { static struct snd_device_ops ops = { @@ -3543,7 +1178,7 @@ static int azx_create(struct snd_card *card, struct pci_dev *pci, chip = kzalloc(sizeof(*chip), GFP_KERNEL); if (!chip) { - snd_printk(KERN_ERR SFX "%s: Cannot allocate chip\n", pci_name(pci)); + dev_err(card->dev, "Cannot allocate chip\n"); pci_disable_device(pci); return -ENOMEM; } @@ -3552,11 +1187,13 @@ static int azx_create(struct snd_card *card, struct pci_dev *pci, mutex_init(&chip->open_mutex); chip->card = card; chip->pci = pci; + chip->ops = hda_ops; chip->irq = -1; chip->driver_caps = driver_caps; chip->driver_type = driver_caps & 0xff; check_msi(chip); chip->dev_index = dev; + chip->jackpoll_ms = jackpoll_ms; INIT_WORK(&chip->irq_pending_work, azx_irq_pending_work); INIT_LIST_HEAD(&chip->pcm_list); INIT_LIST_HEAD(&chip->list); @@ -3588,11 +1225,11 @@ static int azx_create(struct snd_card *card, struct pci_dev *pci, break; } } + chip->bdl_pos_adj = bdl_pos_adj; err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops); if (err < 0) { - snd_printk(KERN_ERR SFX "%s: Error creating device [card]!\n", - pci_name(chip->pci)); + dev_err(card->dev, "Error creating device [card]!\n"); azx_free(chip); return err; } @@ -3610,7 +1247,7 @@ static int azx_first_init(struct azx *chip) int dev = chip->dev_index; struct pci_dev *pci = chip->pci; struct snd_card *card = chip->card; - int i, err; + int err; unsigned short gcap; #if BITS_PER_LONG != 64 @@ -3631,7 +1268,7 @@ static int azx_first_init(struct azx *chip) chip->addr = pci_resource_start(pci, 0); chip->remap_addr = pci_ioremap_bar(pci, 0); if (chip->remap_addr == NULL) { - snd_printk(KERN_ERR SFX "%s: ioremap error\n", pci_name(chip->pci)); + dev_err(card->dev, "ioremap error\n"); return -ENXIO; } @@ -3646,7 +1283,7 @@ static int azx_first_init(struct azx *chip) synchronize_irq(chip->irq); gcap = azx_readw(chip, GCAP); - snd_printdd(SFX "%s: chipset global capabilities = 0x%x\n", pci_name(chip->pci), gcap); + dev_dbg(card->dev, "chipset global capabilities = 0x%x\n", gcap); /* disable SB600 64bit support for safety */ if (chip->pci->vendor == PCI_VENDOR_ID_ATI) { @@ -3663,7 +1300,7 @@ static int azx_first_init(struct azx *chip) /* disable 64bit DMA address on some devices */ if (chip->driver_caps & AZX_DCAPS_NO_64BIT) { - snd_printd(SFX "%s: Disabling 64bit DMA\n", pci_name(chip->pci)); + dev_dbg(card->dev, "Disabling 64bit DMA\n"); gcap &= ~ICH6_GCAP_64OK; } @@ -3718,33 +1355,11 @@ static int azx_first_init(struct azx *chip) chip->azx_dev = kcalloc(chip->num_streams, sizeof(*chip->azx_dev), GFP_KERNEL); if (!chip->azx_dev) { - snd_printk(KERN_ERR SFX "%s: cannot malloc azx_dev\n", pci_name(chip->pci)); + dev_err(card->dev, "cannot malloc azx_dev\n"); return -ENOMEM; } - for (i = 0; i < chip->num_streams; i++) { - dsp_lock_init(&chip->azx_dev[i]); - /* allocate memory for the BDL for each stream */ - err = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, - snd_dma_pci_data(chip->pci), - BDL_SIZE, &chip->azx_dev[i].bdl); - if (err < 0) { - snd_printk(KERN_ERR SFX "%s: cannot allocate BDL\n", pci_name(chip->pci)); - return -ENOMEM; - } - mark_pages_wc(chip, &chip->azx_dev[i].bdl, true); - } - /* allocate memory for the position buffer */ - err = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, - snd_dma_pci_data(chip->pci), - chip->num_streams * 8, &chip->posbuf); - if (err < 0) { - snd_printk(KERN_ERR SFX "%s: cannot allocate posbuf\n", pci_name(chip->pci)); - return -ENOMEM; - } - mark_pages_wc(chip, &chip->posbuf, true); - /* allocate CORB/RIRB */ - err = azx_alloc_cmd_io(chip); + err = azx_alloc_stream_pages(chip); if (err < 0) return err; @@ -3757,7 +1372,7 @@ static int azx_first_init(struct azx *chip) /* codec detection */ if (!chip->codec_mask) { - snd_printk(KERN_ERR SFX "%s: no codecs found!\n", pci_name(chip->pci)); + dev_err(card->dev, "no codecs found!\n"); return -ENODEV; } @@ -3793,8 +1408,7 @@ static void azx_firmware_cb(const struct firmware *fw, void *context) struct pci_dev *pci = chip->pci; if (!fw) { - snd_printk(KERN_ERR SFX "%s: Cannot load firmware, aborting\n", - pci_name(chip->pci)); + dev_err(card->dev, "Cannot load firmware, aborting\n"); goto error; } @@ -3812,6 +1426,132 @@ static void azx_firmware_cb(const struct firmware *fw, void *context) } #endif +/* + * HDA controller ops. + */ + +/* PCI register access. */ +static void pci_azx_writel(u32 value, u32 __iomem *addr) +{ + writel(value, addr); +} + +static u32 pci_azx_readl(u32 __iomem *addr) +{ + return readl(addr); +} + +static void pci_azx_writew(u16 value, u16 __iomem *addr) +{ + writew(value, addr); +} + +static u16 pci_azx_readw(u16 __iomem *addr) +{ + return readw(addr); +} + +static void pci_azx_writeb(u8 value, u8 __iomem *addr) +{ + writeb(value, addr); +} + +static u8 pci_azx_readb(u8 __iomem *addr) +{ + return readb(addr); +} + +static int disable_msi_reset_irq(struct azx *chip) +{ + int err; + + free_irq(chip->irq, chip); + chip->irq = -1; + pci_disable_msi(chip->pci); + chip->msi = 0; + err = azx_acquire_irq(chip, 1); + if (err < 0) + return err; + + return 0; +} + +/* DMA page allocation helpers. */ +static int dma_alloc_pages(struct azx *chip, + int type, + size_t size, + struct snd_dma_buffer *buf) +{ + int err; + + err = snd_dma_alloc_pages(type, + chip->card->dev, + size, buf); + if (err < 0) + return err; + mark_pages_wc(chip, buf, true); + return 0; +} + +static void dma_free_pages(struct azx *chip, struct snd_dma_buffer *buf) +{ + mark_pages_wc(chip, buf, false); + snd_dma_free_pages(buf); +} + +static int substream_alloc_pages(struct azx *chip, + struct snd_pcm_substream *substream, + size_t size) +{ + struct azx_dev *azx_dev = get_azx_dev(substream); + int ret; + + mark_runtime_wc(chip, azx_dev, substream, false); + azx_dev->bufsize = 0; + azx_dev->period_bytes = 0; + azx_dev->format_val = 0; + ret = snd_pcm_lib_malloc_pages(substream, size); + if (ret < 0) + return ret; + mark_runtime_wc(chip, azx_dev, substream, true); + return 0; +} + +static int substream_free_pages(struct azx *chip, + struct snd_pcm_substream *substream) +{ + struct azx_dev *azx_dev = get_azx_dev(substream); + mark_runtime_wc(chip, azx_dev, substream, false); + return snd_pcm_lib_free_pages(substream); +} + +static void pcm_mmap_prepare(struct snd_pcm_substream *substream, + struct vm_area_struct *area) +{ +#ifdef CONFIG_X86 + struct azx_pcm *apcm = snd_pcm_substream_chip(substream); + struct azx *chip = apcm->chip; + if (!azx_snoop(chip)) + area->vm_page_prot = pgprot_writecombine(area->vm_page_prot); +#endif +} + +static const struct hda_controller_ops pci_hda_ops = { + .reg_writel = pci_azx_writel, + .reg_readl = pci_azx_readl, + .reg_writew = pci_azx_writew, + .reg_readw = pci_azx_readw, + .reg_writeb = pci_azx_writeb, + .reg_readb = pci_azx_readb, + .disable_msi_reset_irq = disable_msi_reset_irq, + .dma_alloc_pages = dma_alloc_pages, + .dma_free_pages = dma_free_pages, + .substream_alloc_pages = substream_alloc_pages, + .substream_free_pages = substream_free_pages, + .pcm_mmap_prepare = pcm_mmap_prepare, + .position_check = azx_position_check, +}; + static int azx_probe(struct pci_dev *pci, const struct pci_device_id *pci_id) { @@ -3828,15 +1568,15 @@ static int azx_probe(struct pci_dev *pci, return -ENOENT; } - err = snd_card_create(index[dev], id[dev], THIS_MODULE, 0, &card); + err = snd_card_new(&pci->dev, index[dev], id[dev], THIS_MODULE, + 0, &card); if (err < 0) { - snd_printk(KERN_ERR "hda-intel: Error creating card!\n"); + dev_err(&pci->dev, "Error creating card!\n"); return err; } - snd_card_set_dev(card, &pci->dev); - - err = azx_create(card, pci, dev, pci_id->driver_data, &chip); + err = azx_create(card, pci, dev, pci_id->driver_data, + &pci_hda_ops, &chip); if (err < 0) goto out_free; card->private_data = chip; @@ -3845,15 +1585,13 @@ static int azx_probe(struct pci_dev *pci, err = register_vga_switcheroo(chip); if (err < 0) { - snd_printk(KERN_ERR SFX - "%s: Error registering VGA-switcheroo client\n", pci_name(pci)); + dev_err(card->dev, "Error registering VGA-switcheroo client\n"); goto out_free; } if (check_hdmi_disabled(pci)) { - snd_printk(KERN_INFO SFX "%s: VGA controller is disabled\n", - pci_name(pci)); - snd_printk(KERN_INFO SFX "%s: Delaying initialization\n", pci_name(pci)); + dev_info(card->dev, "VGA controller is disabled\n"); + dev_info(card->dev, "Delaying initialization\n"); chip->disabled = true; } @@ -3861,8 +1599,8 @@ static int azx_probe(struct pci_dev *pci, #ifdef CONFIG_SND_HDA_PATCH_LOADER if (patch[dev] && *patch[dev]) { - snd_printk(KERN_ERR SFX "%s: Applying patch firmware '%s'\n", - pci_name(pci), patch[dev]); + dev_info(card->dev, "Applying patch firmware '%s'\n", + patch[dev]); err = request_firmware_nowait(THIS_MODULE, true, patch[dev], &pci->dev, GFP_KERNEL, card, azx_firmware_cb); @@ -3874,7 +1612,7 @@ static int azx_probe(struct pci_dev *pci, #ifndef CONFIG_SND_HDA_I915 if (chip->driver_caps & AZX_DCAPS_I915_POWERWELL) - snd_printk(KERN_ERR SFX "Haswell must build in CONFIG_SND_HDA_I915\n"); + dev_err(card->dev, "Haswell must build in CONFIG_SND_HDA_I915\n"); #endif if (schedule_probe) @@ -3890,6 +1628,12 @@ out_free: return err; } +/* number of codec slots for each chipset: 0 = default slots (i.e. 4) */ +static unsigned int azx_max_codecs[AZX_NUM_DRIVERS] = { + [AZX_DRIVER_NVIDIA] = 8, + [AZX_DRIVER_TERA] = 1, +}; + static int azx_probe_continue(struct azx *chip) { struct pci_dev *pci = chip->pci; @@ -3901,7 +1645,8 @@ static int azx_probe_continue(struct azx *chip) #ifdef CONFIG_SND_HDA_I915 err = hda_i915_init(); if (err < 0) { - snd_printk(KERN_ERR SFX "Error request power-well from i915\n"); + dev_err(chip->card->dev, + "Error request power-well from i915\n"); goto out_free; } #endif @@ -3917,7 +1662,10 @@ static int azx_probe_continue(struct azx *chip) #endif /* create codec instances */ - err = azx_codec_create(chip, model[dev]); + err = azx_codec_create(chip, model[dev], + azx_max_codecs[chip->driver_type], + power_save_addr); + if (err < 0) goto out_free; #ifdef CONFIG_SND_HDA_PATCH_LOADER @@ -4142,7 +1890,7 @@ static DEFINE_PCI_DEVICE_TABLE(azx_ids) = { .driver_data = AZX_DRIVER_CTHDA | AZX_DCAPS_PRESET_CTHDA }, { PCI_DEVICE(0x1102, 0x0012), .driver_data = AZX_DRIVER_CTHDA | AZX_DCAPS_PRESET_CTHDA }, -#if !defined(CONFIG_SND_CTXFI) && !defined(CONFIG_SND_CTXFI_MODULE) +#if !IS_ENABLED(CONFIG_SND_CTXFI) /* the following entry conflicts with snd-ctxfi driver, * as ctxfi driver mutates from HD-audio to native mode with * a special command sequence. diff --git a/sound/pci/hda/hda_local.h b/sound/pci/hda/hda_local.h index da80c5bd7fd..e51d1552921 100644 --- a/sound/pci/hda/hda_local.h +++ b/sound/pci/hda/hda_local.h @@ -597,23 +597,10 @@ int snd_hda_create_hwdep(struct hda_codec *codec); static inline int snd_hda_create_hwdep(struct hda_codec *codec) { return 0; } #endif -#if defined(CONFIG_PM) && defined(CONFIG_SND_HDA_HWDEP) -int snd_hda_hwdep_add_power_sysfs(struct hda_codec *codec); -#else -static inline int snd_hda_hwdep_add_power_sysfs(struct hda_codec *codec) -{ - return 0; -} -#endif +void snd_hda_sysfs_init(struct hda_codec *codec); +void snd_hda_sysfs_clear(struct hda_codec *codec); -#ifdef CONFIG_SND_HDA_RECONFIG -int snd_hda_hwdep_add_sysfs(struct hda_codec *codec); -#else -static inline int snd_hda_hwdep_add_sysfs(struct hda_codec *codec) -{ - return 0; -} -#endif +extern const struct attribute_group *snd_hda_dev_attr_groups[]; #ifdef CONFIG_SND_HDA_RECONFIG const char *snd_hda_get_hint(struct hda_codec *codec, const char *key); @@ -771,4 +758,11 @@ void snd_hdmi_write_eld_info(struct hdmi_eld *eld, #define SND_PRINT_CHANNEL_ALLOCATION_ADVISED_BUFSIZE 80 void snd_print_channel_allocation(int spk_alloc, char *buf, int buflen); +/* + */ +#define codec_err(codec, fmt, args...) dev_err(&(codec)->dev, fmt, ##args) +#define codec_warn(codec, fmt, args...) dev_warn(&(codec)->dev, fmt, ##args) +#define codec_info(codec, fmt, args...) dev_info(&(codec)->dev, fmt, ##args) +#define codec_dbg(codec, fmt, args...) dev_dbg(&(codec)->dev, fmt, ##args) + #endif /* __SOUND_HDA_LOCAL_H */ diff --git a/sound/pci/hda/hda_priv.h b/sound/pci/hda/hda_priv.h new file mode 100644 index 00000000000..ba38b819f98 --- /dev/null +++ b/sound/pci/hda/hda_priv.h @@ -0,0 +1,463 @@ +/* + * Common defines for the alsa driver code base for HD Audio. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the Free + * Software Foundation; either version 2 of the License, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + */ + +#ifndef __SOUND_HDA_PRIV_H +#define __SOUND_HDA_PRIV_H + +#include <linux/clocksource.h> +#include <sound/core.h> +#include <sound/pcm.h> + +/* + * registers + */ +#define ICH6_REG_GCAP 0x00 +#define ICH6_GCAP_64OK (1 << 0) /* 64bit address support */ +#define ICH6_GCAP_NSDO (3 << 1) /* # of serial data out signals */ +#define ICH6_GCAP_BSS (31 << 3) /* # of bidirectional streams */ +#define ICH6_GCAP_ISS (15 << 8) /* # of input streams */ +#define ICH6_GCAP_OSS (15 << 12) /* # of output streams */ +#define ICH6_REG_VMIN 0x02 +#define ICH6_REG_VMAJ 0x03 +#define ICH6_REG_OUTPAY 0x04 +#define ICH6_REG_INPAY 0x06 +#define ICH6_REG_GCTL 0x08 +#define ICH6_GCTL_RESET (1 << 0) /* controller reset */ +#define ICH6_GCTL_FCNTRL (1 << 1) /* flush control */ +#define ICH6_GCTL_UNSOL (1 << 8) /* accept unsol. response enable */ +#define ICH6_REG_WAKEEN 0x0c +#define ICH6_REG_STATESTS 0x0e +#define ICH6_REG_GSTS 0x10 +#define ICH6_GSTS_FSTS (1 << 1) /* flush status */ +#define ICH6_REG_INTCTL 0x20 +#define ICH6_REG_INTSTS 0x24 +#define ICH6_REG_WALLCLK 0x30 /* 24Mhz source */ +#define ICH6_REG_OLD_SSYNC 0x34 /* SSYNC for old ICH */ +#define ICH6_REG_SSYNC 0x38 +#define ICH6_REG_CORBLBASE 0x40 +#define ICH6_REG_CORBUBASE 0x44 +#define ICH6_REG_CORBWP 0x48 +#define ICH6_REG_CORBRP 0x4a +#define ICH6_CORBRP_RST (1 << 15) /* read pointer reset */ +#define ICH6_REG_CORBCTL 0x4c +#define ICH6_CORBCTL_RUN (1 << 1) /* enable DMA */ +#define ICH6_CORBCTL_CMEIE (1 << 0) /* enable memory error irq */ +#define ICH6_REG_CORBSTS 0x4d +#define ICH6_CORBSTS_CMEI (1 << 0) /* memory error indication */ +#define ICH6_REG_CORBSIZE 0x4e + +#define ICH6_REG_RIRBLBASE 0x50 +#define ICH6_REG_RIRBUBASE 0x54 +#define ICH6_REG_RIRBWP 0x58 +#define ICH6_RIRBWP_RST (1 << 15) /* write pointer reset */ +#define ICH6_REG_RINTCNT 0x5a +#define ICH6_REG_RIRBCTL 0x5c +#define ICH6_RBCTL_IRQ_EN (1 << 0) /* enable IRQ */ +#define ICH6_RBCTL_DMA_EN (1 << 1) /* enable DMA */ +#define ICH6_RBCTL_OVERRUN_EN (1 << 2) /* enable overrun irq */ +#define ICH6_REG_RIRBSTS 0x5d +#define ICH6_RBSTS_IRQ (1 << 0) /* response irq */ +#define ICH6_RBSTS_OVERRUN (1 << 2) /* overrun irq */ +#define ICH6_REG_RIRBSIZE 0x5e + +#define ICH6_REG_IC 0x60 +#define ICH6_REG_IR 0x64 +#define ICH6_REG_IRS 0x68 +#define ICH6_IRS_VALID (1<<1) +#define ICH6_IRS_BUSY (1<<0) + +#define ICH6_REG_DPLBASE 0x70 +#define ICH6_REG_DPUBASE 0x74 +#define ICH6_DPLBASE_ENABLE 0x1 /* Enable position buffer */ + +/* SD offset: SDI0=0x80, SDI1=0xa0, ... SDO3=0x160 */ +enum { SDI0, SDI1, SDI2, SDI3, SDO0, SDO1, SDO2, SDO3 }; + +/* stream register offsets from stream base */ +#define ICH6_REG_SD_CTL 0x00 +#define ICH6_REG_SD_STS 0x03 +#define ICH6_REG_SD_LPIB 0x04 +#define ICH6_REG_SD_CBL 0x08 +#define ICH6_REG_SD_LVI 0x0c +#define ICH6_REG_SD_FIFOW 0x0e +#define ICH6_REG_SD_FIFOSIZE 0x10 +#define ICH6_REG_SD_FORMAT 0x12 +#define ICH6_REG_SD_BDLPL 0x18 +#define ICH6_REG_SD_BDLPU 0x1c + +/* PCI space */ +#define ICH6_PCIREG_TCSEL 0x44 + +/* + * other constants + */ + +/* max number of SDs */ +/* ICH, ATI and VIA have 4 playback and 4 capture */ +#define ICH6_NUM_CAPTURE 4 +#define ICH6_NUM_PLAYBACK 4 + +/* ULI has 6 playback and 5 capture */ +#define ULI_NUM_CAPTURE 5 +#define ULI_NUM_PLAYBACK 6 + +/* ATI HDMI may have up to 8 playbacks and 0 capture */ +#define ATIHDMI_NUM_CAPTURE 0 +#define ATIHDMI_NUM_PLAYBACK 8 + +/* TERA has 4 playback and 3 capture */ +#define TERA_NUM_CAPTURE 3 +#define TERA_NUM_PLAYBACK 4 + +/* this number is statically defined for simplicity */ +#define MAX_AZX_DEV 16 + +/* max number of fragments - we may use more if allocating more pages for BDL */ +#define BDL_SIZE 4096 +#define AZX_MAX_BDL_ENTRIES (BDL_SIZE / 16) +#define AZX_MAX_FRAG 32 +/* max buffer size - no h/w limit, you can increase as you like */ +#define AZX_MAX_BUF_SIZE (1024*1024*1024) + +/* RIRB int mask: overrun[2], response[0] */ +#define RIRB_INT_RESPONSE 0x01 +#define RIRB_INT_OVERRUN 0x04 +#define RIRB_INT_MASK 0x05 + +/* STATESTS int mask: S3,SD2,SD1,SD0 */ +#define AZX_MAX_CODECS 8 +#define AZX_DEFAULT_CODECS 4 +#define STATESTS_INT_MASK ((1 << AZX_MAX_CODECS) - 1) + +/* SD_CTL bits */ +#define SD_CTL_STREAM_RESET 0x01 /* stream reset bit */ +#define SD_CTL_DMA_START 0x02 /* stream DMA start bit */ +#define SD_CTL_STRIPE (3 << 16) /* stripe control */ +#define SD_CTL_TRAFFIC_PRIO (1 << 18) /* traffic priority */ +#define SD_CTL_DIR (1 << 19) /* bi-directional stream */ +#define SD_CTL_STREAM_TAG_MASK (0xf << 20) +#define SD_CTL_STREAM_TAG_SHIFT 20 + +/* SD_CTL and SD_STS */ +#define SD_INT_DESC_ERR 0x10 /* descriptor error interrupt */ +#define SD_INT_FIFO_ERR 0x08 /* FIFO error interrupt */ +#define SD_INT_COMPLETE 0x04 /* completion interrupt */ +#define SD_INT_MASK (SD_INT_DESC_ERR|SD_INT_FIFO_ERR|\ + SD_INT_COMPLETE) + +/* SD_STS */ +#define SD_STS_FIFO_READY 0x20 /* FIFO ready */ + +/* INTCTL and INTSTS */ +#define ICH6_INT_ALL_STREAM 0xff /* all stream interrupts */ +#define ICH6_INT_CTRL_EN 0x40000000 /* controller interrupt enable bit */ +#define ICH6_INT_GLOBAL_EN 0x80000000 /* global interrupt enable bit */ + +/* below are so far hardcoded - should read registers in future */ +#define ICH6_MAX_CORB_ENTRIES 256 +#define ICH6_MAX_RIRB_ENTRIES 256 + +/* driver quirks (capabilities) */ +/* bits 0-7 are used for indicating driver type */ +#define AZX_DCAPS_NO_TCSEL (1 << 8) /* No Intel TCSEL bit */ +#define AZX_DCAPS_NO_MSI (1 << 9) /* No MSI support */ +#define AZX_DCAPS_ATI_SNOOP (1 << 10) /* ATI snoop enable */ +#define AZX_DCAPS_NVIDIA_SNOOP (1 << 11) /* Nvidia snoop enable */ +#define AZX_DCAPS_SCH_SNOOP (1 << 12) /* SCH/PCH snoop enable */ +#define AZX_DCAPS_RIRB_DELAY (1 << 13) /* Long delay in read loop */ +#define AZX_DCAPS_RIRB_PRE_DELAY (1 << 14) /* Put a delay before read */ +#define AZX_DCAPS_CTX_WORKAROUND (1 << 15) /* X-Fi workaround */ +#define AZX_DCAPS_POSFIX_LPIB (1 << 16) /* Use LPIB as default */ +#define AZX_DCAPS_POSFIX_VIA (1 << 17) /* Use VIACOMBO as default */ +#define AZX_DCAPS_NO_64BIT (1 << 18) /* No 64bit address */ +#define AZX_DCAPS_SYNC_WRITE (1 << 19) /* sync each cmd write */ +#define AZX_DCAPS_OLD_SSYNC (1 << 20) /* Old SSYNC reg for ICH */ +#define AZX_DCAPS_BUFSIZE (1 << 21) /* no buffer size alignment */ +#define AZX_DCAPS_ALIGN_BUFSIZE (1 << 22) /* buffer size alignment */ +#define AZX_DCAPS_4K_BDLE_BOUNDARY (1 << 23) /* BDLE in 4k boundary */ +#define AZX_DCAPS_COUNT_LPIB_DELAY (1 << 25) /* Take LPIB as delay */ +#define AZX_DCAPS_PM_RUNTIME (1 << 26) /* runtime PM support */ +#define AZX_DCAPS_I915_POWERWELL (1 << 27) /* HSW i915 powerwell support */ + +/* position fix mode */ +enum { + POS_FIX_AUTO, + POS_FIX_LPIB, + POS_FIX_POSBUF, + POS_FIX_VIACOMBO, + POS_FIX_COMBO, +}; + +/* Defines for ATI HD Audio support in SB450 south bridge */ +#define ATI_SB450_HDAUDIO_MISC_CNTR2_ADDR 0x42 +#define ATI_SB450_HDAUDIO_ENABLE_SNOOP 0x02 + +/* Defines for Nvidia HDA support */ +#define NVIDIA_HDA_TRANSREG_ADDR 0x4e +#define NVIDIA_HDA_ENABLE_COHBITS 0x0f +#define NVIDIA_HDA_ISTRM_COH 0x4d +#define NVIDIA_HDA_OSTRM_COH 0x4c +#define NVIDIA_HDA_ENABLE_COHBIT 0x01 + +/* Defines for Intel SCH HDA snoop control */ +#define INTEL_SCH_HDA_DEVC 0x78 +#define INTEL_SCH_HDA_DEVC_NOSNOOP (0x1<<11) + +/* Define IN stream 0 FIFO size offset in VIA controller */ +#define VIA_IN_STREAM0_FIFO_SIZE_OFFSET 0x90 +/* Define VIA HD Audio Device ID*/ +#define VIA_HDAC_DEVICE_ID 0x3288 + +/* HD Audio class code */ +#define PCI_CLASS_MULTIMEDIA_HD_AUDIO 0x0403 + +struct azx_dev { + struct snd_dma_buffer bdl; /* BDL buffer */ + u32 *posbuf; /* position buffer pointer */ + + unsigned int bufsize; /* size of the play buffer in bytes */ + unsigned int period_bytes; /* size of the period in bytes */ + unsigned int frags; /* number for period in the play buffer */ + unsigned int fifo_size; /* FIFO size */ + unsigned long start_wallclk; /* start + minimum wallclk */ + unsigned long period_wallclk; /* wallclk for period */ + + void __iomem *sd_addr; /* stream descriptor pointer */ + + u32 sd_int_sta_mask; /* stream int status mask */ + + /* pcm support */ + struct snd_pcm_substream *substream; /* assigned substream, + * set in PCM open + */ + unsigned int format_val; /* format value to be set in the + * controller and the codec + */ + unsigned char stream_tag; /* assigned stream */ + unsigned char index; /* stream index */ + int assigned_key; /* last device# key assigned to */ + + unsigned int opened:1; + unsigned int running:1; + unsigned int irq_pending:1; + unsigned int prepared:1; + unsigned int locked:1; + /* + * For VIA: + * A flag to ensure DMA position is 0 + * when link position is not greater than FIFO size + */ + unsigned int insufficient:1; + unsigned int wc_marked:1; + unsigned int no_period_wakeup:1; + + struct timecounter azx_tc; + struct cyclecounter azx_cc; + + int delay_negative_threshold; + +#ifdef CONFIG_SND_HDA_DSP_LOADER + /* Allows dsp load to have sole access to the playback stream. */ + struct mutex dsp_mutex; +#endif +}; + +/* CORB/RIRB */ +struct azx_rb { + u32 *buf; /* CORB/RIRB buffer + * Each CORB entry is 4byte, RIRB is 8byte + */ + dma_addr_t addr; /* physical address of CORB/RIRB buffer */ + /* for RIRB */ + unsigned short rp, wp; /* read/write pointers */ + int cmds[AZX_MAX_CODECS]; /* number of pending requests */ + u32 res[AZX_MAX_CODECS]; /* last read value */ +}; + +struct azx; + +/* Functions to read/write to hda registers. */ +struct hda_controller_ops { + /* Register Access */ + void (*reg_writel)(u32 value, u32 __iomem *addr); + u32 (*reg_readl)(u32 __iomem *addr); + void (*reg_writew)(u16 value, u16 __iomem *addr); + u16 (*reg_readw)(u16 __iomem *addr); + void (*reg_writeb)(u8 value, u8 __iomem *addr); + u8 (*reg_readb)(u8 __iomem *addr); + /* Disable msi if supported, PCI only */ + int (*disable_msi_reset_irq)(struct azx *); + /* Allocation ops */ + int (*dma_alloc_pages)(struct azx *chip, + int type, + size_t size, + struct snd_dma_buffer *buf); + void (*dma_free_pages)(struct azx *chip, struct snd_dma_buffer *buf); + int (*substream_alloc_pages)(struct azx *chip, + struct snd_pcm_substream *substream, + size_t size); + int (*substream_free_pages)(struct azx *chip, + struct snd_pcm_substream *substream); + void (*pcm_mmap_prepare)(struct snd_pcm_substream *substream, + struct vm_area_struct *area); + /* Check if current position is acceptable */ + int (*position_check)(struct azx *chip, struct azx_dev *azx_dev); +}; + +struct azx_pcm { + struct azx *chip; + struct snd_pcm *pcm; + struct hda_codec *codec; + struct hda_pcm_stream *hinfo[2]; + struct list_head list; +}; + +struct azx { + struct snd_card *card; + struct pci_dev *pci; + int dev_index; + + /* chip type specific */ + int driver_type; + unsigned int driver_caps; + int playback_streams; + int playback_index_offset; + int capture_streams; + int capture_index_offset; + int num_streams; + const int *jackpoll_ms; /* per-card jack poll interval */ + + /* Register interaction. */ + const struct hda_controller_ops *ops; + + /* pci resources */ + unsigned long addr; + void __iomem *remap_addr; + int irq; + + /* locks */ + spinlock_t reg_lock; + struct mutex open_mutex; /* Prevents concurrent open/close operations */ + struct completion probe_wait; + + /* streams (x num_streams) */ + struct azx_dev *azx_dev; + + /* PCM */ + struct list_head pcm_list; /* azx_pcm list */ + + /* HD codec */ + unsigned short codec_mask; + int codec_probe_mask; /* copied from probe_mask option */ + struct hda_bus *bus; + unsigned int beep_mode; + + /* CORB/RIRB */ + struct azx_rb corb; + struct azx_rb rirb; + + /* CORB/RIRB and position buffers */ + struct snd_dma_buffer rb; + struct snd_dma_buffer posbuf; + +#ifdef CONFIG_SND_HDA_PATCH_LOADER + const struct firmware *fw; +#endif + + /* flags */ + int position_fix[2]; /* for both playback/capture streams */ + const int *bdl_pos_adj; + int poll_count; + unsigned int running:1; + unsigned int initialized:1; + unsigned int single_cmd:1; + unsigned int polling_mode:1; + unsigned int msi:1; + unsigned int irq_pending_warned:1; + unsigned int probing:1; /* codec probing phase */ + unsigned int snoop:1; + unsigned int align_buffer_size:1; + unsigned int region_requested:1; + + /* VGA-switcheroo setup */ + unsigned int use_vga_switcheroo:1; + unsigned int vga_switcheroo_registered:1; + unsigned int init_failed:1; /* delayed init failed */ + unsigned int disabled:1; /* disabled by VGA-switcher */ + + /* for debugging */ + unsigned int last_cmd[AZX_MAX_CODECS]; + + /* for pending irqs */ + struct work_struct irq_pending_work; + + struct work_struct probe_work; + + /* reboot notifier (for mysterious hangup problem at power-down) */ + struct notifier_block reboot_notifier; + + /* card list (for power_save trigger) */ + struct list_head list; + +#ifdef CONFIG_SND_HDA_DSP_LOADER + struct azx_dev saved_azx_dev; +#endif + + /* secondary power domain for hdmi audio under vga device */ + struct dev_pm_domain hdmi_pm_domain; +}; + +#ifdef CONFIG_SND_VERBOSE_PRINTK +#define SFX /* nop */ +#else +#define SFX "hda-intel " +#endif + +#ifdef CONFIG_X86 +#define azx_snoop(chip) ((chip)->snoop) +#else +#define azx_snoop(chip) true +#endif + +/* + * macros for easy use + */ + +#define azx_writel(chip, reg, value) \ + ((chip)->ops->reg_writel(value, (chip)->remap_addr + ICH6_REG_##reg)) +#define azx_readl(chip, reg) \ + ((chip)->ops->reg_readl((chip)->remap_addr + ICH6_REG_##reg)) +#define azx_writew(chip, reg, value) \ + ((chip)->ops->reg_writew(value, (chip)->remap_addr + ICH6_REG_##reg)) +#define azx_readw(chip, reg) \ + ((chip)->ops->reg_readw((chip)->remap_addr + ICH6_REG_##reg)) +#define azx_writeb(chip, reg, value) \ + ((chip)->ops->reg_writeb(value, (chip)->remap_addr + ICH6_REG_##reg)) +#define azx_readb(chip, reg) \ + ((chip)->ops->reg_readb((chip)->remap_addr + ICH6_REG_##reg)) + +#define azx_sd_writel(chip, dev, reg, value) \ + ((chip)->ops->reg_writel(value, (dev)->sd_addr + ICH6_REG_##reg)) +#define azx_sd_readl(chip, dev, reg) \ + ((chip)->ops->reg_readl((dev)->sd_addr + ICH6_REG_##reg)) +#define azx_sd_writew(chip, dev, reg, value) \ + ((chip)->ops->reg_writew(value, (dev)->sd_addr + ICH6_REG_##reg)) +#define azx_sd_readw(chip, dev, reg) \ + ((chip)->ops->reg_readw((dev)->sd_addr + ICH6_REG_##reg)) +#define azx_sd_writeb(chip, dev, reg, value) \ + ((chip)->ops->reg_writeb(value, (dev)->sd_addr + ICH6_REG_##reg)) +#define azx_sd_readb(chip, dev, reg) \ + ((chip)->ops->reg_readb((dev)->sd_addr + ICH6_REG_##reg)) + +#endif /* __SOUND_HDA_PRIV_H */ diff --git a/sound/pci/hda/hda_sysfs.c b/sound/pci/hda/hda_sysfs.c new file mode 100644 index 00000000000..e2079090ca6 --- /dev/null +++ b/sound/pci/hda/hda_sysfs.c @@ -0,0 +1,780 @@ +/* + * sysfs interface for HD-audio codec + * + * Copyright (c) 2014 Takashi Iwai <tiwai@suse.de> + * + * split from hda_hwdep.c + */ + +#include <linux/init.h> +#include <linux/slab.h> +#include <linux/compat.h> +#include <linux/mutex.h> +#include <linux/ctype.h> +#include <linux/string.h> +#include <linux/export.h> +#include <sound/core.h> +#include "hda_codec.h" +#include "hda_local.h" +#include <sound/hda_hwdep.h> +#include <sound/minors.h> + +/* hint string pair */ +struct hda_hint { + const char *key; + const char *val; /* contained in the same alloc as key */ +}; + +#ifdef CONFIG_PM +static ssize_t power_on_acct_show(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct hda_codec *codec = dev_get_drvdata(dev); + snd_hda_update_power_acct(codec); + return sprintf(buf, "%u\n", jiffies_to_msecs(codec->power_on_acct)); +} + +static ssize_t power_off_acct_show(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct hda_codec *codec = dev_get_drvdata(dev); + snd_hda_update_power_acct(codec); + return sprintf(buf, "%u\n", jiffies_to_msecs(codec->power_off_acct)); +} + +static DEVICE_ATTR_RO(power_on_acct); +static DEVICE_ATTR_RO(power_off_acct); +#endif /* CONFIG_PM */ + +#define CODEC_INFO_SHOW(type) \ +static ssize_t type##_show(struct device *dev, \ + struct device_attribute *attr, \ + char *buf) \ +{ \ + struct hda_codec *codec = dev_get_drvdata(dev); \ + return sprintf(buf, "0x%x\n", codec->type); \ +} + +#define CODEC_INFO_STR_SHOW(type) \ +static ssize_t type##_show(struct device *dev, \ + struct device_attribute *attr, \ + char *buf) \ +{ \ + struct hda_codec *codec = dev_get_drvdata(dev); \ + return sprintf(buf, "%s\n", \ + codec->type ? codec->type : ""); \ +} + +CODEC_INFO_SHOW(vendor_id); +CODEC_INFO_SHOW(subsystem_id); +CODEC_INFO_SHOW(revision_id); +CODEC_INFO_SHOW(afg); +CODEC_INFO_SHOW(mfg); +CODEC_INFO_STR_SHOW(vendor_name); +CODEC_INFO_STR_SHOW(chip_name); +CODEC_INFO_STR_SHOW(modelname); + +static ssize_t pin_configs_show(struct hda_codec *codec, + struct snd_array *list, + char *buf) +{ + int i, len = 0; + mutex_lock(&codec->user_mutex); + for (i = 0; i < list->used; i++) { + struct hda_pincfg *pin = snd_array_elem(list, i); + len += sprintf(buf + len, "0x%02x 0x%08x\n", + pin->nid, pin->cfg); + } + mutex_unlock(&codec->user_mutex); + return len; +} + +static ssize_t init_pin_configs_show(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct hda_codec *codec = dev_get_drvdata(dev); + return pin_configs_show(codec, &codec->init_pins, buf); +} + +static ssize_t driver_pin_configs_show(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct hda_codec *codec = dev_get_drvdata(dev); + return pin_configs_show(codec, &codec->driver_pins, buf); +} + +#ifdef CONFIG_SND_HDA_RECONFIG + +/* + * sysfs interface + */ + +static int clear_codec(struct hda_codec *codec) +{ + int err; + + err = snd_hda_codec_reset(codec); + if (err < 0) { + codec_err(codec, "The codec is being used, can't free.\n"); + return err; + } + snd_hda_sysfs_clear(codec); + return 0; +} + +static int reconfig_codec(struct hda_codec *codec) +{ + int err; + + snd_hda_power_up(codec); + codec_info(codec, "hda-codec: reconfiguring\n"); + err = snd_hda_codec_reset(codec); + if (err < 0) { + codec_err(codec, + "The codec is being used, can't reconfigure.\n"); + goto error; + } + err = snd_hda_codec_configure(codec); + if (err < 0) + goto error; + /* rebuild PCMs */ + err = snd_hda_codec_build_pcms(codec); + if (err < 0) + goto error; + /* rebuild mixers */ + err = snd_hda_codec_build_controls(codec); + if (err < 0) + goto error; + err = snd_card_register(codec->bus->card); + error: + snd_hda_power_down(codec); + return err; +} + +/* + * allocate a string at most len chars, and remove the trailing EOL + */ +static char *kstrndup_noeol(const char *src, size_t len) +{ + char *s = kstrndup(src, len, GFP_KERNEL); + char *p; + if (!s) + return NULL; + p = strchr(s, '\n'); + if (p) + *p = 0; + return s; +} + +#define CODEC_INFO_STORE(type) \ +static ssize_t type##_store(struct device *dev, \ + struct device_attribute *attr, \ + const char *buf, size_t count) \ +{ \ + struct hda_codec *codec = dev_get_drvdata(dev); \ + unsigned long val; \ + int err = kstrtoul(buf, 0, &val); \ + if (err < 0) \ + return err; \ + codec->type = val; \ + return count; \ +} + +#define CODEC_INFO_STR_STORE(type) \ +static ssize_t type##_store(struct device *dev, \ + struct device_attribute *attr, \ + const char *buf, size_t count) \ +{ \ + struct hda_codec *codec = dev_get_drvdata(dev); \ + char *s = kstrndup_noeol(buf, 64); \ + if (!s) \ + return -ENOMEM; \ + kfree(codec->type); \ + codec->type = s; \ + return count; \ +} + +CODEC_INFO_STORE(vendor_id); +CODEC_INFO_STORE(subsystem_id); +CODEC_INFO_STORE(revision_id); +CODEC_INFO_STR_STORE(vendor_name); +CODEC_INFO_STR_STORE(chip_name); +CODEC_INFO_STR_STORE(modelname); + +#define CODEC_ACTION_STORE(type) \ +static ssize_t type##_store(struct device *dev, \ + struct device_attribute *attr, \ + const char *buf, size_t count) \ +{ \ + struct hda_codec *codec = dev_get_drvdata(dev); \ + int err = 0; \ + if (*buf) \ + err = type##_codec(codec); \ + return err < 0 ? err : count; \ +} + +CODEC_ACTION_STORE(reconfig); +CODEC_ACTION_STORE(clear); + +static ssize_t init_verbs_show(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct hda_codec *codec = dev_get_drvdata(dev); + int i, len = 0; + mutex_lock(&codec->user_mutex); + for (i = 0; i < codec->init_verbs.used; i++) { + struct hda_verb *v = snd_array_elem(&codec->init_verbs, i); + len += snprintf(buf + len, PAGE_SIZE - len, + "0x%02x 0x%03x 0x%04x\n", + v->nid, v->verb, v->param); + } + mutex_unlock(&codec->user_mutex); + return len; +} + +static int parse_init_verbs(struct hda_codec *codec, const char *buf) +{ + struct hda_verb *v; + int nid, verb, param; + + if (sscanf(buf, "%i %i %i", &nid, &verb, ¶m) != 3) + return -EINVAL; + if (!nid || !verb) + return -EINVAL; + mutex_lock(&codec->user_mutex); + v = snd_array_new(&codec->init_verbs); + if (!v) { + mutex_unlock(&codec->user_mutex); + return -ENOMEM; + } + v->nid = nid; + v->verb = verb; + v->param = param; + mutex_unlock(&codec->user_mutex); + return 0; +} + +static ssize_t init_verbs_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + struct hda_codec *codec = dev_get_drvdata(dev); + int err = parse_init_verbs(codec, buf); + if (err < 0) + return err; + return count; +} + +static ssize_t hints_show(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct hda_codec *codec = dev_get_drvdata(dev); + int i, len = 0; + mutex_lock(&codec->user_mutex); + for (i = 0; i < codec->hints.used; i++) { + struct hda_hint *hint = snd_array_elem(&codec->hints, i); + len += snprintf(buf + len, PAGE_SIZE - len, + "%s = %s\n", hint->key, hint->val); + } + mutex_unlock(&codec->user_mutex); + return len; +} + +static struct hda_hint *get_hint(struct hda_codec *codec, const char *key) +{ + int i; + + for (i = 0; i < codec->hints.used; i++) { + struct hda_hint *hint = snd_array_elem(&codec->hints, i); + if (!strcmp(hint->key, key)) + return hint; + } + return NULL; +} + +static void remove_trail_spaces(char *str) +{ + char *p; + if (!*str) + return; + p = str + strlen(str) - 1; + for (; isspace(*p); p--) { + *p = 0; + if (p == str) + return; + } +} + +#define MAX_HINTS 1024 + +static int parse_hints(struct hda_codec *codec, const char *buf) +{ + char *key, *val; + struct hda_hint *hint; + int err = 0; + + buf = skip_spaces(buf); + if (!*buf || *buf == '#' || *buf == '\n') + return 0; + if (*buf == '=') + return -EINVAL; + key = kstrndup_noeol(buf, 1024); + if (!key) + return -ENOMEM; + /* extract key and val */ + val = strchr(key, '='); + if (!val) { + kfree(key); + return -EINVAL; + } + *val++ = 0; + val = skip_spaces(val); + remove_trail_spaces(key); + remove_trail_spaces(val); + mutex_lock(&codec->user_mutex); + hint = get_hint(codec, key); + if (hint) { + /* replace */ + kfree(hint->key); + hint->key = key; + hint->val = val; + goto unlock; + } + /* allocate a new hint entry */ + if (codec->hints.used >= MAX_HINTS) + hint = NULL; + else + hint = snd_array_new(&codec->hints); + if (hint) { + hint->key = key; + hint->val = val; + } else { + err = -ENOMEM; + } + unlock: + mutex_unlock(&codec->user_mutex); + if (err) + kfree(key); + return err; +} + +static ssize_t hints_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + struct hda_codec *codec = dev_get_drvdata(dev); + int err = parse_hints(codec, buf); + if (err < 0) + return err; + return count; +} + +static ssize_t user_pin_configs_show(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct hda_codec *codec = dev_get_drvdata(dev); + return pin_configs_show(codec, &codec->user_pins, buf); +} + +#define MAX_PIN_CONFIGS 32 + +static int parse_user_pin_configs(struct hda_codec *codec, const char *buf) +{ + int nid, cfg, err; + + if (sscanf(buf, "%i %i", &nid, &cfg) != 2) + return -EINVAL; + if (!nid) + return -EINVAL; + mutex_lock(&codec->user_mutex); + err = snd_hda_add_pincfg(codec, &codec->user_pins, nid, cfg); + mutex_unlock(&codec->user_mutex); + return err; +} + +static ssize_t user_pin_configs_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + struct hda_codec *codec = dev_get_drvdata(dev); + int err = parse_user_pin_configs(codec, buf); + if (err < 0) + return err; + return count; +} + +/* sysfs attributes exposed only when CONFIG_SND_HDA_RECONFIG=y */ +static DEVICE_ATTR_RW(init_verbs); +static DEVICE_ATTR_RW(hints); +static DEVICE_ATTR_RW(user_pin_configs); +static DEVICE_ATTR_WO(reconfig); +static DEVICE_ATTR_WO(clear); + +/* + * Look for hint string + */ +const char *snd_hda_get_hint(struct hda_codec *codec, const char *key) +{ + struct hda_hint *hint = get_hint(codec, key); + return hint ? hint->val : NULL; +} +EXPORT_SYMBOL_GPL(snd_hda_get_hint); + +int snd_hda_get_bool_hint(struct hda_codec *codec, const char *key) +{ + const char *p; + int ret; + + mutex_lock(&codec->user_mutex); + p = snd_hda_get_hint(codec, key); + if (!p || !*p) + ret = -ENOENT; + else { + switch (toupper(*p)) { + case 'T': /* true */ + case 'Y': /* yes */ + case '1': + ret = 1; + break; + default: + ret = 0; + break; + } + } + mutex_unlock(&codec->user_mutex); + return ret; +} +EXPORT_SYMBOL_GPL(snd_hda_get_bool_hint); + +int snd_hda_get_int_hint(struct hda_codec *codec, const char *key, int *valp) +{ + const char *p; + unsigned long val; + int ret; + + mutex_lock(&codec->user_mutex); + p = snd_hda_get_hint(codec, key); + if (!p) + ret = -ENOENT; + else if (kstrtoul(p, 0, &val)) + ret = -EINVAL; + else { + *valp = val; + ret = 0; + } + mutex_unlock(&codec->user_mutex); + return ret; +} +EXPORT_SYMBOL_GPL(snd_hda_get_int_hint); +#endif /* CONFIG_SND_HDA_RECONFIG */ + +/* + * common sysfs attributes + */ +#ifdef CONFIG_SND_HDA_RECONFIG +#define RECONFIG_DEVICE_ATTR(name) DEVICE_ATTR_RW(name) +#else +#define RECONFIG_DEVICE_ATTR(name) DEVICE_ATTR_RO(name) +#endif +static RECONFIG_DEVICE_ATTR(vendor_id); +static RECONFIG_DEVICE_ATTR(subsystem_id); +static RECONFIG_DEVICE_ATTR(revision_id); +static DEVICE_ATTR_RO(afg); +static DEVICE_ATTR_RO(mfg); +static RECONFIG_DEVICE_ATTR(vendor_name); +static RECONFIG_DEVICE_ATTR(chip_name); +static RECONFIG_DEVICE_ATTR(modelname); +static DEVICE_ATTR_RO(init_pin_configs); +static DEVICE_ATTR_RO(driver_pin_configs); + + +#ifdef CONFIG_SND_HDA_PATCH_LOADER + +/* parser mode */ +enum { + LINE_MODE_NONE, + LINE_MODE_CODEC, + LINE_MODE_MODEL, + LINE_MODE_PINCFG, + LINE_MODE_VERB, + LINE_MODE_HINT, + LINE_MODE_VENDOR_ID, + LINE_MODE_SUBSYSTEM_ID, + LINE_MODE_REVISION_ID, + LINE_MODE_CHIP_NAME, + NUM_LINE_MODES, +}; + +static inline int strmatch(const char *a, const char *b) +{ + return strnicmp(a, b, strlen(b)) == 0; +} + +/* parse the contents after the line "[codec]" + * accept only the line with three numbers, and assign the current codec + */ +static void parse_codec_mode(char *buf, struct hda_bus *bus, + struct hda_codec **codecp) +{ + int vendorid, subid, caddr; + struct hda_codec *codec; + + *codecp = NULL; + if (sscanf(buf, "%i %i %i", &vendorid, &subid, &caddr) == 3) { + list_for_each_entry(codec, &bus->codec_list, list) { + if ((vendorid <= 0 || codec->vendor_id == vendorid) && + (subid <= 0 || codec->subsystem_id == subid) && + codec->addr == caddr) { + *codecp = codec; + break; + } + } + } +} + +/* parse the contents after the other command tags, [pincfg], [verb], + * [vendor_id], [subsystem_id], [revision_id], [chip_name], [hint] and [model] + * just pass to the sysfs helper (only when any codec was specified) + */ +static void parse_pincfg_mode(char *buf, struct hda_bus *bus, + struct hda_codec **codecp) +{ + parse_user_pin_configs(*codecp, buf); +} + +static void parse_verb_mode(char *buf, struct hda_bus *bus, + struct hda_codec **codecp) +{ + parse_init_verbs(*codecp, buf); +} + +static void parse_hint_mode(char *buf, struct hda_bus *bus, + struct hda_codec **codecp) +{ + parse_hints(*codecp, buf); +} + +static void parse_model_mode(char *buf, struct hda_bus *bus, + struct hda_codec **codecp) +{ + kfree((*codecp)->modelname); + (*codecp)->modelname = kstrdup(buf, GFP_KERNEL); +} + +static void parse_chip_name_mode(char *buf, struct hda_bus *bus, + struct hda_codec **codecp) +{ + kfree((*codecp)->chip_name); + (*codecp)->chip_name = kstrdup(buf, GFP_KERNEL); +} + +#define DEFINE_PARSE_ID_MODE(name) \ +static void parse_##name##_mode(char *buf, struct hda_bus *bus, \ + struct hda_codec **codecp) \ +{ \ + unsigned long val; \ + if (!kstrtoul(buf, 0, &val)) \ + (*codecp)->name = val; \ +} + +DEFINE_PARSE_ID_MODE(vendor_id); +DEFINE_PARSE_ID_MODE(subsystem_id); +DEFINE_PARSE_ID_MODE(revision_id); + + +struct hda_patch_item { + const char *tag; + const char *alias; + void (*parser)(char *buf, struct hda_bus *bus, struct hda_codec **retc); +}; + +static struct hda_patch_item patch_items[NUM_LINE_MODES] = { + [LINE_MODE_CODEC] = { + .tag = "[codec]", + .parser = parse_codec_mode, + }, + [LINE_MODE_MODEL] = { + .tag = "[model]", + .parser = parse_model_mode, + }, + [LINE_MODE_VERB] = { + .tag = "[verb]", + .alias = "[init_verbs]", + .parser = parse_verb_mode, + }, + [LINE_MODE_PINCFG] = { + .tag = "[pincfg]", + .alias = "[user_pin_configs]", + .parser = parse_pincfg_mode, + }, + [LINE_MODE_HINT] = { + .tag = "[hint]", + .alias = "[hints]", + .parser = parse_hint_mode + }, + [LINE_MODE_VENDOR_ID] = { + .tag = "[vendor_id]", + .parser = parse_vendor_id_mode, + }, + [LINE_MODE_SUBSYSTEM_ID] = { + .tag = "[subsystem_id]", + .parser = parse_subsystem_id_mode, + }, + [LINE_MODE_REVISION_ID] = { + .tag = "[revision_id]", + .parser = parse_revision_id_mode, + }, + [LINE_MODE_CHIP_NAME] = { + .tag = "[chip_name]", + .parser = parse_chip_name_mode, + }, +}; + +/* check the line starting with '[' -- change the parser mode accodingly */ +static int parse_line_mode(char *buf, struct hda_bus *bus) +{ + int i; + for (i = 0; i < ARRAY_SIZE(patch_items); i++) { + if (!patch_items[i].tag) + continue; + if (strmatch(buf, patch_items[i].tag)) + return i; + if (patch_items[i].alias && strmatch(buf, patch_items[i].alias)) + return i; + } + return LINE_MODE_NONE; +} + +/* copy one line from the buffer in fw, and update the fields in fw + * return zero if it reaches to the end of the buffer, or non-zero + * if successfully copied a line + * + * the spaces at the beginning and the end of the line are stripped + */ +static int get_line_from_fw(char *buf, int size, size_t *fw_size_p, + const void **fw_data_p) +{ + int len; + size_t fw_size = *fw_size_p; + const char *p = *fw_data_p; + + while (isspace(*p) && fw_size) { + p++; + fw_size--; + } + if (!fw_size) + return 0; + + for (len = 0; len < fw_size; len++) { + if (!*p) + break; + if (*p == '\n') { + p++; + len++; + break; + } + if (len < size) + *buf++ = *p++; + } + *buf = 0; + *fw_size_p = fw_size - len; + *fw_data_p = p; + remove_trail_spaces(buf); + return 1; +} + +/* + * load a "patch" firmware file and parse it + */ +int snd_hda_load_patch(struct hda_bus *bus, size_t fw_size, const void *fw_buf) +{ + char buf[128]; + struct hda_codec *codec; + int line_mode; + + line_mode = LINE_MODE_NONE; + codec = NULL; + while (get_line_from_fw(buf, sizeof(buf) - 1, &fw_size, &fw_buf)) { + if (!*buf || *buf == '#' || *buf == '\n') + continue; + if (*buf == '[') + line_mode = parse_line_mode(buf, bus); + else if (patch_items[line_mode].parser && + (codec || line_mode <= LINE_MODE_CODEC)) + patch_items[line_mode].parser(buf, bus, &codec); + } + return 0; +} +EXPORT_SYMBOL_GPL(snd_hda_load_patch); +#endif /* CONFIG_SND_HDA_PATCH_LOADER */ + +/* + * sysfs entries + */ +static struct attribute *hda_dev_attrs[] = { + &dev_attr_vendor_id.attr, + &dev_attr_subsystem_id.attr, + &dev_attr_revision_id.attr, + &dev_attr_afg.attr, + &dev_attr_mfg.attr, + &dev_attr_vendor_name.attr, + &dev_attr_chip_name.attr, + &dev_attr_modelname.attr, + &dev_attr_init_pin_configs.attr, + &dev_attr_driver_pin_configs.attr, +#ifdef CONFIG_PM + &dev_attr_power_on_acct.attr, + &dev_attr_power_off_acct.attr, +#endif +#ifdef CONFIG_SND_HDA_RECONFIG + &dev_attr_init_verbs.attr, + &dev_attr_hints.attr, + &dev_attr_user_pin_configs.attr, + &dev_attr_reconfig.attr, + &dev_attr_clear.attr, +#endif + NULL +}; + +static struct attribute_group hda_dev_attr_group = { + .attrs = hda_dev_attrs, +}; + +const struct attribute_group *snd_hda_dev_attr_groups[] = { + &hda_dev_attr_group, + NULL +}; + +void snd_hda_sysfs_init(struct hda_codec *codec) +{ + mutex_init(&codec->user_mutex); +#ifdef CONFIG_SND_HDA_RECONFIG + snd_array_init(&codec->init_verbs, sizeof(struct hda_verb), 32); + snd_array_init(&codec->hints, sizeof(struct hda_hint), 32); + snd_array_init(&codec->user_pins, sizeof(struct hda_pincfg), 16); +#endif +} + +void snd_hda_sysfs_clear(struct hda_codec *codec) +{ +#ifdef CONFIG_SND_HDA_RECONFIG + int i; + + /* clear init verbs */ + snd_array_free(&codec->init_verbs); + /* clear hints */ + for (i = 0; i < codec->hints.used; i++) { + struct hda_hint *hint = snd_array_elem(&codec->hints, i); + kfree(hint->key); /* we don't need to free hint->val */ + } + snd_array_free(&codec->hints); + snd_array_free(&codec->user_pins); +#endif +} diff --git a/sound/pci/hda/patch_analog.c b/sound/pci/hda/patch_analog.c index 8ed0bcc0138..40ba06eb44a 100644 --- a/sound/pci/hda/patch_analog.c +++ b/sound/pci/hda/patch_analog.c @@ -21,7 +21,6 @@ #include <linux/init.h> #include <linux/slab.h> -#include <linux/pci.h> #include <linux/module.h> #include <sound/core.h> diff --git a/sound/pci/hda/patch_ca0110.c b/sound/pci/hda/patch_ca0110.c index 30b3a4bc06e..5e65999e0d8 100644 --- a/sound/pci/hda/patch_ca0110.c +++ b/sound/pci/hda/patch_ca0110.c @@ -20,7 +20,6 @@ #include <linux/init.h> #include <linux/slab.h> -#include <linux/pci.h> #include <linux/module.h> #include <sound/core.h> #include "hda_codec.h" diff --git a/sound/pci/hda/patch_ca0132.c b/sound/pci/hda/patch_ca0132.c index 46ecdbb9053..092f2bd030b 100644 --- a/sound/pci/hda/patch_ca0132.c +++ b/sound/pci/hda/patch_ca0132.c @@ -24,7 +24,6 @@ #include <linux/init.h> #include <linux/delay.h> #include <linux/slab.h> -#include <linux/pci.h> #include <linux/mutex.h> #include <linux/module.h> #include <linux/firmware.h> @@ -868,7 +867,7 @@ static int chipio_write_data_multiple(struct hda_codec *codec, int status = 0; if (data == NULL) { - snd_printdd(KERN_ERR "chipio_write_data null ptr\n"); + codec_dbg(codec, "chipio_write_data null ptr\n"); return -EINVAL; } @@ -1407,12 +1406,12 @@ static int dspio_scp(struct hda_codec *codec, return -EINVAL; if (dir == SCP_GET && reply == NULL) { - snd_printdd(KERN_ERR "dspio_scp get but has no buffer\n"); + codec_dbg(codec, "dspio_scp get but has no buffer\n"); return -EINVAL; } if (reply != NULL && (reply_len == NULL || (*reply_len == 0))) { - snd_printdd(KERN_ERR "dspio_scp bad resp buf len parms\n"); + codec_dbg(codec, "dspio_scp bad resp buf len parms\n"); return -EINVAL; } @@ -1430,7 +1429,7 @@ static int dspio_scp(struct hda_codec *codec, sizeof(scp_reply), &ret_bytes); if (status < 0) { - snd_printdd(KERN_ERR "dspio_scp: send scp msg failed\n"); + codec_dbg(codec, "dspio_scp: send scp msg failed\n"); return status; } @@ -1449,17 +1448,17 @@ static int dspio_scp(struct hda_codec *codec, / sizeof(unsigned int); if (*reply_len < ret_size*sizeof(unsigned int)) { - snd_printdd(KERN_ERR "reply too long for buf\n"); + codec_dbg(codec, "reply too long for buf\n"); return -EINVAL; } else if (ret_size != reply_data_size) { - snd_printdd(KERN_ERR "RetLen and HdrLen .NE.\n"); + codec_dbg(codec, "RetLen and HdrLen .NE.\n"); return -EINVAL; } else { *reply_len = ret_size*sizeof(unsigned int); memcpy(reply, scp_reply.data, *reply_len); } } else { - snd_printdd(KERN_ERR "reply ill-formed or errflag set\n"); + codec_dbg(codec, "reply ill-formed or errflag set\n"); return -EIO; } @@ -1489,22 +1488,22 @@ static int dspio_alloc_dma_chan(struct hda_codec *codec, unsigned int *dma_chan) int status = 0; unsigned int size = sizeof(dma_chan); - snd_printdd(KERN_INFO " dspio_alloc_dma_chan() -- begin\n"); + codec_dbg(codec, " dspio_alloc_dma_chan() -- begin\n"); status = dspio_scp(codec, MASTERCONTROL, MASTERCONTROL_ALLOC_DMA_CHAN, SCP_GET, NULL, 0, dma_chan, &size); if (status < 0) { - snd_printdd(KERN_INFO "dspio_alloc_dma_chan: SCP Failed\n"); + codec_dbg(codec, "dspio_alloc_dma_chan: SCP Failed\n"); return status; } if ((*dma_chan + 1) == 0) { - snd_printdd(KERN_INFO "no free dma channels to allocate\n"); + codec_dbg(codec, "no free dma channels to allocate\n"); return -EBUSY; } - snd_printdd("dspio_alloc_dma_chan: chan=%d\n", *dma_chan); - snd_printdd(KERN_INFO " dspio_alloc_dma_chan() -- complete\n"); + codec_dbg(codec, "dspio_alloc_dma_chan: chan=%d\n", *dma_chan); + codec_dbg(codec, " dspio_alloc_dma_chan() -- complete\n"); return status; } @@ -1517,18 +1516,18 @@ static int dspio_free_dma_chan(struct hda_codec *codec, unsigned int dma_chan) int status = 0; unsigned int dummy = 0; - snd_printdd(KERN_INFO " dspio_free_dma_chan() -- begin\n"); - snd_printdd("dspio_free_dma_chan: chan=%d\n", dma_chan); + codec_dbg(codec, " dspio_free_dma_chan() -- begin\n"); + codec_dbg(codec, "dspio_free_dma_chan: chan=%d\n", dma_chan); status = dspio_scp(codec, MASTERCONTROL, MASTERCONTROL_ALLOC_DMA_CHAN, SCP_SET, &dma_chan, sizeof(dma_chan), NULL, &dummy); if (status < 0) { - snd_printdd(KERN_INFO "dspio_free_dma_chan: SCP Failed\n"); + codec_dbg(codec, "dspio_free_dma_chan: SCP Failed\n"); return status; } - snd_printdd(KERN_INFO " dspio_free_dma_chan() -- complete\n"); + codec_dbg(codec, " dspio_free_dma_chan() -- complete\n"); return status; } @@ -1576,14 +1575,14 @@ static int dsp_reset(struct hda_codec *codec) unsigned int res; int retry = 20; - snd_printdd("dsp_reset\n"); + codec_dbg(codec, "dsp_reset\n"); do { res = dspio_send(codec, VENDOR_DSPIO_DSP_INIT, 0); retry--; } while (res == -EIO && retry); if (!retry) { - snd_printdd("dsp_reset timeout\n"); + codec_dbg(codec, "dsp_reset timeout\n"); return -EIO; } @@ -1636,39 +1635,39 @@ static int dsp_dma_setup_common(struct hda_codec *codec, unsigned int active; bool code, yram; - snd_printdd(KERN_INFO "-- dsp_dma_setup_common() -- Begin ---------\n"); + codec_dbg(codec, "-- dsp_dma_setup_common() -- Begin ---------\n"); if (dma_chan >= DSPDMAC_DMA_CFG_CHANNEL_COUNT) { - snd_printdd(KERN_ERR "dma chan num invalid\n"); + codec_dbg(codec, "dma chan num invalid\n"); return -EINVAL; } if (dsp_is_dma_active(codec, dma_chan)) { - snd_printdd(KERN_ERR "dma already active\n"); + codec_dbg(codec, "dma already active\n"); return -EBUSY; } dsp_addx = dsp_chip_to_dsp_addx(chip_addx, &code, &yram); if (dsp_addx == INVALID_CHIP_ADDRESS) { - snd_printdd(KERN_ERR "invalid chip addr\n"); + codec_dbg(codec, "invalid chip addr\n"); return -ENXIO; } chnl_prop = DSPDMAC_CHNLPROP_AC_MASK; active = 0; - snd_printdd(KERN_INFO " dsp_dma_setup_common() start reg pgm\n"); + codec_dbg(codec, " dsp_dma_setup_common() start reg pgm\n"); if (ovly) { status = chipio_read(codec, DSPDMAC_CHNLPROP_INST_OFFSET, &chnl_prop); if (status < 0) { - snd_printdd(KERN_ERR "read CHNLPROP Reg fail\n"); + codec_dbg(codec, "read CHNLPROP Reg fail\n"); return status; } - snd_printdd(KERN_INFO "dsp_dma_setup_common() Read CHNLPROP\n"); + codec_dbg(codec, "dsp_dma_setup_common() Read CHNLPROP\n"); } if (!code) @@ -1680,20 +1679,20 @@ static int dsp_dma_setup_common(struct hda_codec *codec, status = chipio_write(codec, DSPDMAC_CHNLPROP_INST_OFFSET, chnl_prop); if (status < 0) { - snd_printdd(KERN_ERR "write CHNLPROP Reg fail\n"); + codec_dbg(codec, "write CHNLPROP Reg fail\n"); return status; } - snd_printdd(KERN_INFO " dsp_dma_setup_common() Write CHNLPROP\n"); + codec_dbg(codec, " dsp_dma_setup_common() Write CHNLPROP\n"); if (ovly) { status = chipio_read(codec, DSPDMAC_ACTIVE_INST_OFFSET, &active); if (status < 0) { - snd_printdd(KERN_ERR "read ACTIVE Reg fail\n"); + codec_dbg(codec, "read ACTIVE Reg fail\n"); return status; } - snd_printdd(KERN_INFO "dsp_dma_setup_common() Read ACTIVE\n"); + codec_dbg(codec, "dsp_dma_setup_common() Read ACTIVE\n"); } active &= (~(1 << (DSPDMAC_ACTIVE_AAR_LOBIT + dma_chan))) & @@ -1701,35 +1700,35 @@ static int dsp_dma_setup_common(struct hda_codec *codec, status = chipio_write(codec, DSPDMAC_ACTIVE_INST_OFFSET, active); if (status < 0) { - snd_printdd(KERN_ERR "write ACTIVE Reg fail\n"); + codec_dbg(codec, "write ACTIVE Reg fail\n"); return status; } - snd_printdd(KERN_INFO " dsp_dma_setup_common() Write ACTIVE\n"); + codec_dbg(codec, " dsp_dma_setup_common() Write ACTIVE\n"); status = chipio_write(codec, DSPDMAC_AUDCHSEL_INST_OFFSET(dma_chan), port_map_mask); if (status < 0) { - snd_printdd(KERN_ERR "write AUDCHSEL Reg fail\n"); + codec_dbg(codec, "write AUDCHSEL Reg fail\n"); return status; } - snd_printdd(KERN_INFO " dsp_dma_setup_common() Write AUDCHSEL\n"); + codec_dbg(codec, " dsp_dma_setup_common() Write AUDCHSEL\n"); status = chipio_write(codec, DSPDMAC_IRQCNT_INST_OFFSET(dma_chan), DSPDMAC_IRQCNT_BICNT_MASK | DSPDMAC_IRQCNT_CICNT_MASK); if (status < 0) { - snd_printdd(KERN_ERR "write IRQCNT Reg fail\n"); + codec_dbg(codec, "write IRQCNT Reg fail\n"); return status; } - snd_printdd(KERN_INFO " dsp_dma_setup_common() Write IRQCNT\n"); + codec_dbg(codec, " dsp_dma_setup_common() Write IRQCNT\n"); - snd_printdd( + codec_dbg(codec, "ChipA=0x%x,DspA=0x%x,dmaCh=%u, " "CHSEL=0x%x,CHPROP=0x%x,Active=0x%x\n", chip_addx, dsp_addx, dma_chan, port_map_mask, chnl_prop, active); - snd_printdd(KERN_INFO "-- dsp_dma_setup_common() -- Complete ------\n"); + codec_dbg(codec, "-- dsp_dma_setup_common() -- Complete ------\n"); return 0; } @@ -1755,20 +1754,20 @@ static int dsp_dma_setup(struct hda_codec *codec, const unsigned int max_dma_count = 1 << (DSPDMAC_XFRCNT_BCNT_HIBIT - DSPDMAC_XFRCNT_BCNT_LOBIT + 1); - snd_printdd(KERN_INFO "-- dsp_dma_setup() -- Begin ---------\n"); + codec_dbg(codec, "-- dsp_dma_setup() -- Begin ---------\n"); if (count > max_dma_count) { - snd_printdd(KERN_ERR "count too big\n"); + codec_dbg(codec, "count too big\n"); return -EINVAL; } dsp_addx = dsp_chip_to_dsp_addx(chip_addx, &code, &yram); if (dsp_addx == INVALID_CHIP_ADDRESS) { - snd_printdd(KERN_ERR "invalid chip addr\n"); + codec_dbg(codec, "invalid chip addr\n"); return -ENXIO; } - snd_printdd(KERN_INFO " dsp_dma_setup() start reg pgm\n"); + codec_dbg(codec, " dsp_dma_setup() start reg pgm\n"); addr_field = dsp_addx << DSPDMAC_DMACFG_DBADR_LOBIT; incr_field = 0; @@ -1785,10 +1784,10 @@ static int dsp_dma_setup(struct hda_codec *codec, status = chipio_write(codec, DSPDMAC_DMACFG_INST_OFFSET(dma_chan), dma_cfg); if (status < 0) { - snd_printdd(KERN_ERR "write DMACFG Reg fail\n"); + codec_dbg(codec, "write DMACFG Reg fail\n"); return status; } - snd_printdd(KERN_INFO " dsp_dma_setup() Write DMACFG\n"); + codec_dbg(codec, " dsp_dma_setup() Write DMACFG\n"); adr_ofs = (count - 1) << (DSPDMAC_DSPADROFS_BOFS_LOBIT + (code ? 0 : 1)); @@ -1796,10 +1795,10 @@ static int dsp_dma_setup(struct hda_codec *codec, status = chipio_write(codec, DSPDMAC_DSPADROFS_INST_OFFSET(dma_chan), adr_ofs); if (status < 0) { - snd_printdd(KERN_ERR "write DSPADROFS Reg fail\n"); + codec_dbg(codec, "write DSPADROFS Reg fail\n"); return status; } - snd_printdd(KERN_INFO " dsp_dma_setup() Write DSPADROFS\n"); + codec_dbg(codec, " dsp_dma_setup() Write DSPADROFS\n"); base_cnt = (count - 1) << DSPDMAC_XFRCNT_BCNT_LOBIT; @@ -1810,17 +1809,17 @@ static int dsp_dma_setup(struct hda_codec *codec, status = chipio_write(codec, DSPDMAC_XFRCNT_INST_OFFSET(dma_chan), xfr_cnt); if (status < 0) { - snd_printdd(KERN_ERR "write XFRCNT Reg fail\n"); + codec_dbg(codec, "write XFRCNT Reg fail\n"); return status; } - snd_printdd(KERN_INFO " dsp_dma_setup() Write XFRCNT\n"); + codec_dbg(codec, " dsp_dma_setup() Write XFRCNT\n"); - snd_printdd( + codec_dbg(codec, "ChipA=0x%x, cnt=0x%x, DMACFG=0x%x, " "ADROFS=0x%x, XFRCNT=0x%x\n", chip_addx, count, dma_cfg, adr_ofs, xfr_cnt); - snd_printdd(KERN_INFO "-- dsp_dma_setup() -- Complete ---------\n"); + codec_dbg(codec, "-- dsp_dma_setup() -- Complete ---------\n"); return 0; } @@ -1834,17 +1833,17 @@ static int dsp_dma_start(struct hda_codec *codec, unsigned int reg = 0; int status = 0; - snd_printdd(KERN_INFO "-- dsp_dma_start() -- Begin ---------\n"); + codec_dbg(codec, "-- dsp_dma_start() -- Begin ---------\n"); if (ovly) { status = chipio_read(codec, DSPDMAC_CHNLSTART_INST_OFFSET, ®); if (status < 0) { - snd_printdd(KERN_ERR "read CHNLSTART reg fail\n"); + codec_dbg(codec, "read CHNLSTART reg fail\n"); return status; } - snd_printdd(KERN_INFO "-- dsp_dma_start() Read CHNLSTART\n"); + codec_dbg(codec, "-- dsp_dma_start() Read CHNLSTART\n"); reg &= ~(DSPDMAC_CHNLSTART_EN_MASK | DSPDMAC_CHNLSTART_DIS_MASK); @@ -1853,10 +1852,10 @@ static int dsp_dma_start(struct hda_codec *codec, status = chipio_write(codec, DSPDMAC_CHNLSTART_INST_OFFSET, reg | (1 << (dma_chan + DSPDMAC_CHNLSTART_EN_LOBIT))); if (status < 0) { - snd_printdd(KERN_ERR "write CHNLSTART reg fail\n"); + codec_dbg(codec, "write CHNLSTART reg fail\n"); return status; } - snd_printdd(KERN_INFO "-- dsp_dma_start() -- Complete ---------\n"); + codec_dbg(codec, "-- dsp_dma_start() -- Complete ---------\n"); return status; } @@ -1870,17 +1869,17 @@ static int dsp_dma_stop(struct hda_codec *codec, unsigned int reg = 0; int status = 0; - snd_printdd(KERN_INFO "-- dsp_dma_stop() -- Begin ---------\n"); + codec_dbg(codec, "-- dsp_dma_stop() -- Begin ---------\n"); if (ovly) { status = chipio_read(codec, DSPDMAC_CHNLSTART_INST_OFFSET, ®); if (status < 0) { - snd_printdd(KERN_ERR "read CHNLSTART reg fail\n"); + codec_dbg(codec, "read CHNLSTART reg fail\n"); return status; } - snd_printdd(KERN_INFO "-- dsp_dma_stop() Read CHNLSTART\n"); + codec_dbg(codec, "-- dsp_dma_stop() Read CHNLSTART\n"); reg &= ~(DSPDMAC_CHNLSTART_EN_MASK | DSPDMAC_CHNLSTART_DIS_MASK); } @@ -1888,10 +1887,10 @@ static int dsp_dma_stop(struct hda_codec *codec, status = chipio_write(codec, DSPDMAC_CHNLSTART_INST_OFFSET, reg | (1 << (dma_chan + DSPDMAC_CHNLSTART_DIS_LOBIT))); if (status < 0) { - snd_printdd(KERN_ERR "write CHNLSTART reg fail\n"); + codec_dbg(codec, "write CHNLSTART reg fail\n"); return status; } - snd_printdd(KERN_INFO "-- dsp_dma_stop() -- Complete ---------\n"); + codec_dbg(codec, "-- dsp_dma_stop() -- Complete ---------\n"); return status; } @@ -1974,17 +1973,17 @@ static int dsp_allocate_ports(struct hda_codec *codec, { int status; - snd_printdd(KERN_INFO " dsp_allocate_ports() -- begin\n"); + codec_dbg(codec, " dsp_allocate_ports() -- begin\n"); if ((rate_multi != 1) && (rate_multi != 2) && (rate_multi != 4)) { - snd_printdd(KERN_ERR "bad rate multiple\n"); + codec_dbg(codec, "bad rate multiple\n"); return -EINVAL; } status = dsp_allocate_router_ports(codec, num_chans, rate_multi, 0, port_map); - snd_printdd(KERN_INFO " dsp_allocate_ports() -- complete\n"); + codec_dbg(codec, " dsp_allocate_ports() -- complete\n"); return status; } @@ -2001,7 +2000,7 @@ static int dsp_allocate_ports_format(struct hda_codec *codec, unsigned int rate_multi = sample_rate_mul / sample_rate_div; if ((rate_multi != 1) && (rate_multi != 2) && (rate_multi != 4)) { - snd_printdd(KERN_ERR "bad rate multiple\n"); + codec_dbg(codec, "bad rate multiple\n"); return -EINVAL; } @@ -2019,14 +2018,14 @@ static int dsp_free_ports(struct hda_codec *codec) { int status; - snd_printdd(KERN_INFO " dsp_free_ports() -- begin\n"); + codec_dbg(codec, " dsp_free_ports() -- begin\n"); status = dsp_free_router_ports(codec); if (status < 0) { - snd_printdd(KERN_ERR "free router ports fail\n"); + codec_dbg(codec, "free router ports fail\n"); return status; } - snd_printdd(KERN_INFO " dsp_free_ports() -- complete\n"); + codec_dbg(codec, " dsp_free_ports() -- complete\n"); return status; } @@ -2092,8 +2091,6 @@ static int dma_set_state(struct dma_engine *dma, enum dma_state state) { bool cmd; - snd_printdd("dma_set_state state=%d\n", state); - switch (state) { case DMA_STATE_STOP: cmd = false; @@ -2196,7 +2193,7 @@ static int dspxfr_hci_write(struct hda_codec *codec, unsigned int count; if (fls == NULL || fls->chip_addr != g_chip_addr_magic_value) { - snd_printdd(KERN_ERR "hci_write invalid params\n"); + codec_dbg(codec, "hci_write invalid params\n"); return -EINVAL; } @@ -2205,7 +2202,7 @@ static int dspxfr_hci_write(struct hda_codec *codec, while (count >= 2) { status = chipio_write(codec, data[0], data[1]); if (status < 0) { - snd_printdd(KERN_ERR "hci_write chipio failed\n"); + codec_dbg(codec, "hci_write chipio failed\n"); return status; } count -= 2; @@ -2265,12 +2262,12 @@ static int dspxfr_one_seg(struct hda_codec *codec, } if (hci_write && (!fls || is_last(fls))) { - snd_printdd("hci_write\n"); + codec_dbg(codec, "hci_write\n"); return dspxfr_hci_write(codec, hci_write); } if (fls == NULL || dma_engine == NULL || port_map_mask == 0) { - snd_printdd("Invalid Params\n"); + codec_dbg(codec, "Invalid Params\n"); return -EINVAL; } @@ -2286,7 +2283,7 @@ static int dspxfr_one_seg(struct hda_codec *codec, if (!UC_RANGE(chip_addx, words_to_write) && !X_RANGE_ALL(chip_addx, words_to_write) && !Y_RANGE_ALL(chip_addx, words_to_write)) { - snd_printdd("Invalid chip_addx Params\n"); + codec_dbg(codec, "Invalid chip_addx Params\n"); return -EINVAL; } @@ -2296,7 +2293,7 @@ static int dspxfr_one_seg(struct hda_codec *codec, buffer_addx = dma_get_buffer_addr(dma_engine); if (buffer_addx == NULL) { - snd_printdd(KERN_ERR "dma_engine buffer NULL\n"); + codec_dbg(codec, "dma_engine buffer NULL\n"); return -EINVAL; } @@ -2309,7 +2306,7 @@ static int dspxfr_one_seg(struct hda_codec *codec, (num_chans * sample_rate_mul / sample_rate_div)); if (hda_frame_size_words == 0) { - snd_printdd(KERN_ERR "frmsz zero\n"); + codec_dbg(codec, "frmsz zero\n"); return -EINVAL; } @@ -2317,14 +2314,14 @@ static int dspxfr_one_seg(struct hda_codec *codec, (unsigned int)(UC_RANGE(chip_addx, 1) ? 65536 : 32768)); buffer_size_words -= buffer_size_words % hda_frame_size_words; - snd_printdd( + codec_dbg(codec, "chpadr=0x%08x frmsz=%u nchan=%u " "rate_mul=%u div=%u bufsz=%u\n", chip_addx, hda_frame_size_words, num_chans, sample_rate_mul, sample_rate_div, buffer_size_words); if (buffer_size_words < hda_frame_size_words) { - snd_printdd(KERN_ERR "dspxfr_one_seg:failed\n"); + codec_dbg(codec, "dspxfr_one_seg:failed\n"); return -EINVAL; } @@ -2338,7 +2335,7 @@ static int dspxfr_one_seg(struct hda_codec *codec, while (words_to_write != 0) { run_size_words = min(buffer_size_words, words_to_write); - snd_printdd("dspxfr (seg loop)cnt=%u rs=%u remainder=%u\n", + codec_dbg(codec, "dspxfr (seg loop)cnt=%u rs=%u remainder=%u\n", words_to_write, run_size_words, remainder_words); dma_xfer(dma_engine, data, run_size_words*sizeof(u32)); if (!comm_dma_setup_done) { @@ -2360,7 +2357,7 @@ static int dspxfr_one_seg(struct hda_codec *codec, if (status < 0) return status; if (!dsp_is_dma_active(codec, dma_chan)) { - snd_printdd(KERN_ERR "dspxfr:DMA did not start\n"); + codec_dbg(codec, "dspxfr:DMA did not start\n"); return -EIO; } status = dma_set_state(dma_engine, DMA_STATE_RUN); @@ -2392,7 +2389,7 @@ static int dspxfr_one_seg(struct hda_codec *codec, if (dma_active) break; - snd_printdd(KERN_INFO "+++++ DMA complete\n"); + codec_dbg(codec, "+++++ DMA complete\n"); dma_set_state(dma_engine, DMA_STATE_STOP); status = dma_reset(dma_engine); @@ -2466,7 +2463,7 @@ static int dspxfr_image(struct hda_codec *codec, hda_format, &response); if (status < 0) { - snd_printdd(KERN_ERR "set converter format fail\n"); + codec_dbg(codec, "set converter format fail\n"); goto exit; } @@ -2481,7 +2478,7 @@ static int dspxfr_image(struct hda_codec *codec, if (ovly) { status = dspio_alloc_dma_chan(codec, &dma_chan); if (status < 0) { - snd_printdd(KERN_ERR "alloc dmachan fail\n"); + codec_dbg(codec, "alloc dmachan fail\n"); dma_chan = INVALID_DMA_CHANNEL; goto exit; } @@ -2491,7 +2488,7 @@ static int dspxfr_image(struct hda_codec *codec, status = dsp_allocate_ports_format(codec, hda_format, &port_map_mask); if (status < 0) { - snd_printdd(KERN_ERR "alloc ports fail\n"); + codec_dbg(codec, "alloc ports fail\n"); goto exit; } @@ -2499,13 +2496,13 @@ static int dspxfr_image(struct hda_codec *codec, status = codec_set_converter_stream_channel(codec, WIDGET_CHIP_CTRL, stream_id, 0, &response); if (status < 0) { - snd_printdd(KERN_ERR "set stream chan fail\n"); + codec_dbg(codec, "set stream chan fail\n"); goto exit; } while ((fls_data != NULL) && !is_last(fls_data)) { if (!is_valid(fls_data)) { - snd_printdd(KERN_ERR "FLS check fail\n"); + codec_dbg(codec, "FLS check fail\n"); status = -EINVAL; goto exit; } @@ -2548,7 +2545,7 @@ exit: */ static void dspload_post_setup(struct hda_codec *codec) { - snd_printdd(KERN_INFO "---- dspload_post_setup ------\n"); + codec_dbg(codec, "---- dspload_post_setup ------\n"); /*set DSP speaker to 2.0 configuration*/ chipio_write(codec, XRAM_XRAM_INST_OFFSET(0x18), 0x08080080); @@ -2586,7 +2583,7 @@ static int dspload_image(struct hda_codec *codec, unsigned int sample_rate; unsigned short channels; - snd_printdd(KERN_INFO "---- dspload_image begin ------\n"); + codec_dbg(codec, "---- dspload_image begin ------\n"); if (router_chans == 0) { if (!ovly) router_chans = DMA_TRANSFER_FRAME_SIZE_NWORDS; @@ -2603,27 +2600,27 @@ static int dspload_image(struct hda_codec *codec, } do { - snd_printdd(KERN_INFO "Ready to program DMA\n"); + codec_dbg(codec, "Ready to program DMA\n"); if (!ovly) status = dsp_reset(codec); if (status < 0) break; - snd_printdd(KERN_INFO "dsp_reset() complete\n"); + codec_dbg(codec, "dsp_reset() complete\n"); status = dspxfr_image(codec, fls, reloc, sample_rate, channels, ovly); if (status < 0) break; - snd_printdd(KERN_INFO "dspxfr_image() complete\n"); + codec_dbg(codec, "dspxfr_image() complete\n"); if (autostart && !ovly) { dspload_post_setup(codec); status = dsp_set_run_state(codec); } - snd_printdd(KERN_INFO "LOAD FINISHED\n"); + codec_dbg(codec, "LOAD FINISHED\n"); } while (0); return status; @@ -3132,7 +3129,7 @@ static int ca0132_select_out(struct hda_codec *codec) unsigned int tmp; int err; - snd_printdd(KERN_INFO "ca0132_select_out\n"); + codec_dbg(codec, "ca0132_select_out\n"); snd_hda_power_up(codec); @@ -3150,7 +3147,7 @@ static int ca0132_select_out(struct hda_codec *codec) spec->cur_out_type = SPEAKER_OUT; if (spec->cur_out_type == SPEAKER_OUT) { - snd_printdd(KERN_INFO "ca0132_select_out speaker\n"); + codec_dbg(codec, "ca0132_select_out speaker\n"); /*speaker out config*/ tmp = FLOAT_ONE; err = dspio_set_uint_param(codec, 0x80, 0x04, tmp); @@ -3183,7 +3180,7 @@ static int ca0132_select_out(struct hda_codec *codec) snd_hda_set_pin_ctl(codec, spec->out_pins[0], pin_ctl | PIN_OUT); } else { - snd_printdd(KERN_INFO "ca0132_select_out hp\n"); + codec_dbg(codec, "ca0132_select_out hp\n"); /*headphone out config*/ tmp = FLOAT_ZERO; err = dspio_set_uint_param(codec, 0x80, 0x04, tmp); @@ -3288,7 +3285,7 @@ static int ca0132_select_mic(struct hda_codec *codec) int jack_present; int auto_jack; - snd_printdd(KERN_INFO "ca0132_select_mic\n"); + codec_dbg(codec, "ca0132_select_mic\n"); snd_hda_power_up(codec); @@ -3410,7 +3407,7 @@ static int ca0132_effects_set(struct hda_codec *codec, hda_nid_t nid, long val) val = 0; } - snd_printdd(KERN_INFO "ca0132_effect_set: nid=0x%x, val=%ld\n", + codec_dbg(codec, "ca0132_effect_set: nid=0x%x, val=%ld\n", nid, val); on = (val == 0) ? FLOAT_ZERO : FLOAT_ONE; @@ -3432,7 +3429,7 @@ static int ca0132_pe_switch_set(struct hda_codec *codec) hda_nid_t nid; int i, ret = 0; - snd_printdd(KERN_INFO "ca0132_pe_switch_set: val=%ld\n", + codec_dbg(codec, "ca0132_pe_switch_set: val=%ld\n", spec->effects_switch[PLAY_ENHANCEMENT - EFFECT_START_NID]); i = OUT_EFFECT_START_NID - EFFECT_START_NID; @@ -3478,7 +3475,7 @@ static int ca0132_cvoice_switch_set(struct hda_codec *codec) int i, ret = 0; unsigned int oldval; - snd_printdd(KERN_INFO "ca0132_cvoice_switch_set: val=%ld\n", + codec_dbg(codec, "ca0132_cvoice_switch_set: val=%ld\n", spec->effects_switch[CRYSTAL_VOICE - EFFECT_START_NID]); i = IN_EFFECT_START_NID - EFFECT_START_NID; @@ -3608,7 +3605,7 @@ static int ca0132_voicefx_put(struct snd_kcontrol *kcontrol, if (sel >= items) return 0; - snd_printdd(KERN_INFO "ca0132_voicefx_put: sel=%d, preset=%s\n", + codec_dbg(codec, "ca0132_voicefx_put: sel=%d, preset=%s\n", sel, ca0132_voicefx_presets[sel].name); /* @@ -3679,7 +3676,7 @@ static int ca0132_switch_put(struct snd_kcontrol *kcontrol, long *valp = ucontrol->value.integer.value; int changed = 1; - snd_printdd(KERN_INFO "ca0132_switch_put: nid=0x%x, val=%ld\n", + codec_dbg(codec, "ca0132_switch_put: nid=0x%x, val=%ld\n", nid, *valp); snd_hda_power_up(codec); @@ -4142,7 +4139,7 @@ static void ca0132_set_dmic(struct hda_codec *codec, int enable) u8 val; unsigned int oldval; - snd_printdd(KERN_INFO "ca0132_set_dmic: enable=%d\n", enable); + codec_dbg(codec, "ca0132_set_dmic: enable=%d\n", enable); oldval = stop_mic1(codec); ca0132_set_vipsource(codec, 0); @@ -4250,7 +4247,7 @@ static void ca0132_refresh_widget_caps(struct hda_codec *codec) int i; hda_nid_t nid; - snd_printdd(KERN_INFO "ca0132_refresh_widget_caps.\n"); + codec_dbg(codec, "ca0132_refresh_widget_caps.\n"); nid = codec->start_nid; for (i = 0; i < codec->num_nodes; i++, nid++) codec->wcaps[i] = snd_hda_param_read(codec, nid, @@ -4394,7 +4391,7 @@ static void ca0132_process_dsp_response(struct hda_codec *codec) { struct ca0132_spec *spec = codec->spec; - snd_printdd(KERN_INFO "ca0132_process_dsp_response\n"); + codec_dbg(codec, "ca0132_process_dsp_response\n"); if (spec->wait_scp) { if (dspio_get_response_data(codec) >= 0) spec->wait_scp = 0; @@ -4413,7 +4410,7 @@ static void ca0132_unsol_event(struct hda_codec *codec, unsigned int res) res = snd_hda_jack_get_action(codec, (res >> AC_UNSOL_RES_TAG_SHIFT) & 0x3f); - snd_printdd(KERN_INFO "snd_hda_jack_get_action: 0x%x\n", res); + codec_dbg(codec, "snd_hda_jack_get_action: 0x%x\n", res); switch (res) { case UNSOL_TAG_HP: @@ -4658,7 +4655,7 @@ static int patch_ca0132(struct hda_codec *codec) struct ca0132_spec *spec; int err; - snd_printdd("patch_ca0132\n"); + codec_dbg(codec, "patch_ca0132\n"); spec = kzalloc(sizeof(*spec), GFP_KERNEL); if (!spec) diff --git a/sound/pci/hda/patch_cirrus.c b/sound/pci/hda/patch_cirrus.c index fc492ac24ca..387f0b55188 100644 --- a/sound/pci/hda/patch_cirrus.c +++ b/sound/pci/hda/patch_cirrus.c @@ -20,7 +20,6 @@ #include <linux/init.h> #include <linux/slab.h> -#include <linux/pci.h> #include <linux/module.h> #include <sound/core.h> #include <sound/tlv.h> diff --git a/sound/pci/hda/patch_cmedia.c b/sound/pci/hda/patch_cmedia.c index 9c6ce73b03c..061ea5965dd 100644 --- a/sound/pci/hda/patch_cmedia.c +++ b/sound/pci/hda/patch_cmedia.c @@ -23,7 +23,6 @@ #include <linux/init.h> #include <linux/slab.h> -#include <linux/pci.h> #include <linux/module.h> #include <sound/core.h> #include "hda_codec.h" @@ -32,6 +31,9 @@ #include "hda_jack.h" #include "hda_generic.h" +#undef ENABLE_CMI_STATIC_QUIRKS + +#ifdef ENABLE_CMI_STATIC_QUIRKS #define NUM_PINS 11 @@ -45,10 +47,12 @@ enum { CMI_AUTO, /* let driver guess it */ CMI_MODELS }; +#endif /* ENABLE_CMI_STATIC_QUIRKS */ struct cmi_spec { struct hda_gen_spec gen; +#ifdef ENABLE_CMI_STATIC_QUIRKS /* below are only for static models */ int board_config; @@ -81,8 +85,10 @@ struct cmi_spec { /* multichannel pins */ struct hda_verb multi_init[9]; /* 2 verbs for each pin + terminator */ +#endif /* ENABLE_CMI_STATIC_QUIRKS */ }; +#ifdef ENABLE_CMI_STATIC_QUIRKS /* * input MUX */ @@ -566,6 +572,7 @@ static const struct hda_codec_ops cmi9880_patch_ops = { .init = cmi9880_init, .free = cmi9880_free, }; +#endif /* ENABLE_CMI_STATIC_QUIRKS */ /* * stuff for auto-parser @@ -588,15 +595,20 @@ static int cmi_parse_auto_config(struct hda_codec *codec) err = snd_hda_parse_pin_defcfg(codec, cfg, NULL, 0); if (err < 0) - return err; + goto error; err = snd_hda_gen_parse_auto_config(codec, cfg); if (err < 0) - return err; + goto error; codec->patch_ops = cmi_auto_patch_ops; return 0; + + error: + snd_hda_gen_free(codec); + return err; } + static int patch_cmi9880(struct hda_codec *codec) { struct cmi_spec *spec; @@ -606,23 +618,18 @@ static int patch_cmi9880(struct hda_codec *codec) return -ENOMEM; codec->spec = spec; +#ifdef ENABLE_CMI_STATIC_QUIRKS spec->board_config = snd_hda_check_board_config(codec, CMI_MODELS, cmi9880_models, cmi9880_cfg_tbl); if (spec->board_config < 0) { - snd_printdd(KERN_INFO "hda_codec: %s: BIOS auto-probing.\n", + codec_dbg(codec, "%s: BIOS auto-probing.\n", codec->chip_name); spec->board_config = CMI_AUTO; /* try everything */ } - if (spec->board_config == CMI_AUTO) { - int err = cmi_parse_auto_config(codec); - if (err < 0) { - snd_hda_gen_free(codec); - return err; - } - return 0; - } + if (spec->board_config == CMI_AUTO) + return cmi_parse_auto_config(codec); /* copy default DAC NIDs */ memcpy(spec->dac_nids, cmi9880_dac_nids, sizeof(spec->dac_nids)); @@ -669,6 +676,9 @@ static int patch_cmi9880(struct hda_codec *codec) codec->patch_ops = cmi9880_patch_ops; return 0; +#else + return cmi_parse_auto_config(codec); +#endif } /* diff --git a/sound/pci/hda/patch_conexant.c b/sound/pci/hda/patch_conexant.c index bcf91bea331..1dc7e974f3b 100644 --- a/sound/pci/hda/patch_conexant.c +++ b/sound/pci/hda/patch_conexant.c @@ -23,7 +23,6 @@ #include <linux/init.h> #include <linux/delay.h> #include <linux/slab.h> -#include <linux/pci.h> #include <linux/module.h> #include <sound/core.h> #include <sound/jack.h> @@ -35,7 +34,7 @@ #include "hda_jack.h" #include "hda_generic.h" -#define ENABLE_CXT_STATIC_QUIRKS +#undef ENABLE_CXT_STATIC_QUIRKS #define CXT_PIN_DIR_IN 0x00 #define CXT_PIN_DIR_OUT 0x01 @@ -68,6 +67,12 @@ struct conexant_spec { unsigned int parse_flags; /* flag for snd_hda_parse_pin_defcfg() */ + /* OPLC XO specific */ + bool recording; + bool dc_enable; + unsigned int dc_input_bias; /* offset into olpc_xo_dc_bias */ + struct nid_path *dc_mode_path; + #ifdef ENABLE_CXT_STATIC_QUIRKS const struct snd_kcontrol_new *mixers[5]; int num_mixers; @@ -123,19 +128,6 @@ struct conexant_spec { unsigned int hp_laptop:1; unsigned int asus:1; - unsigned int ext_mic_present; - unsigned int recording; - void (*capture_prepare)(struct hda_codec *codec); - void (*capture_cleanup)(struct hda_codec *codec); - - /* OLPC XO-1.5 supports DC input mode (e.g. for use with analog sensors) - * through the microphone jack. - * When the user enables this through a mixer switch, both internal and - * external microphones are disabled. Gain is fixed at 0dB. In this mode, - * we also allow the bias to be configured through a separate mixer - * control. */ - unsigned int dc_enable; - unsigned int dc_input_bias; /* offset into cxt5066_olpc_dc_bias */ unsigned int mic_boost; /* offset into cxt5066_analog_mic_boost */ #endif /* ENABLE_CXT_STATIC_QUIRKS */ }; @@ -253,8 +245,6 @@ static int conexant_capture_pcm_prepare(struct hda_pcm_stream *hinfo, struct snd_pcm_substream *substream) { struct conexant_spec *spec = codec->spec; - if (spec->capture_prepare) - spec->capture_prepare(codec); snd_hda_codec_setup_stream(codec, spec->adc_nids[substream->number], stream_tag, 0, format); return 0; @@ -266,8 +256,6 @@ static int conexant_capture_pcm_cleanup(struct hda_pcm_stream *hinfo, { struct conexant_spec *spec = codec->spec; snd_hda_codec_cleanup_stream(codec, spec->adc_nids[substream->number]); - if (spec->capture_cleanup) - spec->capture_cleanup(codec); return 0; } @@ -457,9 +445,7 @@ static int conexant_init(struct hda_codec *codec) static void conexant_free(struct hda_codec *codec) { - struct conexant_spec *spec = codec->spec; - snd_hda_detach_beep_device(codec); - kfree(spec); + kfree(codec->spec); } static const struct snd_kcontrol_new cxt_capture_mixers[] = { @@ -673,14 +659,6 @@ static const struct hda_input_mux cxt5045_capture_source_benq = { } }; -static const struct hda_input_mux cxt5045_capture_source_hp530 = { - .num_items = 2, - .items = { - { "Mic", 0x1 }, - { "Internal Mic", 0x2 }, - } -}; - /* turn on/off EAPD (+ mute HP) as a master switch */ static int cxt5045_hp_master_sw_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) @@ -796,28 +774,6 @@ static const struct snd_kcontrol_new cxt5045_benq_mixers[] = { {} }; -static const struct snd_kcontrol_new cxt5045_mixers_hp530[] = { - HDA_CODEC_VOLUME("Capture Volume", 0x1a, 0x00, HDA_INPUT), - HDA_CODEC_MUTE("Capture Switch", 0x1a, 0x0, HDA_INPUT), - HDA_CODEC_VOLUME("PCM Playback Volume", 0x17, 0x0, HDA_INPUT), - HDA_CODEC_MUTE("PCM Playback Switch", 0x17, 0x0, HDA_INPUT), - HDA_CODEC_VOLUME("Internal Mic Playback Volume", 0x17, 0x2, HDA_INPUT), - HDA_CODEC_MUTE("Internal Mic Playback Switch", 0x17, 0x2, HDA_INPUT), - HDA_CODEC_VOLUME("Mic Playback Volume", 0x17, 0x1, HDA_INPUT), - HDA_CODEC_MUTE("Mic Playback Switch", 0x17, 0x1, HDA_INPUT), - HDA_BIND_VOL("Master Playback Volume", &cxt5045_hp_bind_master_vol), - { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Master Playback Switch", - .info = cxt_eapd_info, - .get = cxt_eapd_get, - .put = cxt5045_hp_master_sw_put, - .private_value = 0x10, - }, - - {} -}; - static const struct hda_verb cxt5045_init_verbs[] = { /* Line in, Mic */ {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN|AC_PINCTL_VREF_80 }, @@ -1000,7 +956,6 @@ enum { CXT5045_LAPTOP_MICSENSE, CXT5045_LAPTOP_HPMICSENSE, CXT5045_BENQ, - CXT5045_LAPTOP_HP530, #ifdef CONFIG_SND_DEBUG CXT5045_TEST, #endif @@ -1013,7 +968,6 @@ static const char * const cxt5045_models[CXT5045_MODELS] = { [CXT5045_LAPTOP_MICSENSE] = "laptop-micsense", [CXT5045_LAPTOP_HPMICSENSE] = "laptop-hpmicsense", [CXT5045_BENQ] = "benq", - [CXT5045_LAPTOP_HP530] = "laptop-hp530", #ifdef CONFIG_SND_DEBUG [CXT5045_TEST] = "test", #endif @@ -1021,8 +975,6 @@ static const char * const cxt5045_models[CXT5045_MODELS] = { }; static const struct snd_pci_quirk cxt5045_cfg_tbl[] = { - SND_PCI_QUIRK(0x103c, 0x30d5, "HP 530", CXT5045_LAPTOP_HP530), - SND_PCI_QUIRK(0x1179, 0xff31, "Toshiba P105", CXT5045_LAPTOP_MICSENSE), SND_PCI_QUIRK(0x152d, 0x0753, "Benq R55E", CXT5045_BENQ), SND_PCI_QUIRK(0x1734, 0x10ad, "Fujitsu Si1520", CXT5045_LAPTOP_MICSENSE), SND_PCI_QUIRK(0x1734, 0x10cb, "Fujitsu Si3515", CXT5045_LAPTOP_HPMICSENSE), @@ -1113,14 +1065,6 @@ static int patch_cxt5045(struct hda_codec *codec) spec->num_mixers = 2; codec->patch_ops.init = cxt5045_init; break; - case CXT5045_LAPTOP_HP530: - codec->patch_ops.unsol_event = cxt5045_hp_unsol_event; - spec->input_mux = &cxt5045_capture_source_hp530; - spec->num_init_verbs = 2; - spec->init_verbs[1] = cxt5045_hp_sense_init_verbs; - spec->mixers[0] = cxt5045_mixers_hp530; - codec->patch_ops.init = cxt5045_init; - break; #ifdef CONFIG_SND_DEBUG case CXT5045_TEST: spec->input_mux = &cxt5045_test_capture_source; @@ -1940,11 +1884,6 @@ static const hda_nid_t cxt5066_adc_nids[3] = { 0x14, 0x15, 0x16 }; static const hda_nid_t cxt5066_capsrc_nids[1] = { 0x17 }; static const hda_nid_t cxt5066_digout_pin_nids[2] = { 0x20, 0x22 }; -/* OLPC's microphone port is DC coupled for use with external sensors, - * therefore we use a 50% mic bias in order to center the input signal with - * the DC input range of the codec. */ -#define CXT5066_OLPC_EXT_MIC_BIAS PIN_VREF50 - static const struct hda_channel_mode cxt5066_modes[1] = { { 2, NULL }, }; @@ -1959,7 +1898,8 @@ static void cxt5066_update_speaker(struct hda_codec *codec) struct conexant_spec *spec = codec->spec; unsigned int pinctl; - snd_printdd("CXT5066: update speaker, hp_present=%d, cur_eapd=%d\n", + codec_dbg(codec, + "CXT5066: update speaker, hp_present=%d, cur_eapd=%d\n", spec->hp_present, spec->cur_eapd); /* Port A (HP) */ @@ -1997,88 +1937,6 @@ static int cxt5066_hp_master_sw_put(struct snd_kcontrol *kcontrol, return 1; } -static const struct hda_input_mux cxt5066_olpc_dc_bias = { - .num_items = 3, - .items = { - { "Off", PIN_IN }, - { "50%", PIN_VREF50 }, - { "80%", PIN_VREF80 }, - }, -}; - -static int cxt5066_set_olpc_dc_bias(struct hda_codec *codec) -{ - struct conexant_spec *spec = codec->spec; - /* Even though port F is the DC input, the bias is controlled on port B. - * we also leave that port as an active input (but unselected) in DC mode - * just in case that is necessary to make the bias setting take effect. */ - return snd_hda_set_pin_ctl_cache(codec, 0x1a, - cxt5066_olpc_dc_bias.items[spec->dc_input_bias].index); -} - -/* OLPC defers mic widget control until when capture is started because the - * microphone LED comes on as soon as these settings are put in place. if we - * did this before recording, it would give the false indication that recording - * is happening when it is not. */ -static void cxt5066_olpc_select_mic(struct hda_codec *codec) -{ - struct conexant_spec *spec = codec->spec; - if (!spec->recording) - return; - - if (spec->dc_enable) { - /* in DC mode we ignore presence detection and just use the jack - * through our special DC port */ - const struct hda_verb enable_dc_mode[] = { - /* disble internal mic, port C */ - {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, 0}, - - /* enable DC capture, port F */ - {0x1e, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, - {}, - }; - - snd_hda_sequence_write(codec, enable_dc_mode); - /* port B input disabled (and bias set) through the following call */ - cxt5066_set_olpc_dc_bias(codec); - return; - } - - /* disable DC (port F) */ - snd_hda_set_pin_ctl(codec, 0x1e, 0); - - /* external mic, port B */ - snd_hda_set_pin_ctl(codec, 0x1a, - spec->ext_mic_present ? CXT5066_OLPC_EXT_MIC_BIAS : 0); - - /* internal mic, port C */ - snd_hda_set_pin_ctl(codec, 0x1b, - spec->ext_mic_present ? 0 : PIN_VREF80); -} - -/* toggle input of built-in and mic jack appropriately */ -static void cxt5066_olpc_automic(struct hda_codec *codec) -{ - struct conexant_spec *spec = codec->spec; - unsigned int present; - - if (spec->dc_enable) /* don't do presence detection in DC mode */ - return; - - present = snd_hda_codec_read(codec, 0x1a, 0, - AC_VERB_GET_PIN_SENSE, 0) & 0x80000000; - if (present) - snd_printdd("CXT5066: external microphone detected\n"); - else - snd_printdd("CXT5066: external microphone absent\n"); - - snd_hda_codec_write(codec, 0x17, 0, AC_VERB_SET_CONNECT_SEL, - present ? 0 : 1); - spec->ext_mic_present = !!present; - - cxt5066_olpc_select_mic(codec); -} - /* toggle input of built-in digital mic and mic jack appropriately */ static void cxt5066_vostro_automic(struct hda_codec *codec) { @@ -2110,10 +1968,10 @@ static void cxt5066_vostro_automic(struct hda_codec *codec) present = snd_hda_jack_detect(codec, 0x1a); if (present) { - snd_printdd("CXT5066: external microphone detected\n"); + codec_dbg(codec, "CXT5066: external microphone detected\n"); snd_hda_sequence_write(codec, ext_mic_present); } else { - snd_printdd("CXT5066: external microphone absent\n"); + codec_dbg(codec, "CXT5066: external microphone absent\n"); snd_hda_sequence_write(codec, ext_mic_absent); } } @@ -2138,10 +1996,10 @@ static void cxt5066_ideapad_automic(struct hda_codec *codec) present = snd_hda_jack_detect(codec, 0x1b); if (present) { - snd_printdd("CXT5066: external microphone detected\n"); + codec_dbg(codec, "CXT5066: external microphone detected\n"); snd_hda_sequence_write(codec, ext_mic_present); } else { - snd_printdd("CXT5066: external microphone absent\n"); + codec_dbg(codec, "CXT5066: external microphone absent\n"); snd_hda_sequence_write(codec, ext_mic_absent); } } @@ -2153,7 +2011,7 @@ static void cxt5066_asus_automic(struct hda_codec *codec) unsigned int present; present = snd_hda_jack_detect(codec, 0x1b); - snd_printdd("CXT5066: external microphone present=%d\n", present); + codec_dbg(codec, "CXT5066: external microphone present=%d\n", present); snd_hda_codec_write(codec, 0x17, 0, AC_VERB_SET_CONNECT_SEL, present ? 1 : 0); } @@ -2165,7 +2023,7 @@ static void cxt5066_hp_laptop_automic(struct hda_codec *codec) unsigned int present; present = snd_hda_jack_detect(codec, 0x1b); - snd_printdd("CXT5066: external microphone present=%d\n", present); + codec_dbg(codec, "CXT5066: external microphone present=%d\n", present); snd_hda_codec_write(codec, 0x17, 0, AC_VERB_SET_CONNECT_SEL, present ? 1 : 3); } @@ -2204,13 +2062,13 @@ static void cxt5066_thinkpad_automic(struct hda_codec *codec) ext_present = snd_hda_jack_detect(codec, 0x1b); dock_present = snd_hda_jack_detect(codec, 0x1a); if (ext_present) { - snd_printdd("CXT5066: external microphone detected\n"); + codec_dbg(codec, "CXT5066: external microphone detected\n"); snd_hda_sequence_write(codec, ext_mic_present); } else if (dock_present) { - snd_printdd("CXT5066: dock microphone detected\n"); + codec_dbg(codec, "CXT5066: dock microphone detected\n"); snd_hda_sequence_write(codec, dock_mic_present); } else { - snd_printdd("CXT5066: external microphone absent\n"); + codec_dbg(codec, "CXT5066: external microphone absent\n"); snd_hda_sequence_write(codec, ext_mic_absent); } } @@ -2229,7 +2087,7 @@ static void cxt5066_hp_automute(struct hda_codec *codec) spec->hp_present = portA ? HP_PRESENT_PORT_A : 0; spec->hp_present |= portD ? HP_PRESENT_PORT_D : 0; - snd_printdd("CXT5066: hp automute portA=%x portD=%x present=%d\n", + codec_dbg(codec, "CXT5066: hp automute portA=%x portD=%x present=%d\n", portA, portD, spec->hp_present); cxt5066_update_speaker(codec); } @@ -2252,26 +2110,9 @@ static void cxt5066_automic(struct hda_codec *codec) } /* unsolicited event for jack sensing */ -static void cxt5066_olpc_unsol_event(struct hda_codec *codec, unsigned int res) -{ - struct conexant_spec *spec = codec->spec; - snd_printdd("CXT5066: unsol event %x (%x)\n", res, res >> 26); - switch (res >> 26) { - case CONEXANT_HP_EVENT: - cxt5066_hp_automute(codec); - break; - case CONEXANT_MIC_EVENT: - /* ignore mic events in DC mode; we're always using the jack */ - if (!spec->dc_enable) - cxt5066_olpc_automic(codec); - break; - } -} - -/* unsolicited event for jack sensing */ static void cxt5066_unsol_event(struct hda_codec *codec, unsigned int res) { - snd_printdd("CXT5066: unsol event %x (%x)\n", res, res >> 26); + codec_dbg(codec, "CXT5066: unsol event %x (%x)\n", res, res >> 26); switch (res >> 26) { case CONEXANT_HP_EVENT: cxt5066_hp_automute(codec); @@ -2338,124 +2179,10 @@ static int cxt5066_mic_boost_mux_enum_put(struct snd_kcontrol *kcontrol, idx = imux->num_items - 1; spec->mic_boost = idx; - if (!spec->dc_enable) - cxt5066_set_mic_boost(codec); - return 1; -} - -static void cxt5066_enable_dc(struct hda_codec *codec) -{ - const struct hda_verb enable_dc_mode[] = { - /* disable gain */ - {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, - - /* switch to DC input */ - {0x17, AC_VERB_SET_CONNECT_SEL, 3}, - {} - }; - - /* configure as input source */ - snd_hda_sequence_write(codec, enable_dc_mode); - cxt5066_olpc_select_mic(codec); /* also sets configured bias */ -} - -static void cxt5066_disable_dc(struct hda_codec *codec) -{ - /* reconfigure input source */ cxt5066_set_mic_boost(codec); - /* automic also selects the right mic if we're recording */ - cxt5066_olpc_automic(codec); -} - -static int cxt5066_olpc_dc_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct hda_codec *codec = snd_kcontrol_chip(kcontrol); - struct conexant_spec *spec = codec->spec; - ucontrol->value.integer.value[0] = spec->dc_enable; - return 0; -} - -static int cxt5066_olpc_dc_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct hda_codec *codec = snd_kcontrol_chip(kcontrol); - struct conexant_spec *spec = codec->spec; - int dc_enable = !!ucontrol->value.integer.value[0]; - - if (dc_enable == spec->dc_enable) - return 0; - - spec->dc_enable = dc_enable; - if (dc_enable) - cxt5066_enable_dc(codec); - else - cxt5066_disable_dc(codec); - - return 1; -} - -static int cxt5066_olpc_dc_bias_enum_info(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo) -{ - return snd_hda_input_mux_info(&cxt5066_olpc_dc_bias, uinfo); -} - -static int cxt5066_olpc_dc_bias_enum_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct hda_codec *codec = snd_kcontrol_chip(kcontrol); - struct conexant_spec *spec = codec->spec; - ucontrol->value.enumerated.item[0] = spec->dc_input_bias; - return 0; -} - -static int cxt5066_olpc_dc_bias_enum_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct hda_codec *codec = snd_kcontrol_chip(kcontrol); - struct conexant_spec *spec = codec->spec; - const struct hda_input_mux *imux = &cxt5066_analog_mic_boost; - unsigned int idx; - - idx = ucontrol->value.enumerated.item[0]; - if (idx >= imux->num_items) - idx = imux->num_items - 1; - - spec->dc_input_bias = idx; - if (spec->dc_enable) - cxt5066_set_olpc_dc_bias(codec); return 1; } -static void cxt5066_olpc_capture_prepare(struct hda_codec *codec) -{ - struct conexant_spec *spec = codec->spec; - /* mark as recording and configure the microphone widget so that the - * recording LED comes on. */ - spec->recording = 1; - cxt5066_olpc_select_mic(codec); -} - -static void cxt5066_olpc_capture_cleanup(struct hda_codec *codec) -{ - struct conexant_spec *spec = codec->spec; - const struct hda_verb disable_mics[] = { - /* disable external mic, port B */ - {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, 0}, - - /* disble internal mic, port C */ - {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, 0}, - - /* disable DC capture, port F */ - {0x1e, AC_VERB_SET_PIN_WIDGET_CONTROL, 0}, - {}, - }; - - snd_hda_sequence_write(codec, disable_mics); - spec->recording = 0; -} - static void conexant_check_dig_outs(struct hda_codec *codec, const hda_nid_t *dig_pins, int num_pins) @@ -2506,43 +2233,6 @@ static const struct snd_kcontrol_new cxt5066_mixer_master[] = { {} }; -static const struct snd_kcontrol_new cxt5066_mixer_master_olpc[] = { - { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Master Playback Volume", - .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | - SNDRV_CTL_ELEM_ACCESS_TLV_READ | - SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK, - .subdevice = HDA_SUBDEV_AMP_FLAG, - .info = snd_hda_mixer_amp_volume_info, - .get = snd_hda_mixer_amp_volume_get, - .put = snd_hda_mixer_amp_volume_put, - .tlv = { .c = snd_hda_mixer_amp_tlv }, - /* offset by 28 volume steps to limit minimum gain to -46dB */ - .private_value = - HDA_COMPOSE_AMP_VAL_OFS(0x10, 3, 0, HDA_OUTPUT, 28), - }, - {} -}; - -static const struct snd_kcontrol_new cxt5066_mixer_olpc_dc[] = { - { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "DC Mode Enable Switch", - .info = snd_ctl_boolean_mono_info, - .get = cxt5066_olpc_dc_get, - .put = cxt5066_olpc_dc_put, - }, - { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "DC Input Bias Enum", - .info = cxt5066_olpc_dc_bias_enum_info, - .get = cxt5066_olpc_dc_bias_enum_get, - .put = cxt5066_olpc_dc_bias_enum_put, - }, - {} -}; - static const struct snd_kcontrol_new cxt5066_mixers[] = { { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, @@ -2633,67 +2323,6 @@ static const struct hda_verb cxt5066_init_verbs[] = { { } /* end */ }; -static const struct hda_verb cxt5066_init_verbs_olpc[] = { - /* Port A: headphones */ - {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, - {0x19, AC_VERB_SET_CONNECT_SEL, 0x00}, /* DAC1 */ - - /* Port B: external microphone */ - {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, 0}, - - /* Port C: internal microphone */ - {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, 0}, - - /* Port D: unused */ - {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0}, - - /* Port E: unused, but has primary EAPD */ - {0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0}, - {0x1d, AC_VERB_SET_EAPD_BTLENABLE, 0x2}, /* default on */ - - /* Port F: external DC input through microphone port */ - {0x1e, AC_VERB_SET_PIN_WIDGET_CONTROL, 0}, - - /* Port G: internal speakers */ - {0x1f, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, - {0x1f, AC_VERB_SET_CONNECT_SEL, 0x00}, /* DAC1 */ - - /* DAC1 */ - {0x10, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, - - /* DAC2: unused */ - {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, - - {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0) | 0x50}, - {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, - {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)}, - {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, - {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, - {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, - {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)}, - {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, - {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, - {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, - {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)}, - {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, - - /* Disable digital microphone port */ - {0x23, AC_VERB_SET_PIN_WIDGET_CONTROL, 0}, - - /* Audio input selectors */ - {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x3}, - {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE }, - - /* Disable SPDIF */ - {0x20, AC_VERB_SET_PIN_WIDGET_CONTROL, 0}, - {0x22, AC_VERB_SET_PIN_WIDGET_CONTROL, 0}, - - /* enable unsolicited events for Port A and B */ - {0x19, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | CONEXANT_HP_EVENT}, - {0x1a, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | CONEXANT_MIC_EVENT}, - { } /* end */ -}; - static const struct hda_verb cxt5066_init_verbs_vostro[] = { /* Port A: headphones */ {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, 0}, @@ -2879,7 +2508,7 @@ static const struct hda_verb cxt5066_init_verbs_hp_laptop[] = { /* initialize jack-sensing, too */ static int cxt5066_init(struct hda_codec *codec) { - snd_printdd("CXT5066: init\n"); + codec_dbg(codec, "CXT5066: init\n"); conexant_init(codec); if (codec->patch_ops.unsol_event) { cxt5066_hp_automute(codec); @@ -2889,25 +2518,9 @@ static int cxt5066_init(struct hda_codec *codec) return 0; } -static int cxt5066_olpc_init(struct hda_codec *codec) -{ - struct conexant_spec *spec = codec->spec; - snd_printdd("CXT5066: init\n"); - conexant_init(codec); - cxt5066_hp_automute(codec); - if (!spec->dc_enable) { - cxt5066_set_mic_boost(codec); - cxt5066_olpc_automic(codec); - } else { - cxt5066_enable_dc(codec); - } - return 0; -} - enum { CXT5066_LAPTOP, /* Laptops w/ EAPD support */ CXT5066_DELL_LAPTOP, /* Dell Laptop */ - CXT5066_OLPC_XO_1_5, /* OLPC XO 1.5 */ CXT5066_DELL_VOSTRO, /* Dell Vostro 1015i */ CXT5066_IDEAPAD, /* Lenovo IdeaPad U150 */ CXT5066_THINKPAD, /* Lenovo ThinkPad T410s, others? */ @@ -2920,7 +2533,6 @@ enum { static const char * const cxt5066_models[CXT5066_MODELS] = { [CXT5066_LAPTOP] = "laptop", [CXT5066_DELL_LAPTOP] = "dell-laptop", - [CXT5066_OLPC_XO_1_5] = "olpc-xo-1_5", [CXT5066_DELL_VOSTRO] = "dell-vostro", [CXT5066_IDEAPAD] = "ideapad", [CXT5066_THINKPAD] = "thinkpad", @@ -2941,10 +2553,8 @@ static const struct snd_pci_quirk cxt5066_cfg_tbl[] = { SND_PCI_QUIRK(0x1043, 0x1643, "Asus K52JU", CXT5066_ASUS), SND_PCI_QUIRK(0x1043, 0x1993, "Asus U50F", CXT5066_ASUS), SND_PCI_QUIRK(0x1179, 0xff1e, "Toshiba Satellite C650D", CXT5066_IDEAPAD), - SND_PCI_QUIRK(0x1179, 0xff50, "Toshiba Satellite P500-PSPGSC-01800T", CXT5066_OLPC_XO_1_5), SND_PCI_QUIRK(0x14f1, 0x0101, "Conexant Reference board", CXT5066_LAPTOP), - SND_PCI_QUIRK(0x152d, 0x0833, "OLPC XO-1.5", CXT5066_OLPC_XO_1_5), SND_PCI_QUIRK(0x17aa, 0x20f2, "Lenovo T400s", CXT5066_THINKPAD), SND_PCI_QUIRK(0x17aa, 0x21c5, "Thinkpad Edge 13", CXT5066_THINKPAD), SND_PCI_QUIRK(0x17aa, 0x21c6, "Thinkpad Edge 13", CXT5066_ASUS), @@ -3030,32 +2640,11 @@ static int patch_cxt5066(struct hda_codec *codec) spec->mic_boost = 3; /* default 30dB gain */ break; - case CXT5066_OLPC_XO_1_5: - codec->patch_ops.init = cxt5066_olpc_init; - codec->patch_ops.unsol_event = cxt5066_olpc_unsol_event; - spec->init_verbs[0] = cxt5066_init_verbs_olpc; - spec->mixers[spec->num_mixers++] = cxt5066_mixer_master_olpc; - spec->mixers[spec->num_mixers++] = cxt5066_mixer_olpc_dc; - spec->mixers[spec->num_mixers++] = cxt5066_mixers; - spec->port_d_mode = 0; - spec->mic_boost = 3; /* default 30dB gain */ - - /* no S/PDIF out */ - spec->multiout.dig_out_nid = 0; - - /* input source automatically selected */ - spec->input_mux = NULL; - - /* our capture hooks which allow us to turn on the microphone LED - * at the right time */ - spec->capture_prepare = cxt5066_olpc_capture_prepare; - spec->capture_cleanup = cxt5066_olpc_capture_cleanup; - break; case CXT5066_DELL_VOSTRO: codec->patch_ops.init = cxt5066_init; codec->patch_ops.unsol_event = cxt5066_unsol_event; spec->init_verbs[0] = cxt5066_init_verbs_vostro; - spec->mixers[spec->num_mixers++] = cxt5066_mixer_master_olpc; + spec->mixers[spec->num_mixers++] = cxt5066_mixer_master; spec->mixers[spec->num_mixers++] = cxt5066_mixers; spec->mixers[spec->num_mixers++] = cxt5066_vostro_mixers; spec->port_d_mode = 0; @@ -3207,11 +2796,7 @@ static int cx_auto_init(struct hda_codec *codec) return 0; } -static void cx_auto_free(struct hda_codec *codec) -{ - snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_FREE); - snd_hda_gen_free(codec); -} +#define cx_auto_free snd_hda_gen_free static const struct hda_codec_ops cx_auto_patch_ops = { .build_controls = cx_auto_build_controls, @@ -3238,6 +2823,11 @@ enum { CXT_FIXUP_HEADPHONE_MIC, CXT_FIXUP_GPIO1, CXT_FIXUP_THINKPAD_ACPI, + CXT_FIXUP_OLPC_XO, + CXT_FIXUP_CAP_MIX_AMP, + CXT_FIXUP_TOSHIBA_P105, + CXT_FIXUP_HP_530, + CXT_FIXUP_CAP_MIX_AMP_5047, }; /* for hda_fixup_thinkpad_acpi() */ @@ -3316,6 +2906,288 @@ static void cxt_fixup_headphone_mic(struct hda_codec *codec, } } +/* OPLC XO 1.5 fixup */ + +/* OLPC XO-1.5 supports DC input mode (e.g. for use with analog sensors) + * through the microphone jack. + * When the user enables this through a mixer switch, both internal and + * external microphones are disabled. Gain is fixed at 0dB. In this mode, + * we also allow the bias to be configured through a separate mixer + * control. */ + +#define update_mic_pin(codec, nid, val) \ + snd_hda_codec_update_cache(codec, nid, 0, \ + AC_VERB_SET_PIN_WIDGET_CONTROL, val) + +static const struct hda_input_mux olpc_xo_dc_bias = { + .num_items = 3, + .items = { + { "Off", PIN_IN }, + { "50%", PIN_VREF50 }, + { "80%", PIN_VREF80 }, + }, +}; + +static void olpc_xo_update_mic_boost(struct hda_codec *codec) +{ + struct conexant_spec *spec = codec->spec; + int ch, val; + + for (ch = 0; ch < 2; ch++) { + val = AC_AMP_SET_OUTPUT | + (ch ? AC_AMP_SET_RIGHT : AC_AMP_SET_LEFT); + if (!spec->dc_enable) + val |= snd_hda_codec_amp_read(codec, 0x17, ch, HDA_OUTPUT, 0); + snd_hda_codec_write(codec, 0x17, 0, + AC_VERB_SET_AMP_GAIN_MUTE, val); + } +} + +static void olpc_xo_update_mic_pins(struct hda_codec *codec) +{ + struct conexant_spec *spec = codec->spec; + int cur_input, val; + struct nid_path *path; + + cur_input = spec->gen.input_paths[0][spec->gen.cur_mux[0]]; + + /* Set up mic pins for port-B, C and F dynamically as the recording + * LED is turned on/off by these pin controls + */ + if (!spec->dc_enable) { + /* disable DC bias path and pin for port F */ + update_mic_pin(codec, 0x1e, 0); + snd_hda_activate_path(codec, spec->dc_mode_path, false, false); + + /* update port B (ext mic) and C (int mic) */ + /* OLPC defers mic widget control until when capture is + * started because the microphone LED comes on as soon as + * these settings are put in place. if we did this before + * recording, it would give the false indication that + * recording is happening when it is not. + */ + update_mic_pin(codec, 0x1a, spec->recording ? + snd_hda_codec_get_pin_target(codec, 0x1a) : 0); + update_mic_pin(codec, 0x1b, spec->recording ? + snd_hda_codec_get_pin_target(codec, 0x1b) : 0); + /* enable normal mic path */ + path = snd_hda_get_path_from_idx(codec, cur_input); + if (path) + snd_hda_activate_path(codec, path, true, false); + } else { + /* disable normal mic path */ + path = snd_hda_get_path_from_idx(codec, cur_input); + if (path) + snd_hda_activate_path(codec, path, false, false); + + /* Even though port F is the DC input, the bias is controlled + * on port B. We also leave that port as an active input (but + * unselected) in DC mode just in case that is necessary to + * make the bias setting take effect. + */ + if (spec->recording) + val = olpc_xo_dc_bias.items[spec->dc_input_bias].index; + else + val = 0; + update_mic_pin(codec, 0x1a, val); + update_mic_pin(codec, 0x1b, 0); + /* enable DC bias path and pin */ + update_mic_pin(codec, 0x1e, spec->recording ? PIN_IN : 0); + snd_hda_activate_path(codec, spec->dc_mode_path, true, false); + } +} + +/* mic_autoswitch hook */ +static void olpc_xo_automic(struct hda_codec *codec, struct hda_jack_tbl *jack) +{ + struct conexant_spec *spec = codec->spec; + int saved_cached_write = codec->cached_write; + + codec->cached_write = 1; + /* in DC mode, we don't handle automic */ + if (!spec->dc_enable) + snd_hda_gen_mic_autoswitch(codec, jack); + olpc_xo_update_mic_pins(codec); + snd_hda_codec_flush_cache(codec); + codec->cached_write = saved_cached_write; + if (spec->dc_enable) + olpc_xo_update_mic_boost(codec); +} + +/* pcm_capture hook */ +static void olpc_xo_capture_hook(struct hda_pcm_stream *hinfo, + struct hda_codec *codec, + struct snd_pcm_substream *substream, + int action) +{ + struct conexant_spec *spec = codec->spec; + + /* toggle spec->recording flag and update mic pins accordingly + * for turning on/off LED + */ + switch (action) { + case HDA_GEN_PCM_ACT_PREPARE: + spec->recording = 1; + olpc_xo_update_mic_pins(codec); + break; + case HDA_GEN_PCM_ACT_CLEANUP: + spec->recording = 0; + olpc_xo_update_mic_pins(codec); + break; + } +} + +static int olpc_xo_dc_mode_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct hda_codec *codec = snd_kcontrol_chip(kcontrol); + struct conexant_spec *spec = codec->spec; + ucontrol->value.integer.value[0] = spec->dc_enable; + return 0; +} + +static int olpc_xo_dc_mode_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct hda_codec *codec = snd_kcontrol_chip(kcontrol); + struct conexant_spec *spec = codec->spec; + int dc_enable = !!ucontrol->value.integer.value[0]; + + if (dc_enable == spec->dc_enable) + return 0; + + spec->dc_enable = dc_enable; + olpc_xo_update_mic_pins(codec); + olpc_xo_update_mic_boost(codec); + return 1; +} + +static int olpc_xo_dc_bias_enum_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct hda_codec *codec = snd_kcontrol_chip(kcontrol); + struct conexant_spec *spec = codec->spec; + ucontrol->value.enumerated.item[0] = spec->dc_input_bias; + return 0; +} + +static int olpc_xo_dc_bias_enum_info(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_info *uinfo) +{ + return snd_hda_input_mux_info(&olpc_xo_dc_bias, uinfo); +} + +static int olpc_xo_dc_bias_enum_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct hda_codec *codec = snd_kcontrol_chip(kcontrol); + struct conexant_spec *spec = codec->spec; + const struct hda_input_mux *imux = &olpc_xo_dc_bias; + unsigned int idx; + + idx = ucontrol->value.enumerated.item[0]; + if (idx >= imux->num_items) + idx = imux->num_items - 1; + if (spec->dc_input_bias == idx) + return 0; + + spec->dc_input_bias = idx; + if (spec->dc_enable) + olpc_xo_update_mic_pins(codec); + return 1; +} + +static const struct snd_kcontrol_new olpc_xo_mixers[] = { + { + .iface = SNDRV_CTL_ELEM_IFACE_MIXER, + .name = "DC Mode Enable Switch", + .info = snd_ctl_boolean_mono_info, + .get = olpc_xo_dc_mode_get, + .put = olpc_xo_dc_mode_put, + }, + { + .iface = SNDRV_CTL_ELEM_IFACE_MIXER, + .name = "DC Input Bias Enum", + .info = olpc_xo_dc_bias_enum_info, + .get = olpc_xo_dc_bias_enum_get, + .put = olpc_xo_dc_bias_enum_put, + }, + {} +}; + +/* overriding mic boost put callback; update mic boost volume only when + * DC mode is disabled + */ +static int olpc_xo_mic_boost_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct hda_codec *codec = snd_kcontrol_chip(kcontrol); + struct conexant_spec *spec = codec->spec; + int ret = snd_hda_mixer_amp_volume_put(kcontrol, ucontrol); + if (ret > 0 && spec->dc_enable) + olpc_xo_update_mic_boost(codec); + return ret; +} + +static void cxt_fixup_olpc_xo(struct hda_codec *codec, + const struct hda_fixup *fix, int action) +{ + struct conexant_spec *spec = codec->spec; + int i; + + if (action != HDA_FIXUP_ACT_PROBE) + return; + + spec->gen.mic_autoswitch_hook = olpc_xo_automic; + spec->gen.pcm_capture_hook = olpc_xo_capture_hook; + spec->dc_mode_path = snd_hda_add_new_path(codec, 0x1e, 0x14, 0); + + snd_hda_add_new_ctls(codec, olpc_xo_mixers); + + /* OLPC's microphone port is DC coupled for use with external sensors, + * therefore we use a 50% mic bias in order to center the input signal + * with the DC input range of the codec. + */ + snd_hda_codec_set_pin_target(codec, 0x1a, PIN_VREF50); + + /* override mic boost control */ + for (i = 0; i < spec->gen.kctls.used; i++) { + struct snd_kcontrol_new *kctl = + snd_array_elem(&spec->gen.kctls, i); + if (!strcmp(kctl->name, "Mic Boost Volume")) { + kctl->put = olpc_xo_mic_boost_put; + break; + } + } +} + +/* + * Fix max input level on mixer widget to 0dB + * (originally it has 0x2b steps with 0dB offset 0x14) + */ +static void cxt_fixup_cap_mix_amp(struct hda_codec *codec, + const struct hda_fixup *fix, int action) +{ + snd_hda_override_amp_caps(codec, 0x17, HDA_INPUT, + (0x14 << AC_AMPCAP_OFFSET_SHIFT) | + (0x14 << AC_AMPCAP_NUM_STEPS_SHIFT) | + (0x05 << AC_AMPCAP_STEP_SIZE_SHIFT) | + (1 << AC_AMPCAP_MUTE_SHIFT)); +} + +/* + * Fix max input level on mixer widget to 0dB + * (originally it has 0x1e steps with 0 dB offset 0x17) + */ +static void cxt_fixup_cap_mix_amp_5047(struct hda_codec *codec, + const struct hda_fixup *fix, int action) +{ + snd_hda_override_amp_caps(codec, 0x10, HDA_INPUT, + (0x17 << AC_AMPCAP_OFFSET_SHIFT) | + (0x17 << AC_AMPCAP_NUM_STEPS_SHIFT) | + (0x05 << AC_AMPCAP_STEP_SIZE_SHIFT) | + (1 << AC_AMPCAP_MUTE_SHIFT)); +} /* ThinkPad X200 & co with cxt5051 */ static const struct hda_pintbl cxt_pincfg_lenovo_x200[] = { @@ -3401,6 +3273,68 @@ static const struct hda_fixup cxt_fixups[] = { .type = HDA_FIXUP_FUNC, .v.func = hda_fixup_thinkpad_acpi, }, + [CXT_FIXUP_OLPC_XO] = { + .type = HDA_FIXUP_FUNC, + .v.func = cxt_fixup_olpc_xo, + }, + [CXT_FIXUP_CAP_MIX_AMP] = { + .type = HDA_FIXUP_FUNC, + .v.func = cxt_fixup_cap_mix_amp, + }, + [CXT_FIXUP_TOSHIBA_P105] = { + .type = HDA_FIXUP_PINS, + .v.pins = (const struct hda_pintbl[]) { + { 0x10, 0x961701f0 }, /* speaker/hp */ + { 0x12, 0x02a1901e }, /* ext mic */ + { 0x14, 0x95a70110 }, /* int mic */ + {} + }, + }, + [CXT_FIXUP_HP_530] = { + .type = HDA_FIXUP_PINS, + .v.pins = (const struct hda_pintbl[]) { + { 0x12, 0x90a60160 }, /* int mic */ + {} + }, + .chained = true, + .chain_id = CXT_FIXUP_CAP_MIX_AMP, + }, + [CXT_FIXUP_CAP_MIX_AMP_5047] = { + .type = HDA_FIXUP_FUNC, + .v.func = cxt_fixup_cap_mix_amp_5047, + }, +}; + +static const struct snd_pci_quirk cxt5045_fixups[] = { + SND_PCI_QUIRK(0x103c, 0x30d5, "HP 530", CXT_FIXUP_HP_530), + SND_PCI_QUIRK(0x1179, 0xff31, "Toshiba P105", CXT_FIXUP_TOSHIBA_P105), + /* HP, Packard Bell, Fujitsu-Siemens & Lenovo laptops have + * really bad sound over 0dB on NID 0x17. + */ + SND_PCI_QUIRK_VENDOR(0x103c, "HP", CXT_FIXUP_CAP_MIX_AMP), + SND_PCI_QUIRK_VENDOR(0x1631, "Packard Bell", CXT_FIXUP_CAP_MIX_AMP), + SND_PCI_QUIRK_VENDOR(0x1734, "Fujitsu", CXT_FIXUP_CAP_MIX_AMP), + SND_PCI_QUIRK_VENDOR(0x17aa, "Lenovo", CXT_FIXUP_CAP_MIX_AMP), + {} +}; + +static const struct hda_model_fixup cxt5045_fixup_models[] = { + { .id = CXT_FIXUP_CAP_MIX_AMP, .name = "cap-mix-amp" }, + { .id = CXT_FIXUP_TOSHIBA_P105, .name = "toshiba-p105" }, + { .id = CXT_FIXUP_HP_530, .name = "hp-530" }, + {} +}; + +static const struct snd_pci_quirk cxt5047_fixups[] = { + /* HP laptops have really bad sound over 0 dB on NID 0x10. + */ + SND_PCI_QUIRK_VENDOR(0x103c, "HP", CXT_FIXUP_CAP_MIX_AMP_5047), + {} +}; + +static const struct hda_model_fixup cxt5047_fixup_models[] = { + { .id = CXT_FIXUP_CAP_MIX_AMP_5047, .name = "cap-mix-amp" }, + {} }; static const struct snd_pci_quirk cxt5051_fixups[] = { @@ -3408,10 +3342,16 @@ static const struct snd_pci_quirk cxt5051_fixups[] = { {} }; +static const struct hda_model_fixup cxt5051_fixup_models[] = { + { .id = CXT_PINCFG_LENOVO_X200, .name = "lenovo-x200" }, + {} +}; + 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_GPIO1), 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), SND_PCI_QUIRK(0x17aa, 0x215e, "Lenovo T410", CXT_PINCFG_LENOVO_TP410), SND_PCI_QUIRK(0x17aa, 0x215f, "Lenovo T510", CXT_PINCFG_LENOVO_TP410), @@ -3428,6 +3368,17 @@ static const struct snd_pci_quirk cxt5066_fixups[] = { {} }; +static const struct hda_model_fixup cxt5066_fixup_models[] = { + { .id = CXT_FIXUP_STEREO_DMIC, .name = "stereo-dmic" }, + { .id = CXT_FIXUP_GPIO1, .name = "gpio1" }, + { .id = CXT_FIXUP_HEADPHONE_MIC_PIN, .name = "headphone-mic-pin" }, + { .id = CXT_PINCFG_LENOVO_TP410, .name = "tp410" }, + { .id = CXT_FIXUP_THINKPAD_ACPI, .name = "thinkpad" }, + { .id = CXT_PINCFG_LEMOTE_A1004, .name = "lemote-a1004" }, + { .id = CXT_FIXUP_OLPC_XO, .name = "olpc-xo" }, + {} +}; + /* add "fake" mute amp-caps to DACs on cx5051 so that mixer mute switches * can be created (bko#42825) */ @@ -3449,8 +3400,7 @@ static int patch_conexant_auto(struct hda_codec *codec) struct conexant_spec *spec; int err; - printk(KERN_INFO "hda_codec: %s: BIOS auto-probing.\n", - codec->chip_name); + codec_info(codec, "%s: BIOS auto-probing.\n", codec->chip_name); spec = kzalloc(sizeof(*spec), GFP_KERNEL); if (!spec) @@ -3467,19 +3417,28 @@ static int patch_conexant_auto(struct hda_codec *codec) switch (codec->vendor_id) { case 0x14f15045: codec->single_adc_amp = 1; + spec->gen.mixer_nid = 0x17; + spec->gen.add_stereo_mix_input = 1; + snd_hda_pick_fixup(codec, cxt5045_fixup_models, + cxt5045_fixups, cxt_fixups); break; case 0x14f15047: codec->pin_amp_workaround = 1; spec->gen.mixer_nid = 0x19; + spec->gen.add_stereo_mix_input = 1; + snd_hda_pick_fixup(codec, cxt5047_fixup_models, + cxt5047_fixups, cxt_fixups); break; case 0x14f15051: add_cx5051_fake_mutes(codec); codec->pin_amp_workaround = 1; - snd_hda_pick_fixup(codec, NULL, cxt5051_fixups, cxt_fixups); + snd_hda_pick_fixup(codec, cxt5051_fixup_models, + cxt5051_fixups, cxt_fixups); break; default: codec->pin_amp_workaround = 1; - snd_hda_pick_fixup(codec, NULL, cxt5066_fixups, cxt_fixups); + snd_hda_pick_fixup(codec, cxt5066_fixup_models, + cxt5066_fixups, cxt_fixups); break; } @@ -3513,7 +3472,7 @@ static int patch_conexant_auto(struct hda_codec *codec) * Better to make reset, then. */ if (!codec->bus->sync_write) { - snd_printd("hda_codec: " + codec_info(codec, "Enable sync_write for stable communication\n"); codec->bus->sync_write = 1; codec->bus->allow_bus_reset = 1; diff --git a/sound/pci/hda/patch_hdmi.c b/sound/pci/hda/patch_hdmi.c index 5ef95034d04..0cb5b89cd0c 100644 --- a/sound/pci/hda/patch_hdmi.c +++ b/sound/pci/hda/patch_hdmi.c @@ -68,6 +68,7 @@ struct hdmi_spec_per_pin { hda_nid_t pin_nid; int num_mux_nids; hda_nid_t mux_nids[HDA_MAX_CONNECTIONS]; + int mux_idx; hda_nid_t cvt_nid; struct hda_codec *codec; @@ -353,40 +354,43 @@ static struct cea_channel_speaker_allocation channel_allocations[] = { #define get_pcm_rec(spec, idx) \ ((struct hda_pcm *)snd_array_elem(&spec->pcm_rec, idx)) -static int pin_nid_to_pin_index(struct hdmi_spec *spec, hda_nid_t pin_nid) +static int pin_nid_to_pin_index(struct hda_codec *codec, hda_nid_t pin_nid) { + struct hdmi_spec *spec = codec->spec; int pin_idx; for (pin_idx = 0; pin_idx < spec->num_pins; pin_idx++) if (get_pin(spec, pin_idx)->pin_nid == pin_nid) return pin_idx; - snd_printk(KERN_WARNING "HDMI: pin nid %d not registered\n", pin_nid); + codec_warn(codec, "HDMI: pin nid %d not registered\n", pin_nid); return -EINVAL; } -static int hinfo_to_pin_index(struct hdmi_spec *spec, +static int hinfo_to_pin_index(struct hda_codec *codec, struct hda_pcm_stream *hinfo) { + struct hdmi_spec *spec = codec->spec; int pin_idx; for (pin_idx = 0; pin_idx < spec->num_pins; pin_idx++) if (get_pcm_rec(spec, pin_idx)->stream == hinfo) return pin_idx; - snd_printk(KERN_WARNING "HDMI: hinfo %p not registered\n", hinfo); + codec_warn(codec, "HDMI: hinfo %p not registered\n", hinfo); return -EINVAL; } -static int cvt_nid_to_cvt_index(struct hdmi_spec *spec, hda_nid_t cvt_nid) +static int cvt_nid_to_cvt_index(struct hda_codec *codec, hda_nid_t cvt_nid) { + struct hdmi_spec *spec = codec->spec; int cvt_idx; for (cvt_idx = 0; cvt_idx < spec->num_cvts; cvt_idx++) if (get_cvt(spec, cvt_idx)->cvt_nid == cvt_nid) return cvt_idx; - snd_printk(KERN_WARNING "HDMI: cvt nid %d not registered\n", cvt_nid); + codec_warn(codec, "HDMI: cvt nid %d not registered\n", cvt_nid); return -EINVAL; } @@ -706,7 +710,7 @@ static void hdmi_debug_channel_mapping(struct hda_codec *codec, for (i = 0; i < 8; i++) { channel = spec->ops.pin_get_slot_channel(codec, pin_nid, i); - printk(KERN_DEBUG "HDMI: ASP channel %d => slot %d\n", + codec_dbg(codec, "HDMI: ASP channel %d => slot %d\n", channel, i); } #endif @@ -755,8 +759,7 @@ static void hdmi_std_setup_channel_mapping(struct hda_codec *codec, int channel = (slotsetup & 0xf0) >> 4; err = spec->ops.pin_set_slot_channel(codec, pin_nid, hdmi_slot, channel); if (err) { - snd_printdd(KERN_NOTICE - "HDMI: channel mapping failed\n"); + codec_dbg(codec, "HDMI: channel mapping failed\n"); break; } } @@ -967,12 +970,12 @@ static void hdmi_debug_dip_size(struct hda_codec *codec, hda_nid_t pin_nid) int size; size = snd_hdmi_get_eld_size(codec, pin_nid); - printk(KERN_DEBUG "HDMI: ELD buf size is %d\n", size); + codec_dbg(codec, "HDMI: ELD buf size is %d\n", size); for (i = 0; i < 8; i++) { size = snd_hda_codec_read(codec, pin_nid, 0, AC_VERB_GET_HDMI_DIP_SIZE, i); - printk(KERN_DEBUG "HDMI: DIP GP[%d] buf size is %d\n", i, size); + codec_dbg(codec, "HDMI: DIP GP[%d] buf size is %d\n", i, size); } #endif } @@ -994,12 +997,12 @@ static void hdmi_clear_dip_buffers(struct hda_codec *codec, hda_nid_t pin_nid) hdmi_write_dip_byte(codec, pin_nid, 0x0); hdmi_get_dip_index(codec, pin_nid, &pi, &bi); if (pi != i) - snd_printd(KERN_INFO "dip index %d: %d != %d\n", + codec_dbg(codec, "dip index %d: %d != %d\n", bi, pi, i); if (bi == 0) /* byte index wrapped around */ break; } - snd_printd(KERN_INFO + codec_dbg(codec, "HDMI: DIP GP[%d] buf reported size=%d, written=%d\n", i, size, j); } @@ -1062,6 +1065,7 @@ static void hdmi_pin_setup_infoframe(struct hda_codec *codec, { union audio_infoframe ai; + memset(&ai, 0, sizeof(ai)); if (conn_type == 0) { /* HDMI */ struct hdmi_audio_infoframe *hdmi_ai = &ai.hdmi; @@ -1080,7 +1084,7 @@ static void hdmi_pin_setup_infoframe(struct hda_codec *codec, dp_ai->CC02_CT47 = active_channels - 1; dp_ai->CA = ca; } else { - snd_printd("HDMI: unknown connection type at pin %d\n", + codec_dbg(codec, "HDMI: unknown connection type at pin %d\n", pin_nid); return; } @@ -1092,8 +1096,8 @@ static void hdmi_pin_setup_infoframe(struct hda_codec *codec, */ if (!hdmi_infoframe_uptodate(codec, pin_nid, ai.bytes, sizeof(ai))) { - snd_printdd("hdmi_pin_setup_infoframe: " - "pin=%d channels=%d ca=0x%02x\n", + codec_dbg(codec, + "hdmi_pin_setup_infoframe: pin=%d channels=%d ca=0x%02x\n", pin_nid, active_channels, ca); hdmi_stop_infoframe_trans(codec, pin_nid); @@ -1161,7 +1165,7 @@ 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) { struct hdmi_spec *spec = codec->spec; - int pin_idx = pin_nid_to_pin_index(spec, jack->nid); + int pin_idx = pin_nid_to_pin_index(codec, jack->nid); if (pin_idx < 0) return; @@ -1180,7 +1184,7 @@ static void hdmi_intrinsic_event(struct hda_codec *codec, unsigned int res) return; jack->jack_dirty = 1; - _snd_printd(SND_PR_VERBOSE, + codec_dbg(codec, "HDMI hot plug event: Codec=%d Pin=%d Device=%d Inactive=%d Presence_Detect=%d ELD_Valid=%d\n", codec->addr, jack->nid, dev_entry, !!(res & AC_UNSOL_RES_IA), !!(res & AC_UNSOL_RES_PD), !!(res & AC_UNSOL_RES_ELDV)); @@ -1195,7 +1199,7 @@ static void hdmi_non_intrinsic_event(struct hda_codec *codec, unsigned int res) int cp_state = !!(res & AC_UNSOL_RES_CP_STATE); int cp_ready = !!(res & AC_UNSOL_RES_CP_READY); - printk(KERN_INFO + codec_info(codec, "HDMI CP event: CODEC=%d TAG=%d SUBTAG=0x%x CP_STATE=%d CP_READY=%d\n", codec->addr, tag, @@ -1217,7 +1221,7 @@ static void hdmi_unsol_event(struct hda_codec *codec, unsigned int res) int subtag = (res & AC_UNSOL_RES_SUBTAG) >> AC_UNSOL_RES_SUBTAG_SHIFT; if (!snd_hda_jack_tbl_get_from_tag(codec, tag)) { - snd_printd(KERN_INFO "Unexpected HDMI event tag 0x%x\n", tag); + codec_dbg(codec, "Unexpected HDMI event tag 0x%x\n", tag); return; } @@ -1244,7 +1248,7 @@ static void haswell_verify_D0(struct hda_codec *codec, msleep(40); pwr = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_POWER_STATE, 0); pwr = (pwr & AC_PWRST_ACTUAL) >> AC_PWRST_ACTUAL_SHIFT; - snd_printd("Haswell HDMI audio: Power for pin 0x%x is now D%d\n", nid, pwr); + codec_dbg(codec, "Haswell HDMI audio: Power for pin 0x%x is now D%d\n", nid, pwr); } } @@ -1274,8 +1278,8 @@ static int hdmi_pin_hbr_setup(struct hda_codec *codec, hda_nid_t pin_nid, else new_pinctl |= AC_PINCTL_EPT_NATIVE; - snd_printdd("hdmi_pin_hbr_setup: " - "NID=0x%x, %spinctl=0x%x\n", + codec_dbg(codec, + "hdmi_pin_hbr_setup: NID=0x%x, %spinctl=0x%x\n", pin_nid, pinctl == new_pinctl ? "" : "new-", new_pinctl); @@ -1302,7 +1306,7 @@ static int hdmi_setup_stream(struct hda_codec *codec, hda_nid_t cvt_nid, err = spec->ops.pin_hbr_setup(codec, pin_nid, is_hbr_format(format)); if (err) { - snd_printdd("hdmi_setup_stream: HBR is not supported\n"); + codec_dbg(codec, "hdmi_setup_stream: HBR is not supported\n"); return err; } @@ -1341,6 +1345,8 @@ static int hdmi_choose_cvt(struct hda_codec *codec, if (cvt_idx == spec->num_cvts) return -ENODEV; + per_pin->mux_idx = mux_idx; + if (cvt_id) *cvt_id = cvt_idx; if (mux_id) @@ -1349,6 +1355,22 @@ static int hdmi_choose_cvt(struct hda_codec *codec, return 0; } +/* Assure the pin select the right convetor */ +static void intel_verify_pin_cvt_connect(struct hda_codec *codec, + struct hdmi_spec_per_pin *per_pin) +{ + hda_nid_t pin_nid = per_pin->pin_nid; + int mux_idx, curr; + + mux_idx = per_pin->mux_idx; + curr = snd_hda_codec_read(codec, pin_nid, 0, + AC_VERB_GET_CONNECT_SEL, 0); + if (curr != mux_idx) + snd_hda_codec_write_cache(codec, pin_nid, 0, + AC_VERB_SET_CONNECT_SEL, + mux_idx); +} + /* Intel HDMI workaround to fix audio routing issue: * For some Intel display codecs, pins share the same connection list. * So a conveter can be selected by multiple pins and playback on any of these @@ -1389,7 +1411,8 @@ static void intel_not_share_assigned_cvt(struct hda_codec *codec, for (cvt_idx = 0; cvt_idx < spec->num_cvts; cvt_idx++) { per_cvt = get_cvt(spec, cvt_idx); if (!per_cvt->assigned) { - snd_printdd("choose cvt %d for pin nid %d\n", + codec_dbg(codec, + "choose cvt %d for pin nid %d\n", cvt_idx, nid); snd_hda_codec_write_cache(codec, nid, 0, AC_VERB_SET_CONNECT_SEL, @@ -1416,7 +1439,7 @@ static int hdmi_pcm_open(struct hda_pcm_stream *hinfo, int err; /* Validate hinfo */ - pin_idx = hinfo_to_pin_index(spec, hinfo); + pin_idx = hinfo_to_pin_index(codec, hinfo); if (snd_BUG_ON(pin_idx < 0)) return -EINVAL; per_pin = get_pin(spec, pin_idx); @@ -1482,9 +1505,8 @@ static int hdmi_read_pin_conn(struct hda_codec *codec, int pin_idx) hda_nid_t pin_nid = per_pin->pin_nid; if (!(get_wcaps(codec, pin_nid) & AC_WCAP_CONN_LIST)) { - snd_printk(KERN_WARNING - "HDMI: pin %d wcaps %#x " - "does not support connection list\n", + codec_warn(codec, + "HDMI: pin %d wcaps %#x does not support connection list\n", pin_nid, get_wcaps(codec, pin_nid)); return -EINVAL; } @@ -1527,7 +1549,7 @@ static bool hdmi_present_sense(struct hdmi_spec_per_pin *per_pin, int repoll) else eld->eld_valid = false; - _snd_printd(SND_PR_VERBOSE, + codec_dbg(codec, "HDMI status: Codec=%d Pin=%d Presence_Detect=%d ELD_Valid=%d\n", codec->addr, pin_nid, pin_eld->monitor_present, eld->eld_valid); @@ -1690,7 +1712,7 @@ static int hdmi_parse_codec(struct hda_codec *codec) nodes = snd_hda_get_sub_nodes(codec, codec->afg, &nid); if (!nid || nodes < 0) { - snd_printk(KERN_WARNING "HDMI: failed to get afg sub nodes\n"); + codec_warn(codec, "HDMI: failed to get afg sub nodes\n"); return -EINVAL; } @@ -1744,12 +1766,25 @@ static int generic_hdmi_playback_pcm_prepare(struct hda_pcm_stream *hinfo, { hda_nid_t cvt_nid = hinfo->nid; struct hdmi_spec *spec = codec->spec; - int pin_idx = hinfo_to_pin_index(spec, hinfo); + int pin_idx = hinfo_to_pin_index(codec, hinfo); struct hdmi_spec_per_pin *per_pin = get_pin(spec, pin_idx); hda_nid_t pin_nid = per_pin->pin_nid; bool non_pcm; int pinctl; + if (is_haswell_plus(codec) || is_valleyview(codec)) { + /* Verify pin:cvt selections to avoid silent audio after S3. + * After S3, the audio driver restores pin:cvt selections + * but this can happen before gfx is ready and such selection + * is overlooked by HW. Thus multiple pins can share a same + * default convertor and mute control will affect each other, + * which can cause a resumed audio playback become silent + * after S3. + */ + intel_verify_pin_cvt_connect(codec, per_pin); + intel_not_share_assigned_cvt(codec, pin_nid, per_pin->mux_idx); + } + non_pcm = check_non_pcm_per_cvt(codec, cvt_nid); mutex_lock(&per_pin->lock); per_pin->channels = substream->runtime->channels; @@ -1788,7 +1823,7 @@ static int hdmi_pcm_close(struct hda_pcm_stream *hinfo, int pinctl; if (hinfo->nid) { - cvt_idx = cvt_nid_to_cvt_index(spec, hinfo->nid); + cvt_idx = cvt_nid_to_cvt_index(codec, hinfo->nid); if (snd_BUG_ON(cvt_idx < 0)) return -EINVAL; per_cvt = get_cvt(spec, cvt_idx); @@ -1797,7 +1832,7 @@ static int hdmi_pcm_close(struct hda_pcm_stream *hinfo, per_cvt->assigned = 0; hinfo->nid = 0; - pin_idx = hinfo_to_pin_index(spec, hinfo); + pin_idx = hinfo_to_pin_index(codec, hinfo); if (snd_BUG_ON(pin_idx < 0)) return -EINVAL; per_pin = get_pin(spec, pin_idx); @@ -2211,7 +2246,7 @@ static void intel_haswell_fixup_connect_list(struct hda_codec *codec, return; /* override pins connection list */ - snd_printdd("hdmi: haswell: override pin connection 0x%x\n", nid); + codec_dbg(codec, "hdmi: haswell: override pin connection 0x%x\n", nid); snd_hda_override_conn_list(codec, nid, spec->num_cvts, spec->cvt_nids); } @@ -3132,8 +3167,8 @@ static int atihdmi_pin_hbr_setup(struct hda_codec *codec, hda_nid_t pin_nid, else hbr_ctl_new = hbr_ctl & ~ATI_HBR_ENABLE; - snd_printdd("atihdmi_pin_hbr_setup: " - "NID=0x%x, %shbr-ctl=0x%x\n", + codec_dbg(codec, + "atihdmi_pin_hbr_setup: NID=0x%x, %shbr-ctl=0x%x\n", pin_nid, hbr_ctl == hbr_ctl_new ? "" : "new-", hbr_ctl_new); diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index 8d0a8443667..ea2351d119f 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -395,6 +395,8 @@ static int alc_auto_parse_customize_define(struct hda_codec *codec) goto do_sku; } + if (!codec->bus->pci) + return -1; ass = codec->subsystem_id & 0xffff; if (ass != codec->bus->pci->subsystem_device && (ass & 1)) goto do_sku; @@ -405,8 +407,8 @@ static int alc_auto_parse_customize_define(struct hda_codec *codec) ass = snd_hda_codec_get_pincfg(codec, nid); if (!(ass & 1)) { - printk(KERN_INFO "hda_codec: %s: SKU not ready 0x%08x\n", - codec->chip_name, ass); + codec_info(codec, "%s: SKU not ready 0x%08x\n", + codec->chip_name, ass); return -1; } @@ -430,17 +432,17 @@ do_sku: spec->cdefine.swap = (ass & 0x2) >> 1; spec->cdefine.override = ass & 0x1; - snd_printd("SKU: Nid=0x%x sku_cfg=0x%08x\n", + codec_dbg(codec, "SKU: Nid=0x%x sku_cfg=0x%08x\n", nid, spec->cdefine.sku_cfg); - snd_printd("SKU: port_connectivity=0x%x\n", + codec_dbg(codec, "SKU: port_connectivity=0x%x\n", spec->cdefine.port_connectivity); - snd_printd("SKU: enable_pcbeep=0x%x\n", spec->cdefine.enable_pcbeep); - snd_printd("SKU: check_sum=0x%08x\n", spec->cdefine.check_sum); - snd_printd("SKU: customization=0x%08x\n", spec->cdefine.customization); - snd_printd("SKU: external_amp=0x%x\n", spec->cdefine.external_amp); - snd_printd("SKU: platform_type=0x%x\n", spec->cdefine.platform_type); - snd_printd("SKU: swap=0x%x\n", spec->cdefine.swap); - snd_printd("SKU: override=0x%x\n", spec->cdefine.override); + codec_dbg(codec, "SKU: enable_pcbeep=0x%x\n", spec->cdefine.enable_pcbeep); + codec_dbg(codec, "SKU: check_sum=0x%08x\n", spec->cdefine.check_sum); + codec_dbg(codec, "SKU: customization=0x%08x\n", spec->cdefine.customization); + codec_dbg(codec, "SKU: external_amp=0x%x\n", spec->cdefine.external_amp); + codec_dbg(codec, "SKU: platform_type=0x%x\n", spec->cdefine.platform_type); + codec_dbg(codec, "SKU: swap=0x%x\n", spec->cdefine.swap); + codec_dbg(codec, "SKU: override=0x%x\n", spec->cdefine.override); return 0; } @@ -483,7 +485,8 @@ static int alc_subsystem_id(struct hda_codec *codec, const hda_nid_t *ports) } ass = codec->subsystem_id & 0xffff; - if ((ass != codec->bus->pci->subsystem_device) && (ass & 1)) + if (codec->bus->pci && + ass != codec->bus->pci->subsystem_device && (ass & 1)) goto do_sku; /* invalid SSID, check the special NID pin defcfg instead */ @@ -499,8 +502,8 @@ static int alc_subsystem_id(struct hda_codec *codec, const hda_nid_t *ports) if (codec->vendor_id == 0x10ec0260) nid = 0x17; ass = snd_hda_codec_get_pincfg(codec, nid); - snd_printd("realtek: No valid SSID, " - "checking pincfg 0x%08x for NID 0x%x\n", + codec_dbg(codec, + "realtek: No valid SSID, checking pincfg 0x%08x for NID 0x%x\n", ass, nid); if (!(ass & 1)) return 0; @@ -516,7 +519,7 @@ static int alc_subsystem_id(struct hda_codec *codec, const hda_nid_t *ports) if (((ass >> 16) & 0xf) != tmp) return 0; do_sku: - snd_printd("realtek: Enabling init ASM_ID=0x%04x CODEC_ID=%08x\n", + codec_dbg(codec, "realtek: Enabling init ASM_ID=0x%04x CODEC_ID=%08x\n", ass & 0xffff, codec->vendor_id); /* * 0 : override @@ -574,8 +577,8 @@ static void alc_ssid_check(struct hda_codec *codec, const hda_nid_t *ports) { if (!alc_subsystem_id(codec, ports)) { struct alc_spec *spec = codec->spec; - snd_printd("realtek: " - "Enable default setup for auto mode as fallback\n"); + codec_dbg(codec, + "realtek: Enable default setup for auto mode as fallback\n"); spec->init_amp = ALC_INIT_DEFAULT; } } @@ -845,11 +848,7 @@ static inline void alc_shutup(struct hda_codec *codec) snd_hda_shutup_pins(codec); } -static void alc_free(struct hda_codec *codec) -{ - snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_FREE); - snd_hda_gen_free(codec); -} +#define alc_free snd_hda_gen_free #ifdef CONFIG_PM static void alc_power_eapd(struct hda_codec *codec) @@ -970,6 +969,8 @@ static int alc_codec_rename_from_preset(struct hda_codec *codec) return alc_codec_rename(codec, p->name); } + if (!codec->bus->pci) + return 0; for (q = rename_pci_tbl; q->codec_vendor_id; q++) { if (q->codec_vendor_id != codec->vendor_id) continue; @@ -993,6 +994,7 @@ static int alc_codec_rename_from_preset(struct hda_codec *codec) static const struct snd_pci_quirk beep_white_list[] = { SND_PCI_QUIRK(0x1043, 0x103c, "ASUS", 1), + SND_PCI_QUIRK(0x1043, 0x115d, "ASUS", 1), SND_PCI_QUIRK(0x1043, 0x829f, "ASUS", 1), SND_PCI_QUIRK(0x1043, 0x8376, "EeePC", 1), SND_PCI_QUIRK(0x1043, 0x83ce, "EeePC", 1), @@ -2786,6 +2788,237 @@ static void alc269_shutup(struct hda_codec *codec) snd_hda_shutup_pins(codec); } +static void alc282_restore_default_value(struct hda_codec *codec) +{ + int val; + + /* Power Down Control */ + alc_write_coef_idx(codec, 0x03, 0x0002); + /* FIFO and filter clock */ + alc_write_coef_idx(codec, 0x05, 0x0700); + /* DMIC control */ + alc_write_coef_idx(codec, 0x07, 0x0200); + /* Analog clock */ + val = alc_read_coef_idx(codec, 0x06); + alc_write_coef_idx(codec, 0x06, (val & ~0x00f0) | 0x0); + /* JD */ + val = alc_read_coef_idx(codec, 0x08); + alc_write_coef_idx(codec, 0x08, (val & ~0xfffc) | 0x0c2c); + /* JD offset1 */ + alc_write_coef_idx(codec, 0x0a, 0xcccc); + /* JD offset2 */ + alc_write_coef_idx(codec, 0x0b, 0xcccc); + /* LDO1/2/3, DAC/ADC */ + alc_write_coef_idx(codec, 0x0e, 0x6e00); + /* JD */ + val = alc_read_coef_idx(codec, 0x0f); + alc_write_coef_idx(codec, 0x0f, (val & ~0xf800) | 0x1000); + /* Capless */ + val = alc_read_coef_idx(codec, 0x10); + alc_write_coef_idx(codec, 0x10, (val & ~0xfc00) | 0x0c00); + /* Class D test 4 */ + alc_write_coef_idx(codec, 0x6f, 0x0); + /* IO power down directly */ + val = alc_read_coef_idx(codec, 0x0c); + alc_write_coef_idx(codec, 0x0c, (val & ~0xfe00) | 0x0); + /* ANC */ + alc_write_coef_idx(codec, 0x34, 0xa0c0); + /* AGC MUX */ + val = alc_read_coef_idx(codec, 0x16); + alc_write_coef_idx(codec, 0x16, (val & ~0x0008) | 0x0); + /* DAC simple content protection */ + val = alc_read_coef_idx(codec, 0x1d); + alc_write_coef_idx(codec, 0x1d, (val & ~0x00e0) | 0x0); + /* ADC simple content protection */ + val = alc_read_coef_idx(codec, 0x1f); + alc_write_coef_idx(codec, 0x1f, (val & ~0x00e0) | 0x0); + /* DAC ADC Zero Detection */ + alc_write_coef_idx(codec, 0x21, 0x8804); + /* PLL */ + alc_write_coef_idx(codec, 0x63, 0x2902); + /* capless control 2 */ + alc_write_coef_idx(codec, 0x68, 0xa080); + /* capless control 3 */ + alc_write_coef_idx(codec, 0x69, 0x3400); + /* capless control 4 */ + alc_write_coef_idx(codec, 0x6a, 0x2f3e); + /* capless control 5 */ + alc_write_coef_idx(codec, 0x6b, 0x0); + /* class D test 2 */ + val = alc_read_coef_idx(codec, 0x6d); + alc_write_coef_idx(codec, 0x6d, (val & ~0x0fff) | 0x0900); + /* class D test 3 */ + alc_write_coef_idx(codec, 0x6e, 0x110a); + /* class D test 5 */ + val = alc_read_coef_idx(codec, 0x70); + alc_write_coef_idx(codec, 0x70, (val & ~0x00f8) | 0x00d8); + /* class D test 6 */ + alc_write_coef_idx(codec, 0x71, 0x0014); + /* classD OCP */ + alc_write_coef_idx(codec, 0x72, 0xc2ba); + /* classD pure DC test */ + val = alc_read_coef_idx(codec, 0x77); + alc_write_coef_idx(codec, 0x77, (val & ~0x0f80) | 0x0); + /* Class D amp control */ + alc_write_coef_idx(codec, 0x6c, 0xfc06); +} + +static void alc282_init(struct hda_codec *codec) +{ + struct alc_spec *spec = codec->spec; + hda_nid_t hp_pin = spec->gen.autocfg.hp_pins[0]; + bool hp_pin_sense; + int coef78; + + alc282_restore_default_value(codec); + + if (!hp_pin) + return; + hp_pin_sense = snd_hda_jack_detect(codec, hp_pin); + coef78 = alc_read_coef_idx(codec, 0x78); + + /* Index 0x78 Direct Drive HP AMP LPM Control 1 */ + /* Headphone capless set to high power mode */ + alc_write_coef_idx(codec, 0x78, 0x9004); + + if (hp_pin_sense) + msleep(2); + + snd_hda_codec_write(codec, hp_pin, 0, + AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE); + + if (hp_pin_sense) + msleep(85); + + snd_hda_codec_write(codec, hp_pin, 0, + AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT); + + if (hp_pin_sense) + msleep(100); + + /* Headphone capless set to normal mode */ + alc_write_coef_idx(codec, 0x78, coef78); +} + +static void alc282_shutup(struct hda_codec *codec) +{ + struct alc_spec *spec = codec->spec; + hda_nid_t hp_pin = spec->gen.autocfg.hp_pins[0]; + bool hp_pin_sense; + int coef78; + + if (!hp_pin) { + alc269_shutup(codec); + return; + } + + hp_pin_sense = snd_hda_jack_detect(codec, hp_pin); + coef78 = alc_read_coef_idx(codec, 0x78); + alc_write_coef_idx(codec, 0x78, 0x9004); + + if (hp_pin_sense) + msleep(2); + + snd_hda_codec_write(codec, hp_pin, 0, + AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE); + + if (hp_pin_sense) + msleep(85); + + snd_hda_codec_write(codec, hp_pin, 0, + AC_VERB_SET_PIN_WIDGET_CONTROL, 0x0); + + if (hp_pin_sense) + msleep(100); + + alc_auto_setup_eapd(codec, false); + snd_hda_shutup_pins(codec); + alc_write_coef_idx(codec, 0x78, coef78); +} + +static void alc283_restore_default_value(struct hda_codec *codec) +{ + int val; + + /* Power Down Control */ + alc_write_coef_idx(codec, 0x03, 0x0002); + /* FIFO and filter clock */ + alc_write_coef_idx(codec, 0x05, 0x0700); + /* DMIC control */ + alc_write_coef_idx(codec, 0x07, 0x0200); + /* Analog clock */ + val = alc_read_coef_idx(codec, 0x06); + alc_write_coef_idx(codec, 0x06, (val & ~0x00f0) | 0x0); + /* JD */ + val = alc_read_coef_idx(codec, 0x08); + alc_write_coef_idx(codec, 0x08, (val & ~0xfffc) | 0x0c2c); + /* JD offset1 */ + alc_write_coef_idx(codec, 0x0a, 0xcccc); + /* JD offset2 */ + alc_write_coef_idx(codec, 0x0b, 0xcccc); + /* LDO1/2/3, DAC/ADC */ + alc_write_coef_idx(codec, 0x0e, 0x6fc0); + /* JD */ + val = alc_read_coef_idx(codec, 0x0f); + alc_write_coef_idx(codec, 0x0f, (val & ~0xf800) | 0x1000); + /* Capless */ + val = alc_read_coef_idx(codec, 0x10); + alc_write_coef_idx(codec, 0x10, (val & ~0xfc00) | 0x0c00); + /* Class D test 4 */ + alc_write_coef_idx(codec, 0x3a, 0x0); + /* IO power down directly */ + val = alc_read_coef_idx(codec, 0x0c); + alc_write_coef_idx(codec, 0x0c, (val & ~0xfe00) | 0x0); + /* ANC */ + alc_write_coef_idx(codec, 0x22, 0xa0c0); + /* AGC MUX */ + val = alc_read_coefex_idx(codec, 0x53, 0x01); + alc_write_coefex_idx(codec, 0x53, 0x01, (val & ~0x000f) | 0x0008); + /* DAC simple content protection */ + val = alc_read_coef_idx(codec, 0x1d); + alc_write_coef_idx(codec, 0x1d, (val & ~0x00e0) | 0x0); + /* ADC simple content protection */ + val = alc_read_coef_idx(codec, 0x1f); + alc_write_coef_idx(codec, 0x1f, (val & ~0x00e0) | 0x0); + /* DAC ADC Zero Detection */ + alc_write_coef_idx(codec, 0x21, 0x8804); + /* PLL */ + alc_write_coef_idx(codec, 0x2e, 0x2902); + /* capless control 2 */ + alc_write_coef_idx(codec, 0x33, 0xa080); + /* capless control 3 */ + alc_write_coef_idx(codec, 0x34, 0x3400); + /* capless control 4 */ + alc_write_coef_idx(codec, 0x35, 0x2f3e); + /* capless control 5 */ + alc_write_coef_idx(codec, 0x36, 0x0); + /* class D test 2 */ + val = alc_read_coef_idx(codec, 0x38); + alc_write_coef_idx(codec, 0x38, (val & ~0x0fff) | 0x0900); + /* class D test 3 */ + alc_write_coef_idx(codec, 0x39, 0x110a); + /* class D test 5 */ + val = alc_read_coef_idx(codec, 0x3b); + alc_write_coef_idx(codec, 0x3b, (val & ~0x00f8) | 0x00d8); + /* class D test 6 */ + alc_write_coef_idx(codec, 0x3c, 0x0014); + /* classD OCP */ + alc_write_coef_idx(codec, 0x3d, 0xc2ba); + /* classD pure DC test */ + val = alc_read_coef_idx(codec, 0x42); + alc_write_coef_idx(codec, 0x42, (val & ~0x0f80) | 0x0); + /* test mode */ + alc_write_coef_idx(codec, 0x49, 0x0); + /* Class D DC enable */ + val = alc_read_coef_idx(codec, 0x40); + alc_write_coef_idx(codec, 0x40, (val & ~0xf800) | 0x9800); + /* DC offset */ + val = alc_read_coef_idx(codec, 0x42); + alc_write_coef_idx(codec, 0x42, (val & ~0xf000) | 0x2000); + /* Class D amp control */ + alc_write_coef_idx(codec, 0x37, 0xfc06); +} + static void alc283_init(struct hda_codec *codec) { struct alc_spec *spec = codec->spec; @@ -2793,6 +3026,8 @@ static void alc283_init(struct hda_codec *codec) bool hp_pin_sense; int val; + alc283_restore_default_value(codec); + if (!hp_pin) return; hp_pin_sense = snd_hda_jack_detect(codec, hp_pin); @@ -3169,7 +3404,8 @@ static void alc269_fixup_hp_mute_led(struct hda_codec *codec, spec->gen.vmaster_mute.hook = alc269_fixup_mic_mute_hook; spec->gen.vmaster_mute_enum = 1; codec->power_filter = led_power_filter; - snd_printd("Detected mute LED for %x:%d\n", spec->mute_led_nid, + codec_dbg(codec, + "Detected mute LED for %x:%d\n", spec->mute_led_nid, spec->mute_led_polarity); break; } @@ -3295,7 +3531,7 @@ static void alc_headset_mode_unplugged(struct hda_codec *codec) alc_write_coef_idx(codec, 0xb7, 0x802b); break; } - snd_printdd("Headset jack set to unplugged mode.\n"); + codec_dbg(codec, "Headset jack set to unplugged mode.\n"); } @@ -3338,7 +3574,7 @@ static void alc_headset_mode_mic_in(struct hda_codec *codec, hda_nid_t hp_pin, snd_hda_set_pin_ctl_cache(codec, mic_pin, PIN_VREF50); break; } - snd_printdd("Headset jack set to mic-in mode.\n"); + codec_dbg(codec, "Headset jack set to mic-in mode.\n"); } static void alc_headset_mode_default(struct hda_codec *codec) @@ -3366,7 +3602,7 @@ static void alc_headset_mode_default(struct hda_codec *codec) alc_write_coef_idx(codec, 0xb7, 0x802b); break; } - snd_printdd("Headset jack set to headphone (default) mode.\n"); + codec_dbg(codec, "Headset jack set to headphone (default) mode.\n"); } /* Iphone type */ @@ -3395,7 +3631,7 @@ static void alc_headset_mode_ctia(struct hda_codec *codec) alc_write_coef_idx(codec, 0xc3, 0x0000); break; } - snd_printdd("Headset jack set to iPhone-style headset mode.\n"); + codec_dbg(codec, "Headset jack set to iPhone-style headset mode.\n"); } /* Nokia type */ @@ -3424,7 +3660,7 @@ static void alc_headset_mode_omtp(struct hda_codec *codec) alc_write_coef_idx(codec, 0xc3, 0x0000); break; } - snd_printdd("Headset jack set to Nokia-style headset mode.\n"); + codec_dbg(codec, "Headset jack set to Nokia-style headset mode.\n"); } static void alc_determine_headset_type(struct hda_codec *codec) @@ -3466,7 +3702,7 @@ static void alc_determine_headset_type(struct hda_codec *codec) break; } - snd_printdd("Headset jack detected iPhone-style headset: %s\n", + codec_dbg(codec, "Headset jack detected iPhone-style headset: %s\n", is_ctia ? "yes" : "no"); spec->current_headset_type = is_ctia ? ALC_HEADSET_TYPE_CTIA : ALC_HEADSET_TYPE_OMTP; } @@ -3592,21 +3828,38 @@ static void alc_fixup_headset_mode_no_hp_mic(struct hda_codec *codec, alc_fixup_headset_mode(codec, fix, action); } +static void alc255_set_default_jack_type(struct hda_codec *codec) +{ + /* Set to iphone type */ + alc_write_coef_idx(codec, 0x1b, 0x880b); + alc_write_coef_idx(codec, 0x45, 0xd089); + alc_write_coef_idx(codec, 0x1b, 0x080b); + alc_write_coef_idx(codec, 0x46, 0x0004); + alc_write_coef_idx(codec, 0x1b, 0x0c0b); + msleep(30); +} + static void alc_fixup_headset_mode_alc255(struct hda_codec *codec, const struct hda_fixup *fix, int action) { if (action == HDA_FIXUP_ACT_PRE_PROBE) { - /* Set to iphone type */ - alc_write_coef_idx(codec, 0x1b, 0x880b); - alc_write_coef_idx(codec, 0x45, 0xd089); - alc_write_coef_idx(codec, 0x1b, 0x080b); - alc_write_coef_idx(codec, 0x46, 0x0004); - alc_write_coef_idx(codec, 0x1b, 0x0c0b); - msleep(30); + alc255_set_default_jack_type(codec); } alc_fixup_headset_mode(codec, fix, action); } +static void alc_fixup_headset_mode_alc255_no_hp_mic(struct hda_codec *codec, + const struct hda_fixup *fix, int action) +{ + if (action == HDA_FIXUP_ACT_PRE_PROBE) { + struct alc_spec *spec = codec->spec; + spec->parse_flags |= HDA_PINCFG_HEADSET_MIC; + alc255_set_default_jack_type(codec); + } + else + alc_fixup_headset_mode(codec, fix, action); +} + static void alc_fixup_auto_mute_via_amp(struct hda_codec *codec, const struct hda_fixup *fix, int action) { @@ -3887,7 +4140,9 @@ enum { ALC290_FIXUP_SUBWOOFER_HSJACK, ALC269_FIXUP_THINKPAD_ACPI, ALC255_FIXUP_DELL1_MIC_NO_PRESENCE, + ALC255_FIXUP_DELL2_MIC_NO_PRESENCE, ALC255_FIXUP_HEADSET_MODE, + ALC255_FIXUP_HEADSET_MODE_NO_HP_MIC, }; static const struct hda_fixup alc269_fixups[] = { @@ -4264,10 +4519,23 @@ static const struct hda_fixup alc269_fixups[] = { .chained = true, .chain_id = ALC255_FIXUP_HEADSET_MODE }, + [ALC255_FIXUP_DELL2_MIC_NO_PRESENCE] = { + .type = HDA_FIXUP_PINS, + .v.pins = (const struct hda_pintbl[]) { + { 0x19, 0x01a1913c }, /* use as headset mic, without its own jack detect */ + { } + }, + .chained = true, + .chain_id = ALC255_FIXUP_HEADSET_MODE_NO_HP_MIC + }, [ALC255_FIXUP_HEADSET_MODE] = { .type = HDA_FIXUP_FUNC, .v.func = alc_fixup_headset_mode_alc255, }, + [ALC255_FIXUP_HEADSET_MODE_NO_HP_MIC] = { + .type = HDA_FIXUP_FUNC, + .v.func = alc_fixup_headset_mode_alc255_no_hp_mic, + }, }; static const struct snd_pci_quirk alc269_fixup_tbl[] = { @@ -4319,6 +4587,9 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = { SND_PCI_QUIRK(0x1028, 0x0616, "Dell Vostro 5470", ALC290_FIXUP_SUBWOOFER_HSJACK), SND_PCI_QUIRK(0x1028, 0x061f, "Dell", ALC255_FIXUP_DELL1_MIC_NO_PRESENCE), SND_PCI_QUIRK(0x1028, 0x0629, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE), + SND_PCI_QUIRK(0x1028, 0x062c, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE), + SND_PCI_QUIRK(0x1028, 0x062e, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE), + SND_PCI_QUIRK(0x1028, 0x0632, "Dell", ALC255_FIXUP_DELL1_MIC_NO_PRESENCE), SND_PCI_QUIRK(0x1028, 0x0638, "Dell Inspiron 5439", ALC290_FIXUP_MONO_SPEAKERS_HSJACK), SND_PCI_QUIRK(0x1028, 0x063e, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE), SND_PCI_QUIRK(0x1028, 0x063f, "Dell", ALC255_FIXUP_DELL1_MIC_NO_PRESENCE), @@ -4331,6 +4602,8 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = { SND_PCI_QUIRK(0x1028, 0x0658, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE), SND_PCI_QUIRK(0x1028, 0x065f, "Dell", ALC255_FIXUP_DELL1_MIC_NO_PRESENCE), SND_PCI_QUIRK(0x1028, 0x0662, "Dell", ALC255_FIXUP_DELL1_MIC_NO_PRESENCE), + SND_PCI_QUIRK(0x1028, 0x0668, "Dell", ALC255_FIXUP_DELL2_MIC_NO_PRESENCE), + SND_PCI_QUIRK(0x1028, 0x0669, "Dell", ALC255_FIXUP_DELL2_MIC_NO_PRESENCE), SND_PCI_QUIRK(0x1028, 0x15cc, "Dell X5 Precision", ALC269_FIXUP_DELL2_MIC_NO_PRESENCE), SND_PCI_QUIRK(0x1028, 0x15cd, "Dell X5 Precision", ALC269_FIXUP_DELL2_MIC_NO_PRESENCE), SND_PCI_QUIRK(0x103c, 0x1586, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC2), @@ -4573,13 +4846,15 @@ static int patch_alc269(struct hda_codec *codec) spec->codec_variant = ALC269_TYPE_ALC269VA; switch (alc_get_coef0(codec) & 0x00f0) { case 0x0010: - if (codec->bus->pci->subsystem_vendor == 0x1025 && + if (codec->bus->pci && + codec->bus->pci->subsystem_vendor == 0x1025 && spec->cdefine.platform_type == 1) err = alc_codec_rename(codec, "ALC271X"); spec->codec_variant = ALC269_TYPE_ALC269VB; break; case 0x0020: - if (codec->bus->pci->subsystem_vendor == 0x17aa && + if (codec->bus->pci && + codec->bus->pci->subsystem_vendor == 0x17aa && codec->bus->pci->subsystem_device == 0x21f3) err = alc_codec_rename(codec, "ALC3202"); spec->codec_variant = ALC269_TYPE_ALC269VC; @@ -4602,6 +4877,8 @@ static int patch_alc269(struct hda_codec *codec) break; case 0x10ec0282: spec->codec_variant = ALC269_TYPE_ALC282; + spec->shutup = alc282_shutup; + spec->init_hook = alc282_init; break; case 0x10ec0233: case 0x10ec0283: @@ -4919,8 +5196,7 @@ static void alc272_fixup_mario(struct hda_codec *codec, (0x3b << AC_AMPCAP_NUM_STEPS_SHIFT) | (0x03 << AC_AMPCAP_STEP_SIZE_SHIFT) | (0 << AC_AMPCAP_MUTE_SHIFT))) - printk(KERN_WARNING - "hda_codec: failed to override amp caps for NID 0x2\n"); + codec_warn(codec, "failed to override amp caps for NID 0x2\n"); } static const struct snd_pcm_chmap_elem asus_pcm_2_1_chmaps[] = { @@ -4942,8 +5218,54 @@ static void alc_fixup_bass_chmap(struct hda_codec *codec, } } +/* turn on/off mute LED per vmaster hook */ +static void alc662_led_gpio1_mute_hook(void *private_data, int enabled) +{ + struct hda_codec *codec = private_data; + struct alc_spec *spec = codec->spec; + unsigned int oldval = spec->gpio_led; + + if (enabled) + spec->gpio_led &= ~0x01; + else + spec->gpio_led |= 0x01; + if (spec->gpio_led != oldval) + snd_hda_codec_write(codec, 0x01, 0, AC_VERB_SET_GPIO_DATA, + spec->gpio_led); +} + +/* avoid D3 for keeping GPIO up */ +static unsigned int gpio_led_power_filter(struct hda_codec *codec, + hda_nid_t nid, + unsigned int power_state) +{ + struct alc_spec *spec = codec->spec; + if (nid == codec->afg && power_state == AC_PWRST_D3 && spec->gpio_led) + return AC_PWRST_D0; + return power_state; +} + +static void alc662_fixup_led_gpio1(struct hda_codec *codec, + const struct hda_fixup *fix, int action) +{ + struct alc_spec *spec = codec->spec; + static const struct hda_verb gpio_init[] = { + { 0x01, AC_VERB_SET_GPIO_MASK, 0x01 }, + { 0x01, AC_VERB_SET_GPIO_DIRECTION, 0x01 }, + {} + }; + + if (action == HDA_FIXUP_ACT_PRE_PROBE) { + spec->gen.vmaster_mute.hook = alc662_led_gpio1_mute_hook; + spec->gpio_led = 0; + snd_hda_add_verbs(codec, gpio_init); + codec->power_filter = gpio_led_power_filter; + } +} + enum { ALC662_FIXUP_ASPIRE, + ALC662_FIXUP_LED_GPIO1, ALC662_FIXUP_IDEAPAD, ALC272_FIXUP_MARIO, ALC662_FIXUP_CZC_P10T, @@ -4962,9 +5284,10 @@ enum { ALC662_FIXUP_INV_DMIC, ALC668_FIXUP_DELL_MIC_NO_PRESENCE, ALC668_FIXUP_HEADSET_MODE, - ALC662_FIXUP_BASS_CHMAP, + ALC662_FIXUP_BASS_MODE4_CHMAP, + ALC662_FIXUP_BASS_16, ALC662_FIXUP_BASS_1A, - ALC662_FIXUP_BASS_1A_CHMAP, + ALC662_FIXUP_BASS_CHMAP, ALC668_FIXUP_AUTO_MUTE, }; @@ -4976,12 +5299,18 @@ static const struct hda_fixup alc662_fixups[] = { { } } }, + [ALC662_FIXUP_LED_GPIO1] = { + .type = HDA_FIXUP_FUNC, + .v.func = alc662_fixup_led_gpio1, + }, [ALC662_FIXUP_IDEAPAD] = { .type = HDA_FIXUP_PINS, .v.pins = (const struct hda_pintbl[]) { { 0x17, 0x99130112 }, /* subwoofer */ { } - } + }, + .chained = true, + .chain_id = ALC662_FIXUP_LED_GPIO1, }, [ALC272_FIXUP_MARIO] = { .type = HDA_FIXUP_FUNC, @@ -5146,24 +5475,33 @@ static const struct hda_fixup alc662_fixups[] = { .type = HDA_FIXUP_FUNC, .v.func = alc_fixup_headset_mode_alc668, }, - [ALC662_FIXUP_BASS_CHMAP] = { + [ALC662_FIXUP_BASS_MODE4_CHMAP] = { .type = HDA_FIXUP_FUNC, .v.func = alc_fixup_bass_chmap, .chained = true, .chain_id = ALC662_FIXUP_ASUS_MODE4 }, + [ALC662_FIXUP_BASS_16] = { + .type = HDA_FIXUP_PINS, + .v.pins = (const struct hda_pintbl[]) { + {0x16, 0x80106111}, /* bass speaker */ + {} + }, + .chained = true, + .chain_id = ALC662_FIXUP_BASS_CHMAP, + }, [ALC662_FIXUP_BASS_1A] = { .type = HDA_FIXUP_PINS, .v.pins = (const struct hda_pintbl[]) { {0x1a, 0x80106111}, /* bass speaker */ {} }, + .chained = true, + .chain_id = ALC662_FIXUP_BASS_CHMAP, }, - [ALC662_FIXUP_BASS_1A_CHMAP] = { + [ALC662_FIXUP_BASS_CHMAP] = { .type = HDA_FIXUP_FUNC, .v.func = alc_fixup_bass_chmap, - .chained = true, - .chain_id = ALC662_FIXUP_BASS_1A, }, }; @@ -5185,9 +5523,11 @@ static const struct snd_pci_quirk alc662_fixup_tbl[] = { SND_PCI_QUIRK(0x1028, 0x0628, "Dell", ALC668_FIXUP_AUTO_MUTE), SND_PCI_QUIRK(0x1028, 0x064e, "Dell", ALC668_FIXUP_AUTO_MUTE), SND_PCI_QUIRK(0x103c, 0x1632, "HP RP5800", ALC662_FIXUP_HP_RP5800), - SND_PCI_QUIRK(0x1043, 0x11cd, "Asus N550", ALC662_FIXUP_BASS_1A_CHMAP), - SND_PCI_QUIRK(0x1043, 0x1477, "ASUS N56VZ", ALC662_FIXUP_BASS_CHMAP), - SND_PCI_QUIRK(0x1043, 0x1bf3, "ASUS N76VZ", ALC662_FIXUP_BASS_CHMAP), + SND_PCI_QUIRK(0x1043, 0x11cd, "Asus N550", ALC662_FIXUP_BASS_1A), + SND_PCI_QUIRK(0x1043, 0x1477, "ASUS N56VZ", ALC662_FIXUP_BASS_MODE4_CHMAP), + SND_PCI_QUIRK(0x1043, 0x15a7, "ASUS UX51VZH", ALC662_FIXUP_BASS_16), + SND_PCI_QUIRK(0x1043, 0x1b73, "ASUS N55SF", ALC662_FIXUP_BASS_16), + SND_PCI_QUIRK(0x1043, 0x1bf3, "ASUS N76VZ", ALC662_FIXUP_BASS_MODE4_CHMAP), SND_PCI_QUIRK(0x1043, 0x8469, "ASUS mobo", ALC662_FIXUP_NO_JACK_DETECT), SND_PCI_QUIRK(0x105b, 0x0cd6, "Foxconn", ALC662_FIXUP_ASUS_MODE2), SND_PCI_QUIRK(0x144d, 0xc051, "Samsung R720", ALC662_FIXUP_IDEAPAD), @@ -5328,7 +5668,7 @@ static int patch_alc662(struct hda_codec *codec) spec->gen.beep_nid = 0x01; if ((alc_get_coef0(codec) & (1 << 14)) && - codec->bus->pci->subsystem_vendor == 0x1025 && + codec->bus->pci && codec->bus->pci->subsystem_vendor == 0x1025 && spec->cdefine.platform_type == 1) { err = alc_codec_rename(codec, "ALC272X"); if (err < 0) diff --git a/sound/pci/hda/patch_si3054.c b/sound/pci/hda/patch_si3054.c index 6679a5095e5..3208ad69583 100644 --- a/sound/pci/hda/patch_si3054.c +++ b/sound/pci/hda/patch_si3054.c @@ -236,7 +236,7 @@ static int si3054_init(struct hda_codec *codec) } while ((val & SI3054_MEI_READY) != SI3054_MEI_READY && wait_count--); if((val&SI3054_MEI_READY) != SI3054_MEI_READY) { - snd_printk(KERN_ERR "si3054: cannot initialize. EXT MID = %04x\n", val); + codec_err(codec, "si3054: cannot initialize. EXT MID = %04x\n", val); /* let's pray that this is no fatal error */ /* return -EACCES; */ } @@ -247,7 +247,8 @@ static int si3054_init(struct hda_codec *codec) SET_REG(codec, SI3054_LINE_CFG1,0x200); if((GET_REG(codec,SI3054_LINE_STATUS) & (1<<6)) == 0) { - snd_printd("Link Frame Detect(FDT) is not ready (line status: %04x)\n", + codec_dbg(codec, + "Link Frame Detect(FDT) is not ready (line status: %04x)\n", GET_REG(codec,SI3054_LINE_STATUS)); } diff --git a/sound/pci/hda/patch_sigmatel.c b/sound/pci/hda/patch_sigmatel.c index 3bc29c9b252..75515b49403 100644 --- a/sound/pci/hda/patch_sigmatel.c +++ b/sound/pci/hda/patch_sigmatel.c @@ -296,7 +296,7 @@ static void stac_gpio_set(struct hda_codec *codec, unsigned int mask, { unsigned int gpiostate, gpiomask, gpiodir; - snd_printdd("%s msk %x dir %x gpio %x\n", __func__, mask, dir_mask, data); + codec_dbg(codec, "%s msk %x dir %x gpio %x\n", __func__, mask, dir_mask, data); gpiostate = snd_hda_codec_read(codec, codec->afg, 0, AC_VERB_GET_GPIO_DATA, 0); @@ -359,7 +359,7 @@ static int stac_vrefout_set(struct hda_codec *codec, { int error, pinctl; - snd_printdd("%s, nid %x ctl %x\n", __func__, nid, new_vref); + codec_dbg(codec, "%s, nid %x ctl %x\n", __func__, nid, new_vref); pinctl = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_PIN_WIDGET_CONTROL, 0); @@ -2086,9 +2086,12 @@ static void stac92hd83xxx_fixup_hp(struct hda_codec *codec, } if (find_mute_led_cfg(codec, spec->default_polarity)) - snd_printd("mute LED gpio %d polarity %d\n", + codec_dbg(codec, "mute LED gpio %d polarity %d\n", spec->gpio_led, spec->gpio_led_polarity); + + /* allow auto-switching of dock line-in */ + spec->gen.line_in_auto_switch = true; } static void stac92hd83xxx_fixup_hp_zephyr(struct hda_codec *codec, @@ -3077,7 +3080,7 @@ static void stac92hd71bxx_fixup_hp(struct hda_codec *codec, } if (find_mute_led_cfg(codec, 1)) - snd_printd("mute LED gpio %d polarity %d\n", + codec_dbg(codec, "mute LED gpio %d polarity %d\n", spec->gpio_led, spec->gpio_led_polarity); @@ -4422,8 +4425,8 @@ static int patch_stac92hd73xx(struct hda_codec *codec) num_dacs = snd_hda_get_num_conns(codec, 0x0a) - 1; if (num_dacs < 3 || num_dacs > 5) { - printk(KERN_WARNING "hda_codec: Could not determine " - "number of channels defaulting to DAC count\n"); + codec_warn(codec, + "Could not determine number of channels defaulting to DAC count\n"); num_dacs = 5; } diff --git a/sound/pci/hda/patch_via.c b/sound/pci/hda/patch_via.c index f84195f3ea3..778166259b3 100644 --- a/sound/pci/hda/patch_via.c +++ b/sound/pci/hda/patch_via.c @@ -465,14 +465,8 @@ static void via_playback_pcm_hook(struct hda_pcm_stream *hinfo, static void via_free(struct hda_codec *codec) { - struct via_spec *spec = codec->spec; - - if (!spec) - return; - vt1708_stop_hp_work(codec); - snd_hda_gen_spec_free(&spec->gen); - kfree(spec); + snd_hda_gen_free(codec); } #ifdef CONFIG_PM diff --git a/sound/pci/hda/thinkpad_helper.c b/sound/pci/hda/thinkpad_helper.c index 8fe3b8c18ed..6ba0b5517c4 100644 --- a/sound/pci/hda/thinkpad_helper.c +++ b/sound/pci/hda/thinkpad_helper.c @@ -63,7 +63,8 @@ static void hda_fixup_thinkpad_acpi(struct hda_codec *codec, if (!led_set_func) led_set_func = symbol_request(tpacpi_led_set); if (!led_set_func) { - snd_printk(KERN_WARNING "Failed to find thinkpad-acpi symbol tpacpi_led_set\n"); + codec_warn(codec, + "Failed to find thinkpad-acpi symbol tpacpi_led_set\n"); return; } @@ -75,7 +76,8 @@ static void hda_fixup_thinkpad_acpi(struct hda_codec *codec, } if (led_set_func(TPACPI_LED_MICMUTE, false) >= 0) { if (spec->num_adc_nids > 1) - snd_printdd("Skipping micmute LED control due to several ADCs"); + codec_dbg(codec, + "Skipping micmute LED control due to several ADCs"); else { spec->cap_sync_hook = update_tpacpi_micmute_led; removefunc = false; diff --git a/sound/pci/ice1712/aureon.c b/sound/pci/ice1712/aureon.c index 55902ec4034..3b3cf4ac906 100644 --- a/sound/pci/ice1712/aureon.c +++ b/sound/pci/ice1712/aureon.c @@ -1937,9 +1937,12 @@ static int aureon_add_controls(struct snd_ice1712 *ice) snd_ice1712_save_gpio_status(ice); id = aureon_cs8415_get(ice, CS8415_ID); if (id != 0x41) - snd_printk(KERN_INFO "No CS8415 chip. Skipping CS8415 controls.\n"); + dev_info(ice->card->dev, + "No CS8415 chip. Skipping CS8415 controls.\n"); else if ((id & 0x0F) != 0x01) - snd_printk(KERN_INFO "Detected unsupported CS8415 rev. (%c)\n", (char)((id & 0x0F) + 'A' - 1)); + dev_info(ice->card->dev, + "Detected unsupported CS8415 rev. (%c)\n", + (char)((id & 0x0F) + 'A' - 1)); else { for (i = 0; i < ARRAY_SIZE(cs8415_controls); i++) { struct snd_kcontrol *kctl; diff --git a/sound/pci/ice1712/delta.c b/sound/pci/ice1712/delta.c index 9e28cc12969..ed2144eee38 100644 --- a/sound/pci/ice1712/delta.c +++ b/sound/pci/ice1712/delta.c @@ -425,7 +425,8 @@ static int snd_ice1712_delta1010lt_wordclock_status_get(struct snd_kcontrol *kco struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); if (snd_i2c_sendbytes(ice->cs8427, ®, 1) != 1) - snd_printk(KERN_ERR "unable to send register 0x%x byte to CS8427\n", reg); + dev_err(ice->card->dev, + "unable to send register 0x%x byte to CS8427\n", reg); snd_i2c_readbytes(ice->cs8427, ®, 1); ucontrol->value.integer.value[0] = (reg & CS8427_UNLOCK) ? 1 : 0; return 0; @@ -575,6 +576,30 @@ static struct snd_ak4xxx_private akm_vx442_priv = { .mask_flags = 0, }; +#ifdef CONFIG_PM_SLEEP +static int snd_ice1712_delta_resume(struct snd_ice1712 *ice) +{ + unsigned char akm_backup[AK4XXX_IMAGE_SIZE]; + /* init codec and restore registers */ + if (ice->akm_codecs) { + memcpy(akm_backup, ice->akm->images, sizeof(akm_backup)); + snd_akm4xxx_init(ice->akm); + memcpy(ice->akm->images, akm_backup, sizeof(akm_backup)); + snd_akm4xxx_reset(ice->akm, 0); + } + + return 0; +} + +static int snd_ice1712_delta_suspend(struct snd_ice1712 *ice) +{ + if (ice->akm_codecs) /* reset & mute codec */ + snd_akm4xxx_reset(ice->akm, 1); + + return 0; +} +#endif + static int snd_ice1712_delta_init(struct snd_ice1712 *ice) { int err; @@ -621,7 +646,11 @@ static int snd_ice1712_delta_init(struct snd_ice1712 *ice) ice->num_total_adcs = 4; break; } - +#ifdef CONFIG_PM_SLEEP + ice->pm_resume = snd_ice1712_delta_resume; + ice->pm_suspend = snd_ice1712_delta_suspend; + ice->pm_suspend_enabled = 1; +#endif /* initialize the SPI clock to high */ tmp = snd_ice1712_read(ice, ICE1712_IREG_GPIO_DATA); tmp |= ICE1712_DELTA_AP_CCLK; @@ -637,7 +666,7 @@ static int snd_ice1712_delta_init(struct snd_ice1712 *ice) case ICE1712_SUBDEVICE_VX442: case ICE1712_SUBDEVICE_DELTA66E: if ((err = snd_i2c_bus_create(ice->card, "ICE1712 GPIO 1", NULL, &ice->i2c)) < 0) { - snd_printk(KERN_ERR "unable to create I2C bus\n"); + dev_err(ice->card->dev, "unable to create I2C bus\n"); return err; } ice->i2c->private_data = ice; diff --git a/sound/pci/ice1712/ews.c b/sound/pci/ice1712/ews.c index bc2e7011c55..817a1bc50a6 100644 --- a/sound/pci/ice1712/ews.c +++ b/sound/pci/ice1712/ews.c @@ -163,7 +163,8 @@ static int snd_ice1712_ews88mt_chip_select(struct snd_ice1712 *ice, int chip_mas __error: snd_i2c_unlock(ice->i2c); - snd_printk(KERN_ERR "AK4524 chip select failed, check cable to the front module\n"); + dev_err(ice->card->dev, + "AK4524 chip select failed, check cable to the front module\n"); return -EIO; } @@ -174,7 +175,7 @@ static void ews88mt_ak4524_lock(struct snd_akm4xxx *ak, int chip) unsigned char tmp; /* assert AK4524 CS */ if (snd_ice1712_ews88mt_chip_select(ice, ~(1 << chip) & 0x0f) < 0) - snd_printk(KERN_ERR "fatal error (ews88mt chip select)\n"); + dev_err(ice->card->dev, "fatal error (ews88mt chip select)\n"); snd_ice1712_save_gpio_status(ice); tmp = ICE1712_EWS88_SERIAL_DATA | ICE1712_EWS88_SERIAL_CLOCK | @@ -456,7 +457,7 @@ static int snd_ice1712_ews_init(struct snd_ice1712 *ice) /* create i2c */ if ((err = snd_i2c_bus_create(ice->card, "ICE1712 GPIO 1", NULL, &ice->i2c)) < 0) { - snd_printk(KERN_ERR "unable to create I2C bus\n"); + dev_err(ice->card->dev, "unable to create I2C bus\n"); return err; } ice->i2c->private_data = ice; @@ -469,7 +470,8 @@ static int snd_ice1712_ews_init(struct snd_ice1712 *ice) ICE1712_6FIRE_PCF9554_ADDR, &spec->i2cdevs[EWS_I2C_6FIRE]); if (err < 0) { - snd_printk(KERN_ERR "PCF9554 initialization failed\n"); + dev_err(ice->card->dev, + "PCF9554 initialization failed\n"); return err; } snd_ice1712_6fire_write_pca(ice, PCF9554_REG_CONFIG, 0x80); @@ -834,7 +836,7 @@ static int snd_ice1712_6fire_read_pca(struct snd_ice1712 *ice, unsigned char reg byte = 0; if (snd_i2c_readbytes(spec->i2cdevs[EWS_I2C_6FIRE], &byte, 1) != 1) { snd_i2c_unlock(ice->i2c); - printk(KERN_ERR "cannot read pca\n"); + dev_err(ice->card->dev, "cannot read pca\n"); return -EIO; } snd_i2c_unlock(ice->i2c); diff --git a/sound/pci/ice1712/ice1712.c b/sound/pci/ice1712/ice1712.c index 28ec872e54c..291672fc4a9 100644 --- a/sound/pci/ice1712/ice1712.c +++ b/sound/pci/ice1712/ice1712.c @@ -394,7 +394,7 @@ int snd_ice1712_init_cs8427(struct snd_ice1712 *ice, int addr) err = snd_cs8427_create(ice->i2c, addr, (ice->cs8427_timeout * HZ) / 1000, &ice->cs8427); if (err < 0) { - snd_printk(KERN_ERR "CS8427 initialization failed\n"); + dev_err(ice->card->dev, "CS8427 initialization failed\n"); return err; } ice->spdif.ops.open = open_cs8427; @@ -467,7 +467,7 @@ static irqreturn_t snd_ice1712_interrupt(int irq, void *dev_id) u16 pbkstatus; struct snd_pcm_substream *substream; pbkstatus = inw(ICEDS(ice, INTSTAT)); - /* printk(KERN_DEBUG "pbkstatus = 0x%x\n", pbkstatus); */ + /* dev_dbg(ice->card->dev, "pbkstatus = 0x%x\n", pbkstatus); */ for (idx = 0; idx < 6; idx++) { if ((pbkstatus & (3 << (idx * 2))) == 0) continue; @@ -903,7 +903,8 @@ static int snd_ice1712_pcm(struct snd_ice1712 *ice, int device, struct snd_pcm * if (rpcm) *rpcm = pcm; - printk(KERN_WARNING "Consumer PCM code does not work well at the moment --jk\n"); + dev_warn(ice->card->dev, + "Consumer PCM code does not work well at the moment --jk\n"); return 0; } @@ -1534,7 +1535,8 @@ static int snd_ice1712_ac97_mixer(struct snd_ice1712 *ice) ac97.private_free = snd_ice1712_mixer_free_ac97; err = snd_ac97_mixer(pbus, &ac97, &ice->ac97); if (err < 0) - printk(KERN_WARNING "ice1712: cannot initialize ac97 for consumer, skipped\n"); + dev_warn(ice->card->dev, + "cannot initialize ac97 for consumer, skipped\n"); else { err = snd_ctl_add(ice->card, snd_ctl_new1(&snd_ice1712_mixer_digmix_route_ac97, ice)); if (err < 0) @@ -1552,7 +1554,8 @@ static int snd_ice1712_ac97_mixer(struct snd_ice1712 *ice) ac97.private_free = snd_ice1712_mixer_free_ac97; err = snd_ac97_mixer(pbus, &ac97, &ice->ac97); if (err < 0) - printk(KERN_WARNING "ice1712: cannot initialize pro ac97, skipped\n"); + dev_warn(ice->card->dev, + "cannot initialize pro ac97, skipped\n"); else return 0; } @@ -2332,7 +2335,8 @@ static int snd_ice1712_read_eeprom(struct snd_ice1712 *ice, pci_read_config_word(ice->pci, PCI_SUBSYSTEM_ID, &device); ice->eeprom.subvendor = ((unsigned int)swab16(vendor) << 16) | swab16(device); if (ice->eeprom.subvendor == 0 || ice->eeprom.subvendor == (unsigned int)-1) { - printk(KERN_ERR "ice1712: No valid ID is found\n"); + dev_err(ice->card->dev, + "No valid ID is found\n"); return -ENXIO; } } @@ -2340,21 +2344,22 @@ static int snd_ice1712_read_eeprom(struct snd_ice1712 *ice, for (tbl = card_tables; *tbl; tbl++) { for (c = *tbl; c->subvendor; c++) { if (modelname && c->model && !strcmp(modelname, c->model)) { - printk(KERN_INFO "ice1712: Using board model %s\n", c->name); + dev_info(ice->card->dev, + "Using board model %s\n", c->name); ice->eeprom.subvendor = c->subvendor; } else if (c->subvendor != ice->eeprom.subvendor) continue; if (!c->eeprom_size || !c->eeprom_data) goto found; /* if the EEPROM is given by the driver, use it */ - snd_printdd("using the defined eeprom..\n"); + dev_dbg(ice->card->dev, "using the defined eeprom..\n"); ice->eeprom.version = 1; ice->eeprom.size = c->eeprom_size + 6; memcpy(ice->eeprom.data, c->eeprom_data, c->eeprom_size); goto read_skipped; } } - printk(KERN_WARNING "ice1712: No matching model found for ID 0x%x\n", + dev_warn(ice->card->dev, "No matching model found for ID 0x%x\n", ice->eeprom.subvendor); found: @@ -2362,12 +2367,13 @@ static int snd_ice1712_read_eeprom(struct snd_ice1712 *ice, if (ice->eeprom.size < 6) ice->eeprom.size = 32; /* FIXME: any cards without the correct size? */ else if (ice->eeprom.size > 32) { - snd_printk(KERN_ERR "invalid EEPROM (size = %i)\n", ice->eeprom.size); + dev_err(ice->card->dev, + "invalid EEPROM (size = %i)\n", ice->eeprom.size); return -EIO; } ice->eeprom.version = snd_ice1712_read_i2c(ice, dev, 0x05); if (ice->eeprom.version != 1) { - snd_printk(KERN_ERR "invalid EEPROM version %i\n", + dev_err(ice->card->dev, "invalid EEPROM version %i\n", ice->eeprom.version); /* return -EIO; */ } @@ -2428,6 +2434,13 @@ static int snd_ice1712_chip_init(struct snd_ice1712 *ice) snd_ice1712_write(ice, ICE1712_IREG_CONSUMER_POWERDOWN, 0); } snd_ice1712_set_pro_rate(ice, 48000, 1); + /* unmask used interrupts */ + outb(((ice->eeprom.data[ICE_EEP1_CODEC] & ICE1712_CFG_2xMPU401) == 0 ? + ICE1712_IRQ_MPU2 : 0) | + ((ice->eeprom.data[ICE_EEP1_CODEC] & ICE1712_CFG_NO_CON_AC97) ? + ICE1712_IRQ_PBKDS | ICE1712_IRQ_CONCAP | ICE1712_IRQ_CONPBK : 0), + ICEREG(ice, IRQMASK)); + outb(0x00, ICEMT(ice, IRQ)); return 0; } @@ -2553,7 +2566,8 @@ static int snd_ice1712_create(struct snd_card *card, /* check, if we can restrict PCI DMA transfers to 28 bits */ if (pci_set_dma_mask(pci, DMA_BIT_MASK(28)) < 0 || pci_set_consistent_dma_mask(pci, DMA_BIT_MASK(28)) < 0) { - snd_printk(KERN_ERR "architecture does not support 28bit PCI busmaster DMA\n"); + dev_err(card->dev, + "architecture does not support 28bit PCI busmaster DMA\n"); pci_disable_device(pci); return -ENXIO; } @@ -2589,6 +2603,7 @@ static int snd_ice1712_create(struct snd_card *card, ice->pci = pci; ice->irq = -1; pci_set_master(pci); + /* disable legacy emulation */ pci_write_config_word(ice->pci, 0x40, 0x807f); pci_write_config_word(ice->pci, 0x42, 0x0006); snd_ice1712_proc_init(ice); @@ -2609,7 +2624,7 @@ static int snd_ice1712_create(struct snd_card *card, if (request_irq(pci->irq, snd_ice1712_interrupt, IRQF_SHARED, KBUILD_MODNAME, ice)) { - snd_printk(KERN_ERR "unable to grab IRQ %d\n", pci->irq); + dev_err(card->dev, "unable to grab IRQ %d\n", pci->irq); snd_ice1712_free(ice); return -EIO; } @@ -2625,22 +2640,12 @@ static int snd_ice1712_create(struct snd_card *card, return -EIO; } - /* unmask used interrupts */ - outb(((ice->eeprom.data[ICE_EEP1_CODEC] & ICE1712_CFG_2xMPU401) == 0 ? - ICE1712_IRQ_MPU2 : 0) | - ((ice->eeprom.data[ICE_EEP1_CODEC] & ICE1712_CFG_NO_CON_AC97) ? - ICE1712_IRQ_PBKDS | ICE1712_IRQ_CONCAP | ICE1712_IRQ_CONPBK : 0), - ICEREG(ice, IRQMASK)); - outb(0x00, ICEMT(ice, IRQ)); - err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, ice, &ops); if (err < 0) { snd_ice1712_free(ice); return err; } - snd_card_set_dev(card, &pci->dev); - *r_ice1712 = ice; return 0; } @@ -2670,7 +2675,8 @@ static int snd_ice1712_probe(struct pci_dev *pci, return -ENOENT; } - err = snd_card_create(index[dev], id[dev], THIS_MODULE, 0, &card); + err = snd_card_new(&pci->dev, index[dev], id[dev], THIS_MODULE, + 0, &card); if (err < 0) return err; @@ -2809,11 +2815,80 @@ static void snd_ice1712_remove(struct pci_dev *pci) snd_card_free(card); } +#ifdef CONFIG_PM_SLEEP +static int snd_ice1712_suspend(struct device *dev) +{ + struct pci_dev *pci = to_pci_dev(dev); + struct snd_card *card = dev_get_drvdata(dev); + struct snd_ice1712 *ice = card->private_data; + + if (!ice->pm_suspend_enabled) + return 0; + + snd_power_change_state(card, SNDRV_CTL_POWER_D3hot); + + snd_pcm_suspend_all(ice->pcm); + snd_pcm_suspend_all(ice->pcm_pro); + snd_pcm_suspend_all(ice->pcm_ds); + snd_ac97_suspend(ice->ac97); + + if (ice->pm_suspend) + ice->pm_suspend(ice); + + pci_disable_device(pci); + pci_save_state(pci); + pci_set_power_state(pci, PCI_D3hot); + return 0; +} + +static int snd_ice1712_resume(struct device *dev) +{ + struct pci_dev *pci = to_pci_dev(dev); + struct snd_card *card = dev_get_drvdata(dev); + struct snd_ice1712 *ice = card->private_data; + + if (!ice->pm_suspend_enabled) + return 0; + + pci_set_power_state(pci, PCI_D0); + pci_restore_state(pci); + + if (pci_enable_device(pci) < 0) { + snd_card_disconnect(card); + return -EIO; + } + + pci_set_master(pci); + + if (snd_ice1712_chip_init(ice) < 0) { + snd_card_disconnect(card); + return -EIO; + } + + if (ice->pm_resume) + ice->pm_resume(ice); + + if (ice->ac97) + snd_ac97_resume(ice->ac97); + + snd_power_change_state(card, SNDRV_CTL_POWER_D0); + return 0; +} + +static SIMPLE_DEV_PM_OPS(snd_ice1712_pm, snd_ice1712_suspend, snd_ice1712_resume); +#define SND_VT1712_PM_OPS &snd_ice1712_pm +#else +#define SND_VT1712_PM_OPS NULL +#endif /* CONFIG_PM_SLEEP */ + static struct pci_driver ice1712_driver = { .name = KBUILD_MODNAME, .id_table = snd_ice1712_ids, .probe = snd_ice1712_probe, .remove = snd_ice1712_remove, + .driver = { + .pm = SND_VT1712_PM_OPS, + }, }; module_pci_driver(ice1712_driver); diff --git a/sound/pci/ice1712/ice1724.c b/sound/pci/ice1712/ice1724.c index 50047177829..5e7948f3efe 100644 --- a/sound/pci/ice1712/ice1724.c +++ b/sound/pci/ice1712/ice1724.c @@ -146,7 +146,7 @@ static unsigned char snd_vt1724_ac97_ready(struct snd_ice1712 *ice) continue; return old_cmd; } - snd_printd(KERN_ERR "snd_vt1724_ac97_ready: timeout\n"); + dev_dbg(ice->card->dev, "snd_vt1724_ac97_ready: timeout\n"); return old_cmd; } @@ -156,7 +156,7 @@ static int snd_vt1724_ac97_wait_bit(struct snd_ice1712 *ice, unsigned char bit) for (tm = 0; tm < 0x10000; tm++) if ((inb(ICEMT1724(ice, AC97_CMD)) & bit) == 0) return 0; - snd_printd(KERN_ERR "snd_vt1724_ac97_wait_bit: timeout\n"); + dev_dbg(ice->card->dev, "snd_vt1724_ac97_wait_bit: timeout\n"); return -EIO; } @@ -430,10 +430,10 @@ static irqreturn_t snd_vt1724_interrupt(int irq, void *dev_id) spin_lock(&ice->reg_lock); if (++timeout > 10) { status = inb(ICEREG1724(ice, IRQSTAT)); - printk(KERN_ERR "ice1724: Too long irq loop, " - "status = 0x%x\n", status); + dev_err(ice->card->dev, + "Too long irq loop, status = 0x%x\n", status); if (status & VT1724_IRQ_MPU_TX) { - printk(KERN_ERR "ice1724: Disabling MPU_TX\n"); + dev_err(ice->card->dev, "Disabling MPU_TX\n"); enable_midi_irq(ice, VT1724_IRQ_MPU_TX, 0); } spin_unlock(&ice->reg_lock); @@ -801,7 +801,7 @@ static int snd_vt1724_playback_pro_prepare(struct snd_pcm_substream *substream) spin_unlock_irq(&ice->reg_lock); /* - printk(KERN_DEBUG "pro prepare: ch = %d, addr = 0x%x, " + dev_dbg(ice->card->dev, "pro prepare: ch = %d, addr = 0x%x, " "buffer = 0x%x, period = 0x%x\n", substream->runtime->channels, (unsigned int)substream->runtime->dma_addr, @@ -821,13 +821,13 @@ static snd_pcm_uframes_t snd_vt1724_playback_pro_pointer(struct snd_pcm_substrea #if 0 /* read PLAYBACK_ADDR */ ptr = inl(ICEMT1724(ice, PLAYBACK_ADDR)); if (ptr < substream->runtime->dma_addr) { - snd_printd("ice1724: invalid negative ptr\n"); + dev_dbg(ice->card->dev, "invalid negative ptr\n"); return 0; } ptr -= substream->runtime->dma_addr; ptr = bytes_to_frames(substream->runtime, ptr); if (ptr >= substream->runtime->buffer_size) { - snd_printd("ice1724: invalid ptr %d (size=%d)\n", + dev_dbg(ice->card->dev, "invalid ptr %d (size=%d)\n", (int)ptr, (int)substream->runtime->period_size); return 0; } @@ -840,7 +840,7 @@ static snd_pcm_uframes_t snd_vt1724_playback_pro_pointer(struct snd_pcm_substrea else if (ptr <= substream->runtime->buffer_size) ptr = substream->runtime->buffer_size - ptr; else { - snd_printd("ice1724: invalid ptr %d (size=%d)\n", + dev_dbg(ice->card->dev, "invalid ptr %d (size=%d)\n", (int)ptr, (int)substream->runtime->buffer_size); ptr = 0; } @@ -884,7 +884,7 @@ static snd_pcm_uframes_t snd_vt1724_pcm_pointer(struct snd_pcm_substream *substr else if (ptr <= substream->runtime->buffer_size) ptr = substream->runtime->buffer_size - ptr; else { - snd_printd("ice1724: invalid ptr %d (size=%d)\n", + dev_dbg(ice->card->dev, "invalid ptr %d (size=%d)\n", (int)ptr, (int)substream->runtime->buffer_size); ptr = 0; } @@ -1508,7 +1508,8 @@ static int snd_vt1724_ac97_mixer(struct snd_ice1712 *ice) ac97.private_data = ice; err = snd_ac97_mixer(pbus, &ac97, &ice->ac97); if (err < 0) - printk(KERN_WARNING "ice1712: cannot initialize pro ac97, skipped\n"); + dev_warn(ice->card->dev, + "cannot initialize pro ac97, skipped\n"); else return 0; } @@ -2271,7 +2272,7 @@ static void wait_i2c_busy(struct snd_ice1712 *ice) while ((inb(ICEREG1724(ice, I2C_CTRL)) & VT1724_I2C_BUSY) && t--) ; if (t == -1) - printk(KERN_ERR "ice1724: i2c busy timeout\n"); + dev_err(ice->card->dev, "i2c busy timeout\n"); } unsigned char snd_vt1724_read_i2c(struct snd_ice1712 *ice, @@ -2287,7 +2288,7 @@ unsigned char snd_vt1724_read_i2c(struct snd_ice1712 *ice, val = inb(ICEREG1724(ice, I2C_DATA)); mutex_unlock(&ice->i2c_mutex); /* - printk(KERN_DEBUG "i2c_read: [0x%x,0x%x] = 0x%x\n", dev, addr, val); + dev_dbg(ice->card->dev, "i2c_read: [0x%x,0x%x] = 0x%x\n", dev, addr, val); */ return val; } @@ -2298,7 +2299,7 @@ void snd_vt1724_write_i2c(struct snd_ice1712 *ice, mutex_lock(&ice->i2c_mutex); wait_i2c_busy(ice); /* - printk(KERN_DEBUG "i2c_write: [0x%x,0x%x] = 0x%x\n", dev, addr, data); + dev_dbg(ice->card->dev, "i2c_write: [0x%x,0x%x] = 0x%x\n", dev, addr, data); */ outb(addr, ICEREG1724(ice, I2C_BYTE_ADDR)); outb(data, ICEREG1724(ice, I2C_DATA)); @@ -2335,7 +2336,8 @@ static int snd_vt1724_read_eeprom(struct snd_ice1712 *ice, ((unsigned int)swab16(vendor) << 16) | swab16(device); if (ice->eeprom.subvendor == 0 || ice->eeprom.subvendor == (unsigned int)-1) { - printk(KERN_ERR "ice1724: No valid ID is found\n"); + dev_err(ice->card->dev, + "No valid ID is found\n"); return -ENXIO; } } @@ -2344,7 +2346,8 @@ static int snd_vt1724_read_eeprom(struct snd_ice1712 *ice, for (c = *tbl; c->name; c++) { if (modelname && c->model && !strcmp(modelname, c->model)) { - printk(KERN_INFO "ice1724: Using board model %s\n", + dev_info(ice->card->dev, + "Using board model %s\n", c->name); ice->eeprom.subvendor = c->subvendor; } else if (c->subvendor != ice->eeprom.subvendor) @@ -2353,14 +2356,14 @@ static int snd_vt1724_read_eeprom(struct snd_ice1712 *ice, if (!c->eeprom_size || !c->eeprom_data) goto found; /* if the EEPROM is given by the driver, use it */ - snd_printdd("using the defined eeprom..\n"); + dev_dbg(ice->card->dev, "using the defined eeprom..\n"); ice->eeprom.version = 2; ice->eeprom.size = c->eeprom_size + 6; memcpy(ice->eeprom.data, c->eeprom_data, c->eeprom_size); goto read_skipped; } } - printk(KERN_WARNING "ice1724: No matching model found for ID 0x%x\n", + dev_warn(ice->card->dev, "No matching model found for ID 0x%x\n", ice->eeprom.subvendor); #ifdef CONFIG_PM_SLEEP /* assume AC97-only card which can suspend without additional code */ @@ -2372,13 +2375,13 @@ static int snd_vt1724_read_eeprom(struct snd_ice1712 *ice, if (ice->eeprom.size < 6) ice->eeprom.size = 32; else if (ice->eeprom.size > 32) { - printk(KERN_ERR "ice1724: Invalid EEPROM (size = %i)\n", + dev_err(ice->card->dev, "Invalid EEPROM (size = %i)\n", ice->eeprom.size); return -EIO; } ice->eeprom.version = snd_vt1724_read_i2c(ice, dev, 0x05); if (ice->eeprom.version != 1 && ice->eeprom.version != 2) - printk(KERN_WARNING "ice1724: Invalid EEPROM version %i\n", + dev_warn(ice->card->dev, "Invalid EEPROM version %i\n", ice->eeprom.version); size = ice->eeprom.size - 6; for (i = 0; i < size; i++) @@ -2586,7 +2589,7 @@ static int snd_vt1724_create(struct snd_card *card, if (request_irq(pci->irq, snd_vt1724_interrupt, IRQF_SHARED, KBUILD_MODNAME, ice)) { - snd_printk(KERN_ERR "unable to grab IRQ %d\n", pci->irq); + dev_err(card->dev, "unable to grab IRQ %d\n", pci->irq); snd_vt1724_free(ice); return -EIO; } @@ -2609,8 +2612,6 @@ static int snd_vt1724_create(struct snd_card *card, return err; } - snd_card_set_dev(card, &pci->dev); - *r_ice1712 = ice; return 0; } @@ -2638,7 +2639,8 @@ static int snd_vt1724_probe(struct pci_dev *pci, return -ENOENT; } - err = snd_card_create(index[dev], id[dev], THIS_MODULE, 0, &card); + err = snd_card_new(&pci->dev, index[dev], id[dev], THIS_MODULE, + 0, &card); if (err < 0) return err; diff --git a/sound/pci/ice1712/juli.c b/sound/pci/ice1712/juli.c index 8855933e710..7a6c0786c55 100644 --- a/sound/pci/ice1712/juli.c +++ b/sound/pci/ice1712/juli.c @@ -244,7 +244,7 @@ static void juli_akm_set_rate_val(struct snd_akm4xxx *ak, unsigned int rate) /* AK5385 first, since it requires cold reset affecting both codecs */ old_gpio = ice->gpio.get_data(ice); new_gpio = (old_gpio & ~GPIO_AK5385A_MASK) | ak5385_pins; - /* printk(KERN_DEBUG "JULI - ak5385 set_rate_val: new gpio 0x%x\n", + /* dev_dbg(ice->card->dev, "JULI - ak5385 set_rate_val: new gpio 0x%x\n", new_gpio); */ ice->gpio.set_data(ice, new_gpio); @@ -344,7 +344,7 @@ static int juli_mute_put(struct snd_kcontrol *kcontrol, new_gpio = old_gpio & ~((unsigned int) kcontrol->private_value); } - /* printk(KERN_DEBUG + /* dev_dbg(ice->card->dev, "JULI - mute/unmute: control_value: 0x%x, old_gpio: 0x%x, " "new_gpio 0x%x\n", (unsigned int)ucontrol->value.integer.value[0], old_gpio, @@ -439,9 +439,9 @@ static void add_slaves(struct snd_card *card, { for (; *list; list++) { struct snd_kcontrol *slave = ctl_find(card, *list); - /* printk(KERN_DEBUG "add_slaves - %s\n", *list); */ + /* dev_dbg(card->dev, "add_slaves - %s\n", *list); */ if (slave) { - /* printk(KERN_DEBUG "slave %s found\n", *list); */ + /* dev_dbg(card->dev, "slave %s found\n", *list); */ snd_ctl_add_slave(master, slave); } } @@ -536,7 +536,7 @@ static void juli_set_rate(struct snd_ice1712 *ice, unsigned int rate) old = ice->gpio.get_data(ice); new = (old & ~GPIO_RATE_MASK) | get_gpio_val(rate); - /* printk(KERN_DEBUG "JULI - set_rate: old %x, new %x\n", + /* dev_dbg(ice->card->dev, "JULI - set_rate: old %x, new %x\n", old & GPIO_RATE_MASK, new & GPIO_RATE_MASK); */ @@ -573,7 +573,7 @@ static void juli_ak4114_change(struct ak4114 *ak4114, unsigned char c0, if (ice->is_spdif_master(ice) && c1) { /* only for SPDIF master mode, rate was changed */ rate = snd_ak4114_external_rate(ak4114); - /* printk(KERN_DEBUG "ak4114 - input rate changed to %d\n", + /* dev_dbg(ice->card->dev, "ak4114 - input rate changed to %d\n", rate); */ juli_akm_set_rate_val(ice->akm, rate); } @@ -628,7 +628,7 @@ static int juli_init(struct snd_ice1712 *ice) #endif if (spec->analog) { - printk(KERN_INFO "juli@: analog I/O detected\n"); + dev_info(ice->card->dev, "juli@: analog I/O detected\n"); ice->num_total_dacs = 2; ice->num_total_adcs = 2; diff --git a/sound/pci/ice1712/prodigy192.c b/sound/pci/ice1712/prodigy192.c index e610339f760..f3b491aa3e2 100644 --- a/sound/pci/ice1712/prodigy192.c +++ b/sound/pci/ice1712/prodigy192.c @@ -98,7 +98,7 @@ static int stac9460_dac_mute(struct snd_ice1712 *ice, int idx, new = (~mute << 7 & 0x80) | (old & ~0x80); change = (new != old); if (change) - /*printk ("Volume register 0x%02x: 0x%02x\n", idx, new);*/ + /* dev_dbg(ice->card->dev, "Volume register 0x%02x: 0x%02x\n", idx, new);*/ stac9460_put(ice, idx, new); return change; } @@ -133,7 +133,7 @@ static int stac9460_dac_mute_put(struct snd_kcontrol *kcontrol, struct snd_ctl_e /* due to possible conflicts with stac9460_set_rate_val, mutexing */ mutex_lock(&spec->mute_mutex); /* - printk(KERN_DEBUG "Mute put: reg 0x%02x, ctrl value: 0x%02x\n", idx, + dev_dbg(ice->card->dev, "Mute put: reg 0x%02x, ctrl value: 0x%02x\n", idx, ucontrol->value.integer.value[0]); */ change = stac9460_dac_mute(ice, idx, ucontrol->value.integer.value[0]); @@ -187,7 +187,7 @@ static int stac9460_dac_vol_put(struct snd_kcontrol *kcontrol, struct snd_ctl_el if (change) { ovol = (0x7f - nvol) | (tmp & 0x80); /* - printk(KERN_DEBUG "DAC Volume: reg 0x%02x: 0x%02x\n", + dev_dbg(ice->card->dev, "DAC Volume: reg 0x%02x: 0x%02x\n", idx, ovol); */ stac9460_put(ice, idx, (0x7f - nvol) | (tmp & 0x80)); @@ -348,7 +348,7 @@ static void stac9460_set_rate_val(struct snd_ice1712 *ice, unsigned int rate) for (idx = 0; idx < 7 ; ++idx) changed[idx] = stac9460_dac_mute(ice, STAC946X_MASTER_VOLUME + idx, 0); - /*printk(KERN_DEBUG "Rate change: %d, new MC: 0x%02x\n", rate, new);*/ + /*dev_dbg(ice->card->dev, "Rate change: %d, new MC: 0x%02x\n", rate, new);*/ stac9460_put(ice, STAC946X_MASTER_CLOCKING, new); udelay(10); /* unmuting - only originally unmuted dacs - @@ -768,9 +768,10 @@ static int prodigy192_init(struct snd_ice1712 *ice) /* from this moment if err = 0 then * spec->ak4114 should not be null */ - snd_printdd("AK4114 initialized with status %d\n", err); + dev_dbg(ice->card->dev, + "AK4114 initialized with status %d\n", err); } else - snd_printdd("AK4114 not found\n"); + dev_dbg(ice->card->dev, "AK4114 not found\n"); if (err < 0) return err; diff --git a/sound/pci/ice1712/quartet.c b/sound/pci/ice1712/quartet.c index 71c6003ef33..2c2df4b74e0 100644 --- a/sound/pci/ice1712/quartet.c +++ b/sound/pci/ice1712/quartet.c @@ -280,7 +280,7 @@ static void qtet_akm_write(struct snd_akm4xxx *ak, int chip, if (snd_BUG_ON(chip < 0 || chip >= 4)) return; - /*printk(KERN_DEBUG "Writing to AK4620: chip=%d, addr=0x%x, + /*dev_dbg(ice->card->dev, "Writing to AK4620: chip=%d, addr=0x%x, data=0x%x\n", chip, addr, data);*/ orig_dir = ice->gpio.get_dir(ice); ice->gpio.set_dir(ice, orig_dir | GPIO_SPI_ALL); @@ -898,7 +898,7 @@ static void qtet_set_rate(struct snd_ice1712 *ice, unsigned int rate) new = (get_cpld(ice) & ~CPLD_CKS_MASK) | get_cks_val(rate); /* switch to internal clock, drop CPLD_SYNC_SEL */ new &= ~CPLD_SYNC_SEL; - /* printk(KERN_DEBUG "QT - set_rate: old %x, new %x\n", + /* dev_dbg(ice->card->dev, "QT - set_rate: old %x, new %x\n", get_cpld(ice), new); */ set_cpld(ice, new); } @@ -978,7 +978,7 @@ static void qtet_ak4113_change(struct ak4113 *ak4113, unsigned char c0, c1) { /* only for SPDIF master mode, rate was changed */ rate = snd_ak4113_external_rate(ak4113); - /* printk(KERN_DEBUG "ak4113 - input rate changed to %d\n", + /* dev_dbg(ice->card->dev, "ak4113 - input rate changed to %d\n", rate); */ qtet_akm_set_rate_val(ice->akm, rate); } diff --git a/sound/pci/intel8x0.c b/sound/pci/intel8x0.c index 08d8733604a..68340d7df76 100644 --- a/sound/pci/intel8x0.c +++ b/sound/pci/intel8x0.c @@ -547,7 +547,8 @@ static int snd_intel8x0_codec_semaphore(struct intel8x0 *chip, unsigned int code /* access to some forbidden (non existent) ac97 registers will not * reset the semaphore. So even if you don't get the semaphore, still * continue the access. We don't need the semaphore anyway. */ - snd_printk(KERN_ERR "codec_semaphore: semaphore is not ready [0x%x][0x%x]\n", + dev_err(chip->card->dev, + "codec_semaphore: semaphore is not ready [0x%x][0x%x]\n", igetbyte(chip, ICHREG(ACC_SEMA)), igetdword(chip, ICHREG(GLOB_STA))); iagetword(chip, 0); /* clear semaphore flag */ /* I don't care about the semaphore */ @@ -562,7 +563,9 @@ static void snd_intel8x0_codec_write(struct snd_ac97 *ac97, if (snd_intel8x0_codec_semaphore(chip, ac97->num) < 0) { if (! chip->in_ac97_init) - snd_printk(KERN_ERR "codec_write %d: semaphore is not ready for register 0x%x\n", ac97->num, reg); + dev_err(chip->card->dev, + "codec_write %d: semaphore is not ready for register 0x%x\n", + ac97->num, reg); } iaputword(chip, reg + ac97->num * 0x80, val); } @@ -576,7 +579,9 @@ static unsigned short snd_intel8x0_codec_read(struct snd_ac97 *ac97, if (snd_intel8x0_codec_semaphore(chip, ac97->num) < 0) { if (! chip->in_ac97_init) - snd_printk(KERN_ERR "codec_read %d: semaphore is not ready for register 0x%x\n", ac97->num, reg); + dev_err(chip->card->dev, + "codec_read %d: semaphore is not ready for register 0x%x\n", + ac97->num, reg); res = 0xffff; } else { res = iagetword(chip, reg + ac97->num * 0x80); @@ -585,7 +590,9 @@ static unsigned short snd_intel8x0_codec_read(struct snd_ac97 *ac97, iputdword(chip, ICHREG(GLOB_STA), tmp & ~(chip->codec_ready_bits | ICH_GSCI)); if (! chip->in_ac97_init) - snd_printk(KERN_ERR "codec_read %d: read timeout for register 0x%x\n", ac97->num, reg); + dev_err(chip->card->dev, + "codec_read %d: read timeout for register 0x%x\n", + ac97->num, reg); res = 0xffff; } } @@ -619,7 +626,7 @@ static int snd_intel8x0_ali_codec_ready(struct intel8x0 *chip, int mask) return 0; } if (! chip->in_ac97_init) - snd_printd(KERN_WARNING "intel8x0: AC97 codec ready timeout.\n"); + dev_warn(chip->card->dev, "AC97 codec ready timeout.\n"); return -EBUSY; } @@ -631,7 +638,7 @@ static int snd_intel8x0_ali_codec_semaphore(struct intel8x0 *chip) while (--time && (igetdword(chip, ICHREG(ALI_CAS)) & ALI_CAS_SEM_BUSY)) udelay(1); if (! time && ! chip->in_ac97_init) - snd_printk(KERN_WARNING "ali_codec_semaphore timeout\n"); + dev_warn(chip->card->dev, "ali_codec_semaphore timeout\n"); return snd_intel8x0_ali_codec_ready(chip, ALI_CSPSR_CODEC_READY); } @@ -700,7 +707,7 @@ static void snd_intel8x0_setup_periods(struct intel8x0 *chip, struct ichdev *ich bdbar[idx + 1] = cpu_to_le32(0x80000000 | /* interrupt on completion */ ichdev->fragsize >> ichdev->pos_shift); #if 0 - printk(KERN_DEBUG "bdbar[%i] = 0x%x [0x%x]\n", + dev_dbg(chip->card->dev, "bdbar[%i] = 0x%x [0x%x]\n", idx + 0, bdbar[idx + 0], bdbar[idx + 1]); #endif } @@ -712,8 +719,8 @@ static void snd_intel8x0_setup_periods(struct intel8x0 *chip, struct ichdev *ich ichdev->lvi_frag = ICH_REG_LVI_MASK % ichdev->frags; ichdev->position = 0; #if 0 - printk(KERN_DEBUG "lvi_frag = %i, frags = %i, period_size = 0x%x, " - "period_size1 = 0x%x\n", + dev_dbg(chip->card->dev, + "lvi_frag = %i, frags = %i, period_size = 0x%x, period_size1 = 0x%x\n", ichdev->lvi_frag, ichdev->frags, ichdev->fragsize, ichdev->fragsize1); #endif @@ -781,8 +788,8 @@ static inline void snd_intel8x0_update(struct intel8x0 *chip, struct ichdev *ich ichdev->lvi_frag %= ichdev->frags; ichdev->bdbar[ichdev->lvi * 2] = cpu_to_le32(ichdev->physbuf + ichdev->lvi_frag * ichdev->fragsize1); #if 0 - printk(KERN_DEBUG "new: bdbar[%i] = 0x%x [0x%x], prefetch = %i, " - "all = 0x%x, 0x%x\n", + dev_dbg(chip->card->dev, + "new: bdbar[%i] = 0x%x [0x%x], prefetch = %i, all = 0x%x, 0x%x\n", ichdev->lvi * 2, ichdev->bdbar[ichdev->lvi * 2], ichdev->bdbar[ichdev->lvi * 2 + 1], inb(ICH_REG_OFF_PIV + port), inl(port + 4), inb(port + ICH_REG_OFF_CR)); @@ -2289,7 +2296,8 @@ static int snd_intel8x0_mixer(struct intel8x0 *chip, int ac97_clock, ac97.num = i; if ((err = snd_ac97_mixer(pbus, &ac97, &chip->ac97[i])) < 0) { if (err != -EACCES) - snd_printk(KERN_ERR "Unable to initialize codec #%d\n", i); + dev_err(chip->card->dev, + "Unable to initialize codec #%d\n", i); if (i == 0) goto __err; } @@ -2441,7 +2449,7 @@ static int snd_intel8x0_ich_chip_reset(struct intel8x0 *chip) return 0; schedule_timeout_uninterruptible(1); } while (time_after_eq(end_time, jiffies)); - snd_printk(KERN_ERR "AC'97 warm reset still in progress? [0x%x]\n", + dev_err(chip->card->dev, "AC'97 warm reset still in progress? [0x%x]\n", igetdword(chip, ICHREG(GLOB_CNT))); return -EIO; } @@ -2483,7 +2491,8 @@ static int snd_intel8x0_ich_chip_init(struct intel8x0 *chip, int probing) } while (time_after_eq(end_time, jiffies)); if (! status) { /* no codec is found */ - snd_printk(KERN_ERR "codec_ready: codec is not ready [0x%x]\n", + dev_err(chip->card->dev, + "codec_ready: codec is not ready [0x%x]\n", igetdword(chip, ICHREG(GLOB_STA))); return -EIO; } @@ -2547,7 +2556,7 @@ static int snd_intel8x0_ali_chip_init(struct intel8x0 *chip, int probing) goto __ok; schedule_timeout_uninterruptible(1); } - snd_printk(KERN_ERR "AC'97 reset failed.\n"); + dev_err(chip->card->dev, "AC'97 reset failed.\n"); if (probing) return -EIO; @@ -2591,7 +2600,7 @@ static int snd_intel8x0_chip_init(struct intel8x0 *chip, int probing) break; } if (timeout == 0) - printk(KERN_ERR "intel8x0: reset of registers failed?\n"); + dev_err(chip->card->dev, "reset of registers failed?\n"); } /* initialize Buffer Descriptor Lists */ for (i = 0; i < chip->bdbars_count; i++) @@ -2692,8 +2701,7 @@ static int intel8x0_resume(struct device *dev) pci_set_power_state(pci, PCI_D0); pci_restore_state(pci); if (pci_enable_device(pci) < 0) { - printk(KERN_ERR "intel8x0: pci_enable_device failed, " - "disabling device\n"); + dev_err(dev, "pci_enable_device failed, disabling device\n"); snd_card_disconnect(card); return -EIO; } @@ -2701,8 +2709,8 @@ static int intel8x0_resume(struct device *dev) snd_intel8x0_chip_init(chip, 0); if (request_irq(pci->irq, snd_intel8x0_interrupt, IRQF_SHARED, KBUILD_MODNAME, chip)) { - printk(KERN_ERR "intel8x0: unable to grab IRQ %d, " - "disabling device\n", pci->irq); + dev_err(dev, "unable to grab IRQ %d, disabling device\n", + pci->irq); snd_card_disconnect(card); return -EIO; } @@ -2779,7 +2787,8 @@ static void intel8x0_measure_ac97_clock(struct intel8x0 *chip) __again: subs = chip->pcm[0]->streams[0].substream; if (! subs || subs->dma_buffer.bytes < INTEL8X0_TESTBUF_SIZE) { - snd_printk(KERN_WARNING "no playback buffer allocated - aborting measure ac97 clock\n"); + dev_warn(chip->card->dev, + "no playback buffer allocated - aborting measure ac97 clock\n"); return; } ichdev = &chip->ichd[ICHD_PCMOUT]; @@ -2789,7 +2798,8 @@ static void intel8x0_measure_ac97_clock(struct intel8x0 *chip) /* set rate */ if (snd_ac97_set_rate(chip->ac97[0], AC97_PCM_FRONT_DAC_RATE, 48000) < 0) { - snd_printk(KERN_ERR "cannot set ac97 rate: clock = %d\n", chip->ac97_bus->clock); + dev_err(chip->card->dev, "cannot set ac97 rate: clock = %d\n", + chip->ac97_bus->clock); return; } snd_intel8x0_setup_periods(chip, ichdev); @@ -2843,7 +2853,8 @@ static void intel8x0_measure_ac97_clock(struct intel8x0 *chip) spin_unlock_irq(&chip->reg_lock); if (pos == 0) { - snd_printk(KERN_ERR "intel8x0: measure - unreliable DMA position..\n"); + dev_err(chip->card->dev, + "measure - unreliable DMA position..\n"); __retry: if (attempt < 3) { msleep(300); @@ -2857,16 +2868,17 @@ static void intel8x0_measure_ac97_clock(struct intel8x0 *chip) t = stop_time.tv_sec - start_time.tv_sec; t *= 1000000; t += (stop_time.tv_nsec - start_time.tv_nsec) / 1000; - printk(KERN_INFO "%s: measured %lu usecs (%lu samples)\n", __func__, t, pos); + dev_info(chip->card->dev, + "%s: measured %lu usecs (%lu samples)\n", __func__, t, pos); if (t == 0) { - snd_printk(KERN_ERR "intel8x0: ?? calculation error..\n"); + dev_err(chip->card->dev, "?? calculation error..\n"); goto __retry; } pos *= 1000; pos = (pos / t) * 1000 + ((pos % t) * 1000) / t; if (pos < 40000 || pos >= 60000) { /* abnormal value. hw problem? */ - printk(KERN_INFO "intel8x0: measured clock %ld rejected\n", pos); + dev_info(chip->card->dev, "measured clock %ld rejected\n", pos); goto __retry; } else if (pos > 40500 && pos < 41500) /* first exception - 41000Hz reference clock */ @@ -2878,7 +2890,7 @@ static void intel8x0_measure_ac97_clock(struct intel8x0 *chip) /* not 48000Hz, tuning the clock.. */ chip->ac97_bus->clock = (chip->ac97_bus->clock * 48000) / pos; __end: - printk(KERN_INFO "intel8x0: clocking to %d\n", chip->ac97_bus->clock); + dev_info(chip->card->dev, "clocking to %d\n", chip->ac97_bus->clock); snd_ac97_update_power(chip->ac97[0], AC97_PCM_FRONT_DAC_RATE, 0); } @@ -2899,7 +2911,7 @@ static int intel8x0_in_clock_list(struct intel8x0 *chip) wl = snd_pci_quirk_lookup(pci, intel8x0_clock_list); if (!wl) return 0; - printk(KERN_INFO "intel8x0: white list rate for %04x:%04x is %i\n", + dev_info(chip->card->dev, "white list rate for %04x:%04x is %i\n", pci->subsystem_vendor, pci->subsystem_device, wl->value); chip->ac97_bus->clock = wl->value; return 1; @@ -3003,7 +3015,7 @@ static int snd_intel8x0_inside_vm(struct pci_dev *pci) fini: if (msg != NULL) - printk(KERN_INFO "intel8x0: %s optimization\n", msg); + dev_info(&pci->dev, "%s optimization\n", msg); return result; } @@ -3098,7 +3110,7 @@ static int snd_intel8x0_create(struct snd_card *card, else chip->addr = pci_iomap(pci, 0, 0); if (!chip->addr) { - snd_printk(KERN_ERR "AC'97 space ioremap problem\n"); + dev_err(card->dev, "AC'97 space ioremap problem\n"); snd_intel8x0_free(chip); return -EIO; } @@ -3107,7 +3119,7 @@ static int snd_intel8x0_create(struct snd_card *card, else chip->bmaddr = pci_iomap(pci, 1, 0); if (!chip->bmaddr) { - snd_printk(KERN_ERR "Controller space ioremap problem\n"); + dev_err(card->dev, "Controller space ioremap problem\n"); snd_intel8x0_free(chip); return -EIO; } @@ -3152,7 +3164,7 @@ static int snd_intel8x0_create(struct snd_card *card, chip->bdbars_count * sizeof(u32) * ICH_MAX_FRAGS * 2, &chip->bdbars) < 0) { snd_intel8x0_free(chip); - snd_printk(KERN_ERR "intel8x0: cannot allocate buffer descriptors\n"); + dev_err(card->dev, "cannot allocate buffer descriptors\n"); return -ENOMEM; } /* tables must be aligned to 8 bytes here, but the kernel pages @@ -3206,7 +3218,7 @@ static int snd_intel8x0_create(struct snd_card *card, /* request irq after initializaing int_sta_mask, etc */ if (request_irq(pci->irq, snd_intel8x0_interrupt, IRQF_SHARED, KBUILD_MODNAME, chip)) { - snd_printk(KERN_ERR "unable to grab IRQ %d\n", pci->irq); + dev_err(card->dev, "unable to grab IRQ %d\n", pci->irq); snd_intel8x0_free(chip); return -EBUSY; } @@ -3217,8 +3229,6 @@ static int snd_intel8x0_create(struct snd_card *card, return err; } - snd_card_set_dev(card, &pci->dev); - *r_intel8x0 = chip; return 0; } @@ -3265,12 +3275,12 @@ static int check_default_spdif_aclink(struct pci_dev *pci) w = snd_pci_quirk_lookup(pci, spdif_aclink_defaults); if (w) { if (w->value) - snd_printdd(KERN_INFO - "intel8x0: Using SPDIF over AC-Link for %s\n", + dev_dbg(&pci->dev, + "Using SPDIF over AC-Link for %s\n", snd_pci_quirk_name(w)); else - snd_printdd(KERN_INFO - "intel8x0: Using integrated SPDIF DMA for %s\n", + dev_dbg(&pci->dev, + "Using integrated SPDIF DMA for %s\n", snd_pci_quirk_name(w)); return w->value; } @@ -3285,7 +3295,7 @@ static int snd_intel8x0_probe(struct pci_dev *pci, int err; struct shortname_table *name; - err = snd_card_create(index, id, THIS_MODULE, 0, &card); + err = snd_card_new(&pci->dev, index, id, THIS_MODULE, 0, &card); if (err < 0) return err; diff --git a/sound/pci/intel8x0m.c b/sound/pci/intel8x0m.c index 3573c119366..b54d3e93cab 100644 --- a/sound/pci/intel8x0m.c +++ b/sound/pci/intel8x0m.c @@ -334,7 +334,8 @@ static int snd_intel8x0m_codec_semaphore(struct intel8x0m *chip, unsigned int co /* access to some forbidden (non existent) ac97 registers will not * reset the semaphore. So even if you don't get the semaphore, still * continue the access. We don't need the semaphore anyway. */ - snd_printk(KERN_ERR "codec_semaphore: semaphore is not ready [0x%x][0x%x]\n", + dev_err(chip->card->dev, + "codec_semaphore: semaphore is not ready [0x%x][0x%x]\n", igetbyte(chip, ICHREG(ACC_SEMA)), igetdword(chip, ICHREG(GLOB_STA))); iagetword(chip, 0); /* clear semaphore flag */ /* I don't care about the semaphore */ @@ -349,7 +350,9 @@ static void snd_intel8x0m_codec_write(struct snd_ac97 *ac97, if (snd_intel8x0m_codec_semaphore(chip, ac97->num) < 0) { if (! chip->in_ac97_init) - snd_printk(KERN_ERR "codec_write %d: semaphore is not ready for register 0x%x\n", ac97->num, reg); + dev_err(chip->card->dev, + "codec_write %d: semaphore is not ready for register 0x%x\n", + ac97->num, reg); } iaputword(chip, reg + ac97->num * 0x80, val); } @@ -363,7 +366,9 @@ static unsigned short snd_intel8x0m_codec_read(struct snd_ac97 *ac97, if (snd_intel8x0m_codec_semaphore(chip, ac97->num) < 0) { if (! chip->in_ac97_init) - snd_printk(KERN_ERR "codec_read %d: semaphore is not ready for register 0x%x\n", ac97->num, reg); + dev_err(chip->card->dev, + "codec_read %d: semaphore is not ready for register 0x%x\n", + ac97->num, reg); res = 0xffff; } else { res = iagetword(chip, reg + ac97->num * 0x80); @@ -372,7 +377,9 @@ static unsigned short snd_intel8x0m_codec_read(struct snd_ac97 *ac97, iputdword(chip, ICHREG(GLOB_STA), tmp & ~(ICH_SRI|ICH_PRI|ICH_TRI|ICH_GSCI)); if (! chip->in_ac97_init) - snd_printk(KERN_ERR "codec_read %d: read timeout for register 0x%x\n", ac97->num, reg); + dev_err(chip->card->dev, + "codec_read %d: read timeout for register 0x%x\n", + ac97->num, reg); res = 0xffff; } } @@ -412,7 +419,7 @@ static void snd_intel8x0m_setup_periods(struct intel8x0m *chip, struct ichdev *i bdbar[idx + 1] = cpu_to_le32(0x80000000 | /* interrupt on completion */ ichdev->fragsize >> chip->pcm_pos_shift); /* - printk(KERN_DEBUG "bdbar[%i] = 0x%x [0x%x]\n", + dev_dbg(chip->card->dev, "bdbar[%i] = 0x%x [0x%x]\n", idx + 0, bdbar[idx + 0], bdbar[idx + 1]); */ } @@ -424,8 +431,8 @@ static void snd_intel8x0m_setup_periods(struct intel8x0m *chip, struct ichdev *i ichdev->lvi_frag = ICH_REG_LVI_MASK % ichdev->frags; ichdev->position = 0; #if 0 - printk(KERN_DEBUG "lvi_frag = %i, frags = %i, period_size = 0x%x, " - "period_size1 = 0x%x\n", + dev_dbg(chip->card->dev, + "lvi_frag = %i, frags = %i, period_size = 0x%x, period_size1 = 0x%x\n", ichdev->lvi_frag, ichdev->frags, ichdev->fragsize, ichdev->fragsize1); #endif @@ -470,8 +477,8 @@ static inline void snd_intel8x0m_update(struct intel8x0m *chip, struct ichdev *i ichdev->lvi_frag * ichdev->fragsize1); #if 0 - printk(KERN_DEBUG "new: bdbar[%i] = 0x%x [0x%x], " - "prefetch = %i, all = 0x%x, 0x%x\n", + dev_dbg(chip->card->dev, + "new: bdbar[%i] = 0x%x [0x%x], prefetch = %i, all = 0x%x, 0x%x\n", ichdev->lvi * 2, ichdev->bdbar[ichdev->lvi * 2], ichdev->bdbar[ichdev->lvi * 2 + 1], inb(ICH_REG_OFF_PIV + port), inl(port + 4), inb(port + ICH_REG_OFF_CR)); @@ -850,7 +857,8 @@ static int snd_intel8x0m_mixer(struct intel8x0m *chip, int ac97_clock) ac97.pci = chip->pci; ac97.num = glob_sta & ICH_SCR ? 1 : 0; if ((err = snd_ac97_mixer(pbus, &ac97, &x97)) < 0) { - snd_printk(KERN_ERR "Unable to initialize codec #%d\n", ac97.num); + dev_err(chip->card->dev, + "Unable to initialize codec #%d\n", ac97.num); if (ac97.num == 0) goto __err; return err; @@ -901,7 +909,7 @@ static int snd_intel8x0m_ich_chip_init(struct intel8x0m *chip, int probing) goto __ok; schedule_timeout_uninterruptible(1); } while (time_after_eq(end_time, jiffies)); - snd_printk(KERN_ERR "AC'97 warm reset still in progress? [0x%x]\n", + dev_err(chip->card->dev, "AC'97 warm reset still in progress? [0x%x]\n", igetdword(chip, ICHREG(GLOB_CNT))); return -EIO; @@ -921,7 +929,8 @@ static int snd_intel8x0m_ich_chip_init(struct intel8x0m *chip, int probing) } while (time_after_eq(end_time, jiffies)); if (! status) { /* no codec is found */ - snd_printk(KERN_ERR "codec_ready: codec is not ready [0x%x]\n", + dev_err(chip->card->dev, + "codec_ready: codec is not ready [0x%x]\n", igetdword(chip, ICHREG(GLOB_STA))); return -EIO; } @@ -1042,16 +1051,15 @@ static int intel8x0m_resume(struct device *dev) pci_set_power_state(pci, PCI_D0); pci_restore_state(pci); if (pci_enable_device(pci) < 0) { - printk(KERN_ERR "intel8x0m: pci_enable_device failed, " - "disabling device\n"); + dev_err(dev, "pci_enable_device failed, disabling device\n"); snd_card_disconnect(card); return -EIO; } pci_set_master(pci); if (request_irq(pci->irq, snd_intel8x0m_interrupt, IRQF_SHARED, KBUILD_MODNAME, chip)) { - printk(KERN_ERR "intel8x0m: unable to grab IRQ %d, " - "disabling device\n", pci->irq); + dev_err(dev, "unable to grab IRQ %d, disabling device\n", + pci->irq); snd_card_disconnect(card); return -EIO; } @@ -1165,7 +1173,7 @@ static int snd_intel8x0m_create(struct snd_card *card, else chip->addr = pci_iomap(pci, 0, 0); if (!chip->addr) { - snd_printk(KERN_ERR "AC'97 space ioremap problem\n"); + dev_err(card->dev, "AC'97 space ioremap problem\n"); snd_intel8x0m_free(chip); return -EIO; } @@ -1174,7 +1182,7 @@ static int snd_intel8x0m_create(struct snd_card *card, else chip->bmaddr = pci_iomap(pci, 1, 0); if (!chip->bmaddr) { - snd_printk(KERN_ERR "Controller space ioremap problem\n"); + dev_err(card->dev, "Controller space ioremap problem\n"); snd_intel8x0m_free(chip); return -EIO; } @@ -1182,7 +1190,7 @@ static int snd_intel8x0m_create(struct snd_card *card, port_inited: if (request_irq(pci->irq, snd_intel8x0m_interrupt, IRQF_SHARED, KBUILD_MODNAME, chip)) { - snd_printk(KERN_ERR "unable to grab IRQ %d\n", pci->irq); + dev_err(card->dev, "unable to grab IRQ %d\n", pci->irq); snd_intel8x0m_free(chip); return -EBUSY; } @@ -1243,8 +1251,6 @@ static int snd_intel8x0m_create(struct snd_card *card, return err; } - snd_card_set_dev(card, &pci->dev); - *r_intel8x0m = chip; return 0; } @@ -1283,7 +1289,7 @@ static int snd_intel8x0m_probe(struct pci_dev *pci, int err; struct shortname_table *name; - err = snd_card_create(index, id, THIS_MODULE, 0, &card); + err = snd_card_new(&pci->dev, index, id, THIS_MODULE, 0, &card); if (err < 0) return err; diff --git a/sound/pci/korg1212/korg1212.c b/sound/pci/korg1212/korg1212.c index 9cf9829555d..8f36d77f01e 100644 --- a/sound/pci/korg1212/korg1212.c +++ b/sound/pci/korg1212/korg1212.c @@ -2418,8 +2418,6 @@ static int snd_korg1212_create(struct snd_card *card, struct pci_dev *pci, snd_korg1212_proc_init(korg1212); - snd_card_set_dev(card, &pci->dev); - * rchip = korg1212; return 0; @@ -2445,7 +2443,8 @@ snd_korg1212_probe(struct pci_dev *pci, dev++; return -ENOENT; } - err = snd_card_create(index[dev], id[dev], THIS_MODULE, 0, &card); + err = snd_card_new(&pci->dev, index[dev], id[dev], THIS_MODULE, + 0, &card); if (err < 0) return err; diff --git a/sound/pci/lola/lola.c b/sound/pci/lola/lola.c index 0568540dc8d..68824cdd137 100644 --- a/sound/pci/lola/lola.c +++ b/sound/pci/lola/lola.c @@ -75,7 +75,7 @@ MODULE_AUTHOR("Takashi Iwai <tiwai@suse.de>"); static int debug; module_param(debug, int, 0644); #define verbose_debug(fmt, args...) \ - do { if (debug > 1) printk(KERN_DEBUG SFX fmt, ##args); } while (0) + do { if (debug > 1) pr_debug(SFX fmt, ##args); } while (0) #else #define verbose_debug(fmt, args...) #endif @@ -168,7 +168,7 @@ static int rirb_get_response(struct lola *chip, unsigned int *val, verbose_debug("get_response: %x, %x\n", chip->res, chip->res_ex); if (chip->res_ex & LOLA_RIRB_EX_ERROR) { - printk(KERN_WARNING SFX "RIRB ERROR: " + dev_warn(chip->card->dev, "RIRB ERROR: " "NID=%x, verb=%x, data=%x, ext=%x\n", chip->last_cmd_nid, chip->last_verb, chip->last_data, @@ -182,9 +182,9 @@ static int rirb_get_response(struct lola *chip, unsigned int *val, udelay(20); cond_resched(); } - printk(KERN_WARNING SFX "RIRB response error\n"); + dev_warn(chip->card->dev, "RIRB response error\n"); if (!chip->polling_mode) { - printk(KERN_WARNING SFX "switching to polling mode\n"); + dev_warn(chip->card->dev, "switching to polling mode\n"); chip->polling_mode = 1; goto again; } @@ -327,7 +327,7 @@ static int reset_controller(struct lola *chip) break; } while (time_before(jiffies, end_time)); if (!gctl) { - printk(KERN_ERR SFX "cannot reset controller\n"); + dev_err(chip->card->dev, "cannot reset controller\n"); return -EIO; } return 0; @@ -452,40 +452,40 @@ static int lola_parse_tree(struct lola *chip) err = lola_read_param(chip, 0, LOLA_PAR_VENDOR_ID, &val); if (err < 0) { - printk(KERN_ERR SFX "Can't read VENDOR_ID\n"); + dev_err(chip->card->dev, "Can't read VENDOR_ID\n"); return err; } val >>= 16; if (val != 0x1369) { - printk(KERN_ERR SFX "Unknown codec vendor 0x%x\n", val); + dev_err(chip->card->dev, "Unknown codec vendor 0x%x\n", val); return -EINVAL; } err = lola_read_param(chip, 1, LOLA_PAR_FUNCTION_TYPE, &val); if (err < 0) { - printk(KERN_ERR SFX "Can't read FUNCTION_TYPE\n"); + dev_err(chip->card->dev, "Can't read FUNCTION_TYPE\n"); return err; } if (val != 1) { - printk(KERN_ERR SFX "Unknown function type %d\n", val); + dev_err(chip->card->dev, "Unknown function type %d\n", val); return -EINVAL; } err = lola_read_param(chip, 1, LOLA_PAR_SPECIFIC_CAPS, &val); if (err < 0) { - printk(KERN_ERR SFX "Can't read SPECCAPS\n"); + dev_err(chip->card->dev, "Can't read SPECCAPS\n"); return err; } chip->lola_caps = val; chip->pin[CAPT].num_pins = LOLA_AFG_INPUT_PIN_COUNT(chip->lola_caps); chip->pin[PLAY].num_pins = LOLA_AFG_OUTPUT_PIN_COUNT(chip->lola_caps); - snd_printdd(SFX "speccaps=0x%x, pins in=%d, out=%d\n", + dev_dbg(chip->card->dev, "speccaps=0x%x, pins in=%d, out=%d\n", chip->lola_caps, chip->pin[CAPT].num_pins, chip->pin[PLAY].num_pins); if (chip->pin[CAPT].num_pins > MAX_AUDIO_INOUT_COUNT || chip->pin[PLAY].num_pins > MAX_AUDIO_INOUT_COUNT) { - printk(KERN_ERR SFX "Invalid Lola-spec caps 0x%x\n", val); + dev_err(chip->card->dev, "Invalid Lola-spec caps 0x%x\n", val); return -EINVAL; } @@ -586,7 +586,6 @@ static int lola_create(struct snd_card *card, struct pci_dev *pci, chip = kzalloc(sizeof(*chip), GFP_KERNEL); if (!chip) { - snd_printk(KERN_ERR SFX "cannot allocate chip\n"); pci_disable_device(pci); return -ENOMEM; } @@ -609,7 +608,7 @@ static int lola_create(struct snd_card *card, struct pci_dev *pci, chip->sample_rate_max = 192000; break; default: - snd_printk(KERN_WARNING SFX + dev_warn(chip->card->dev, "Invalid granularity %d, reset to %d\n", chip->granularity, LOLA_GRANULARITY_MAX); chip->granularity = LOLA_GRANULARITY_MAX; @@ -618,7 +617,7 @@ static int lola_create(struct snd_card *card, struct pci_dev *pci, } chip->sample_rate_min = sample_rate_min[dev]; if (chip->sample_rate_min > chip->sample_rate_max) { - snd_printk(KERN_WARNING SFX + dev_warn(chip->card->dev, "Invalid sample_rate_min %d, reset to 16000\n", chip->sample_rate_min); chip->sample_rate_min = 16000; @@ -636,7 +635,7 @@ static int lola_create(struct snd_card *card, struct pci_dev *pci, chip->bar[1].addr = pci_resource_start(pci, 2); chip->bar[1].remap_addr = pci_ioremap_bar(pci, 2); if (!chip->bar[0].remap_addr || !chip->bar[1].remap_addr) { - snd_printk(KERN_ERR SFX "ioremap error\n"); + dev_err(chip->card->dev, "ioremap error\n"); err = -ENXIO; goto errout; } @@ -649,7 +648,7 @@ static int lola_create(struct snd_card *card, struct pci_dev *pci, if (request_irq(pci->irq, lola_interrupt, IRQF_SHARED, KBUILD_MODNAME, chip)) { - printk(KERN_ERR SFX "unable to grab IRQ %d\n", pci->irq); + dev_err(chip->card->dev, "unable to grab IRQ %d\n", pci->irq); err = -EBUSY; goto errout; } @@ -660,7 +659,7 @@ static int lola_create(struct snd_card *card, struct pci_dev *pci, chip->pcm[CAPT].num_streams = (dever >> 0) & 0x3ff; chip->pcm[PLAY].num_streams = (dever >> 10) & 0x3ff; chip->version = (dever >> 24) & 0xff; - snd_printdd(SFX "streams in=%d, out=%d, version=0x%x\n", + dev_dbg(chip->card->dev, "streams in=%d, out=%d, version=0x%x\n", chip->pcm[CAPT].num_streams, chip->pcm[PLAY].num_streams, chip->version); @@ -669,7 +668,7 @@ static int lola_create(struct snd_card *card, struct pci_dev *pci, chip->pcm[PLAY].num_streams > MAX_STREAM_OUT_COUNT || (!chip->pcm[CAPT].num_streams && !chip->pcm[PLAY].num_streams)) { - printk(KERN_ERR SFX "invalid DEVER = %x\n", dever); + dev_err(chip->card->dev, "invalid DEVER = %x\n", dever); err = -EINVAL; goto errout; } @@ -680,7 +679,7 @@ static int lola_create(struct snd_card *card, struct pci_dev *pci, err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops); if (err < 0) { - snd_printk(KERN_ERR SFX "Error creating device [card]!\n"); + dev_err(chip->card->dev, "Error creating device [card]!\n"); goto errout; } @@ -717,14 +716,13 @@ static int lola_probe(struct pci_dev *pci, return -ENOENT; } - err = snd_card_create(index[dev], id[dev], THIS_MODULE, 0, &card); + err = snd_card_new(&pci->dev, index[dev], id[dev], THIS_MODULE, + 0, &card); if (err < 0) { - snd_printk(KERN_ERR SFX "Error creating card!\n"); + dev_err(card->dev, "Error creating card!\n"); return err; } - snd_card_set_dev(card, &pci->dev); - err = lola_create(card, pci, dev, &chip); if (err < 0) goto out_free; diff --git a/sound/pci/lola/lola_clock.c b/sound/pci/lola/lola_clock.c index eb1d6b97df1..2bef6b412ae 100644 --- a/sound/pci/lola/lola_clock.c +++ b/sound/pci/lola/lola_clock.c @@ -128,21 +128,21 @@ int lola_init_clock_widget(struct lola *chip, int nid) err = lola_read_param(chip, nid, LOLA_PAR_AUDIO_WIDGET_CAP, &val); if (err < 0) { - printk(KERN_ERR SFX "Can't read wcaps for 0x%x\n", nid); + dev_err(chip->card->dev, "Can't read wcaps for 0x%x\n", nid); return err; } if ((val & 0xfff00000) != 0x01f00000) { /* test SubType and Type */ - snd_printdd("No valid clock widget\n"); + dev_dbg(chip->card->dev, "No valid clock widget\n"); return 0; } chip->clock.nid = nid; chip->clock.items = val & 0xff; - snd_printdd("clock_list nid=%x, entries=%d\n", nid, + dev_dbg(chip->card->dev, "clock_list nid=%x, entries=%d\n", nid, chip->clock.items); if (chip->clock.items > MAX_SAMPLE_CLOCK_COUNT) { - printk(KERN_ERR SFX "CLOCK_LIST too big: %d\n", + dev_err(chip->card->dev, "CLOCK_LIST too big: %d\n", chip->clock.items); return -EINVAL; } @@ -158,7 +158,7 @@ int lola_init_clock_widget(struct lola *chip, int nid) err = lola_codec_read(chip, nid, LOLA_VERB_GET_CLOCK_LIST, idx, 0, &val, &res_ex); if (err < 0) { - printk(KERN_ERR SFX "Can't read CLOCK_LIST\n"); + dev_err(chip->card->dev, "Can't read CLOCK_LIST\n"); return -EINVAL; } @@ -223,7 +223,7 @@ int lola_enable_clock_events(struct lola *chip) if (err < 0) return err; if (res) { - printk(KERN_WARNING SFX "error in enable_clock_events %d\n", + dev_warn(chip->card->dev, "error in enable_clock_events %d\n", res); return -EINVAL; } @@ -242,7 +242,7 @@ int lola_set_clock_index(struct lola *chip, unsigned int idx) if (err < 0) return err; if (res) { - printk(KERN_WARNING SFX "error in set_clock %d\n", res); + dev_warn(chip->card->dev, "error in set_clock %d\n", res); return -EINVAL; } return 0; diff --git a/sound/pci/lola/lola_mixer.c b/sound/pci/lola/lola_mixer.c index 52c8d6b0f39..782f4d8299a 100644 --- a/sound/pci/lola/lola_mixer.c +++ b/sound/pci/lola/lola_mixer.c @@ -37,7 +37,7 @@ static int lola_init_pin(struct lola *chip, struct lola_pin *pin, pin->nid = nid; err = lola_read_param(chip, nid, LOLA_PAR_AUDIO_WIDGET_CAP, &val); if (err < 0) { - printk(KERN_ERR SFX "Can't read wcaps for 0x%x\n", nid); + dev_err(chip->card->dev, "Can't read wcaps for 0x%x\n", nid); return err; } val &= 0x00f00fff; /* test TYPE and bits 0..11 */ @@ -48,7 +48,7 @@ static int lola_init_pin(struct lola *chip, struct lola_pin *pin, else if (val == 0x0040000c && dir == PLAY) /* Dig=0, OutAmp/ovrd */ pin->is_analog = true; else { - printk(KERN_ERR SFX "Invalid wcaps 0x%x for 0x%x\n", val, nid); + dev_err(chip->card->dev, "Invalid wcaps 0x%x for 0x%x\n", val, nid); return -EINVAL; } @@ -62,7 +62,7 @@ static int lola_init_pin(struct lola *chip, struct lola_pin *pin, else err = lola_read_param(chip, nid, LOLA_PAR_AMP_IN_CAP, &val); if (err < 0) { - printk(KERN_ERR SFX "Can't read AMP-caps for 0x%x\n", nid); + dev_err(chip->card->dev, "Can't read AMP-caps for 0x%x\n", nid); return err; } @@ -79,7 +79,7 @@ static int lola_init_pin(struct lola *chip, struct lola_pin *pin, err = lola_codec_read(chip, nid, LOLA_VERB_GET_MAX_LEVEL, 0, 0, &val, NULL); if (err < 0) { - printk(KERN_ERR SFX "Can't get MAX_LEVEL 0x%x\n", nid); + dev_err(chip->card->dev, "Can't get MAX_LEVEL 0x%x\n", nid); return err; } pin->max_level = val & 0x3ff; /* 10 bits */ @@ -119,12 +119,12 @@ int lola_init_mixer_widget(struct lola *chip, int nid) err = lola_read_param(chip, nid, LOLA_PAR_AUDIO_WIDGET_CAP, &val); if (err < 0) { - printk(KERN_ERR SFX "Can't read wcaps for 0x%x\n", nid); + dev_err(chip->card->dev, "Can't read wcaps for 0x%x\n", nid); return err; } if ((val & 0xfff00000) != 0x02f00000) { /* test SubType and Type */ - snd_printdd("No valid mixer widget\n"); + dev_dbg(chip->card->dev, "No valid mixer widget\n"); return 0; } @@ -202,7 +202,7 @@ int lola_init_mixer_widget(struct lola *chip, int nid) */ if (chip->mixer.src_stream_out_ofs > MAX_AUDIO_INOUT_COUNT || chip->mixer.dest_phys_out_ofs > MAX_STREAM_IN_COUNT) { - printk(KERN_ERR SFX "Invalid mixer widget size\n"); + dev_err(chip->card->dev, "Invalid mixer widget size\n"); return -EINVAL; } @@ -213,7 +213,7 @@ int lola_init_mixer_widget(struct lola *chip, int nid) (((1U << chip->mixer.dest_phys_outs) - 1) << chip->mixer.dest_phys_out_ofs); - snd_printdd("Mixer src_mask=%x, dest_mask=%x\n", + dev_dbg(chip->card->dev, "Mixer src_mask=%x, dest_mask=%x\n", chip->mixer.src_mask, chip->mixer.dest_mask); return 0; @@ -236,7 +236,8 @@ static int lola_mixer_set_src_gain(struct lola *chip, unsigned int id, (gain == readw(&chip->mixer.array->src_gain[id]))) return 0; - snd_printdd("lola_mixer_set_src_gain (id=%d, gain=%d) enable=%x\n", + dev_dbg(chip->card->dev, + "lola_mixer_set_src_gain (id=%d, gain=%d) enable=%x\n", id, gain, val); writew(gain, &chip->mixer.array->src_gain[id]); writel(val, &chip->mixer.array->src_gain_enable); @@ -409,7 +410,8 @@ static int set_analog_volume(struct lola *chip, int dir, return 0; if (external_call) lola_codec_flush(chip); - snd_printdd("set_analog_volume (dir=%d idx=%d, volume=%d)\n", + dev_dbg(chip->card->dev, + "set_analog_volume (dir=%d idx=%d, volume=%d)\n", dir, idx, val); err = lola_codec_write(chip, pin->nid, LOLA_VERB_SET_AMP_GAIN_MUTE, val, 0); diff --git a/sound/pci/lola/lola_pcm.c b/sound/pci/lola/lola_pcm.c index 5ea85e8b83a..3bd6985430e 100644 --- a/sound/pci/lola/lola_pcm.c +++ b/sound/pci/lola/lola_pcm.c @@ -103,7 +103,7 @@ static void wait_for_srst_clear(struct lola *chip, struct lola_stream *str) return; msleep(1); } - printk(KERN_WARNING SFX "SRST not clear (stream %d)\n", str->dsd); + dev_warn(chip->card->dev, "SRST not clear (stream %d)\n", str->dsd); } static int lola_stream_wait_for_fifo(struct lola *chip, @@ -118,7 +118,7 @@ static int lola_stream_wait_for_fifo(struct lola *chip, return 0; msleep(1); } - printk(KERN_WARNING SFX "FIFO not ready (stream %d)\n", str->dsd); + dev_warn(chip->card->dev, "FIFO not ready (stream %d)\n", str->dsd); return -EIO; } @@ -156,7 +156,7 @@ static int lola_sync_wait_for_fifo(struct lola *chip, return 0; msleep(1); } - printk(KERN_WARNING SFX "FIFO not ready (pending %d)\n", pending - 1); + dev_warn(chip->card->dev, "FIFO not ready (pending %d)\n", pending - 1); return -EIO; } @@ -373,7 +373,7 @@ static int lola_setup_periods(struct lola *chip, struct lola_pcm *pcm, return 0; error: - snd_printk(KERN_ERR SFX "Too many BDL entries: buffer=%d, period=%d\n", + dev_err(chip->card->dev, "Too many BDL entries: buffer=%d, period=%d\n", str->bufsize, period_bytes); return -EINVAL; } @@ -415,7 +415,7 @@ static int lola_set_stream_config(struct lola *chip, err = lola_codec_read(chip, str->nid, LOLA_VERB_SET_STREAM_FORMAT, str->format_verb, 0, &val, NULL); if (err < 0) { - printk(KERN_ERR SFX "Cannot set stream format 0x%x\n", + dev_err(chip->card->dev, "Cannot set stream format 0x%x\n", str->format_verb); return err; } @@ -427,7 +427,8 @@ static int lola_set_stream_config(struct lola *chip, LOLA_VERB_SET_CHANNEL_STREAMID, 0, verb, &val, NULL); if (err < 0) { - printk(KERN_ERR SFX "Cannot set stream channel %d\n", i); + dev_err(chip->card->dev, + "Cannot set stream channel %d\n", i); return err; } } @@ -651,13 +652,14 @@ static int lola_init_stream(struct lola *chip, struct lola_stream *str, str->dsd += MAX_STREAM_IN_COUNT; err = lola_read_param(chip, nid, LOLA_PAR_AUDIO_WIDGET_CAP, &val); if (err < 0) { - printk(KERN_ERR SFX "Can't read wcaps for 0x%x\n", nid); + dev_err(chip->card->dev, "Can't read wcaps for 0x%x\n", nid); return err; } if (dir == PLAY) { /* test TYPE and bits 0..11 (no test bit9 : Digital = 0/1) */ if ((val & 0x00f00dff) != 0x00000010) { - printk(KERN_ERR SFX "Invalid wcaps 0x%x for 0x%x\n", + dev_err(chip->card->dev, + "Invalid wcaps 0x%x for 0x%x\n", val, nid); return -EINVAL; } @@ -666,7 +668,8 @@ static int lola_init_stream(struct lola *chip, struct lola_stream *str, * (bug : ignore bit8: Conn list = 0/1) */ if ((val & 0x00f00cff) != 0x00100010) { - printk(KERN_ERR SFX "Invalid wcaps 0x%x for 0x%x\n", + dev_err(chip->card->dev, + "Invalid wcaps 0x%x for 0x%x\n", val, nid); return -EINVAL; } @@ -677,14 +680,15 @@ static int lola_init_stream(struct lola *chip, struct lola_stream *str, err = lola_read_param(chip, nid, LOLA_PAR_STREAM_FORMATS, &val); if (err < 0) { - printk(KERN_ERR SFX "Can't read FORMATS 0x%x\n", nid); + dev_err(chip->card->dev, "Can't read FORMATS 0x%x\n", nid); return err; } val &= 3; if (val == 3) str->can_float = true; if (!(val & 1)) { - printk(KERN_ERR SFX "Invalid formats 0x%x for 0x%x", val, nid); + dev_err(chip->card->dev, + "Invalid formats 0x%x for 0x%x", val, nid); return -EINVAL; } return 0; diff --git a/sound/pci/lx6464es/lx6464es.c b/sound/pci/lx6464es/lx6464es.c index 5fcaaa6da4a..27f60ce8a55 100644 --- a/sound/pci/lx6464es/lx6464es.c +++ b/sound/pci/lx6464es/lx6464es.c @@ -112,16 +112,16 @@ static int lx_hardware_open(struct lx6464es *chip, snd_pcm_uframes_t period_size = runtime->period_size; - snd_printd(LXP "allocating pipe for %d channels\n", channels); + dev_dbg(chip->card->dev, "allocating pipe for %d channels\n", channels); err = lx_pipe_allocate(chip, 0, is_capture, channels); if (err < 0) { - snd_printk(KERN_ERR LXP "allocating pipe failed\n"); + dev_err(chip->card->dev, LXP "allocating pipe failed\n"); return err; } err = lx_set_granularity(chip, period_size); if (err < 0) { - snd_printk(KERN_ERR LXP "setting granularity to %ld failed\n", + dev_err(chip->card->dev, "setting granularity to %ld failed\n", period_size); return err; } @@ -136,24 +136,24 @@ static int lx_hardware_start(struct lx6464es *chip, struct snd_pcm_runtime *runtime = substream->runtime; int is_capture = (substream->stream == SNDRV_PCM_STREAM_CAPTURE); - snd_printd(LXP "setting stream format\n"); + dev_dbg(chip->card->dev, "setting stream format\n"); err = lx_stream_set_format(chip, runtime, 0, is_capture); if (err < 0) { - snd_printk(KERN_ERR LXP "setting stream format failed\n"); + dev_err(chip->card->dev, "setting stream format failed\n"); return err; } - snd_printd(LXP "starting pipe\n"); + dev_dbg(chip->card->dev, "starting pipe\n"); err = lx_pipe_start(chip, 0, is_capture); if (err < 0) { - snd_printk(KERN_ERR LXP "starting pipe failed\n"); + dev_err(chip->card->dev, "starting pipe failed\n"); return err; } - snd_printd(LXP "waiting for pipe to start\n"); + dev_dbg(chip->card->dev, "waiting for pipe to start\n"); err = lx_pipe_wait_for_start(chip, 0, is_capture); if (err < 0) { - snd_printk(KERN_ERR LXP "waiting for pipe failed\n"); + dev_err(chip->card->dev, "waiting for pipe failed\n"); return err; } @@ -167,24 +167,24 @@ static int lx_hardware_stop(struct lx6464es *chip, int err = 0; int is_capture = (substream->stream == SNDRV_PCM_STREAM_CAPTURE); - snd_printd(LXP "pausing pipe\n"); + dev_dbg(chip->card->dev, "pausing pipe\n"); err = lx_pipe_pause(chip, 0, is_capture); if (err < 0) { - snd_printk(KERN_ERR LXP "pausing pipe failed\n"); + dev_err(chip->card->dev, "pausing pipe failed\n"); return err; } - snd_printd(LXP "waiting for pipe to become idle\n"); + dev_dbg(chip->card->dev, "waiting for pipe to become idle\n"); err = lx_pipe_wait_for_idle(chip, 0, is_capture); if (err < 0) { - snd_printk(KERN_ERR LXP "waiting for pipe failed\n"); + dev_err(chip->card->dev, "waiting for pipe failed\n"); return err; } - snd_printd(LXP "stopping pipe\n"); + dev_dbg(chip->card->dev, "stopping pipe\n"); err = lx_pipe_stop(chip, 0, is_capture); if (err < 0) { - snd_printk(LXP "stopping pipe failed\n"); + dev_err(chip->card->dev, "stopping pipe failed\n"); return err; } @@ -198,10 +198,10 @@ static int lx_hardware_close(struct lx6464es *chip, int err = 0; int is_capture = (substream->stream == SNDRV_PCM_STREAM_CAPTURE); - snd_printd(LXP "releasing pipe\n"); + dev_dbg(chip->card->dev, "releasing pipe\n"); err = lx_pipe_release(chip, 0, is_capture); if (err < 0) { - snd_printk(LXP "releasing pipe failed\n"); + dev_err(chip->card->dev, "releasing pipe failed\n"); return err; } @@ -216,7 +216,7 @@ static int lx_pcm_open(struct snd_pcm_substream *substream) int err = 0; int board_rate; - snd_printdd("->lx_pcm_open\n"); + dev_dbg(chip->card->dev, "->lx_pcm_open\n"); mutex_lock(&chip->setup_mutex); /* copy the struct snd_pcm_hardware struct */ @@ -227,7 +227,7 @@ static int lx_pcm_open(struct snd_pcm_substream *substream) err = snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS); if (err < 0) { - snd_printk(KERN_WARNING LXP "could not constrain periods\n"); + dev_warn(chip->card->dev, "could not constrain periods\n"); goto exit; } #endif @@ -238,7 +238,7 @@ static int lx_pcm_open(struct snd_pcm_substream *substream) board_rate, board_rate); if (err < 0) { - snd_printk(KERN_WARNING LXP "could not constrain periods\n"); + dev_warn(chip->card->dev, "could not constrain periods\n"); goto exit; } @@ -248,7 +248,7 @@ static int lx_pcm_open(struct snd_pcm_substream *substream) MICROBLAZE_IBL_MIN, MICROBLAZE_IBL_MAX); if (err < 0) { - snd_printk(KERN_WARNING LXP + dev_warn(chip->card->dev, "could not constrain period size\n"); goto exit; } @@ -263,14 +263,14 @@ exit: runtime->private_data = chip; mutex_unlock(&chip->setup_mutex); - snd_printdd("<-lx_pcm_open, %d\n", err); + dev_dbg(chip->card->dev, "<-lx_pcm_open, %d\n", err); return err; } static int lx_pcm_close(struct snd_pcm_substream *substream) { int err = 0; - snd_printdd("->lx_pcm_close\n"); + dev_dbg(substream->pcm->card->dev, "->lx_pcm_close\n"); return err; } @@ -285,13 +285,13 @@ static snd_pcm_uframes_t lx_pcm_stream_pointer(struct snd_pcm_substream struct lx_stream *lx_stream = is_capture ? &chip->capture_stream : &chip->playback_stream; - snd_printdd("->lx_pcm_stream_pointer\n"); + dev_dbg(chip->card->dev, "->lx_pcm_stream_pointer\n"); spin_lock_irqsave(&chip->lock, flags); pos = lx_stream->frame_pos * substream->runtime->period_size; spin_unlock_irqrestore(&chip->lock, flags); - snd_printdd(LXP "stream_pointer at %ld\n", pos); + dev_dbg(chip->card->dev, "stream_pointer at %ld\n", pos); return pos; } @@ -301,37 +301,37 @@ static int lx_pcm_prepare(struct snd_pcm_substream *substream) int err = 0; const int is_capture = (substream->stream == SNDRV_PCM_STREAM_CAPTURE); - snd_printdd("->lx_pcm_prepare\n"); + dev_dbg(chip->card->dev, "->lx_pcm_prepare\n"); mutex_lock(&chip->setup_mutex); if (chip->hardware_running[is_capture]) { err = lx_hardware_stop(chip, substream); if (err < 0) { - snd_printk(KERN_ERR LXP "failed to stop hardware. " + dev_err(chip->card->dev, "failed to stop hardware. " "Error code %d\n", err); goto exit; } err = lx_hardware_close(chip, substream); if (err < 0) { - snd_printk(KERN_ERR LXP "failed to close hardware. " + dev_err(chip->card->dev, "failed to close hardware. " "Error code %d\n", err); goto exit; } } - snd_printd(LXP "opening hardware\n"); + dev_dbg(chip->card->dev, "opening hardware\n"); err = lx_hardware_open(chip, substream); if (err < 0) { - snd_printk(KERN_ERR LXP "failed to open hardware. " + dev_err(chip->card->dev, "failed to open hardware. " "Error code %d\n", err); goto exit; } err = lx_hardware_start(chip, substream); if (err < 0) { - snd_printk(KERN_ERR LXP "failed to start hardware. " + dev_err(chip->card->dev, "failed to start hardware. " "Error code %d\n", err); goto exit; } @@ -354,7 +354,7 @@ static int lx_pcm_hw_params(struct snd_pcm_substream *substream, struct lx6464es *chip = snd_pcm_substream_chip(substream); int err = 0; - snd_printdd("->lx_pcm_hw_params\n"); + dev_dbg(chip->card->dev, "->lx_pcm_hw_params\n"); mutex_lock(&chip->setup_mutex); @@ -389,20 +389,20 @@ static int lx_pcm_hw_free(struct snd_pcm_substream *substream) int err = 0; int is_capture = (substream->stream == SNDRV_PCM_STREAM_CAPTURE); - snd_printdd("->lx_pcm_hw_free\n"); + dev_dbg(chip->card->dev, "->lx_pcm_hw_free\n"); mutex_lock(&chip->setup_mutex); if (chip->hardware_running[is_capture]) { err = lx_hardware_stop(chip, substream); if (err < 0) { - snd_printk(KERN_ERR LXP "failed to stop hardware. " + dev_err(chip->card->dev, "failed to stop hardware. " "Error code %d\n", err); goto exit; } err = lx_hardware_close(chip, substream); if (err < 0) { - snd_printk(KERN_ERR LXP "failed to close hardware. " + dev_err(chip->card->dev, "failed to close hardware. " "Error code %d\n", err); goto exit; } @@ -446,25 +446,25 @@ static void lx_trigger_start(struct lx6464es *chip, struct lx_stream *lx_stream) err = lx_buffer_ask(chip, 0, is_capture, &needed, &freed, size_array); - snd_printdd(LXP "starting: needed %d, freed %d\n", + dev_dbg(chip->card->dev, "starting: needed %d, freed %d\n", needed, freed); err = lx_buffer_give(chip, 0, is_capture, period_bytes, lower_32_bits(buf), upper_32_bits(buf), &buffer_index); - snd_printdd(LXP "starting: buffer index %x on 0x%lx (%d bytes)\n", + dev_dbg(chip->card->dev, "starting: buffer index %x on 0x%lx (%d bytes)\n", buffer_index, (unsigned long)buf, period_bytes); buf += period_bytes; } err = lx_buffer_ask(chip, 0, is_capture, &needed, &freed, size_array); - snd_printdd(LXP "starting: needed %d, freed %d\n", needed, freed); + dev_dbg(chip->card->dev, "starting: needed %d, freed %d\n", needed, freed); - snd_printd(LXP "starting: starting stream\n"); + dev_dbg(chip->card->dev, "starting: starting stream\n"); err = lx_stream_start(chip, 0, is_capture); if (err < 0) - snd_printk(KERN_ERR LXP "couldn't start stream\n"); + dev_err(chip->card->dev, "couldn't start stream\n"); else lx_stream->status = LX_STREAM_STATUS_RUNNING; @@ -476,10 +476,10 @@ static void lx_trigger_stop(struct lx6464es *chip, struct lx_stream *lx_stream) const unsigned int is_capture = lx_stream->is_capture; int err; - snd_printd(LXP "stopping: stopping stream\n"); + dev_dbg(chip->card->dev, "stopping: stopping stream\n"); err = lx_stream_stop(chip, 0, is_capture); if (err < 0) - snd_printk(KERN_ERR LXP "couldn't stop stream\n"); + dev_err(chip->card->dev, "couldn't stop stream\n"); else lx_stream->status = LX_STREAM_STATUS_FREE; @@ -507,7 +507,7 @@ static void lx_trigger_tasklet(unsigned long data) struct lx6464es *chip = (struct lx6464es *)data; unsigned long flags; - snd_printdd("->lx_trigger_tasklet\n"); + dev_dbg(chip->card->dev, "->lx_trigger_tasklet\n"); spin_lock_irqsave(&chip->lock, flags); lx_trigger_tasklet_dispatch_stream(chip, &chip->capture_stream); @@ -547,14 +547,14 @@ static int lx_pcm_trigger(struct snd_pcm_substream *substream, int cmd) struct lx_stream *stream = is_capture ? &chip->capture_stream : &chip->playback_stream; - snd_printdd("->lx_pcm_trigger\n"); + dev_dbg(chip->card->dev, "->lx_pcm_trigger\n"); return lx_pcm_trigger_dispatch(chip, stream, cmd); } static int snd_lx6464es_free(struct lx6464es *chip) { - snd_printdd("->snd_lx6464es_free\n"); + dev_dbg(chip->card->dev, "->snd_lx6464es_free\n"); lx_irq_disable(chip); @@ -583,7 +583,7 @@ static int lx_init_xilinx_reset(struct lx6464es *chip) int i; u32 plx_reg = lx_plx_reg_read(chip, ePLX_CHIPSC); - snd_printdd("->lx_init_xilinx_reset\n"); + dev_dbg(chip->card->dev, "->lx_init_xilinx_reset\n"); /* activate reset of xilinx */ plx_reg &= ~CHIPSC_RESET_XILINX; @@ -603,8 +603,8 @@ static int lx_init_xilinx_reset(struct lx6464es *chip) msleep(10); reg_mbox3 = lx_plx_reg_read(chip, ePLX_MBOX3); if (reg_mbox3) { - snd_printd(LXP "xilinx reset done\n"); - snd_printdd(LXP "xilinx took %d loops\n", i); + dev_dbg(chip->card->dev, "xilinx reset done\n"); + dev_dbg(chip->card->dev, "xilinx took %d loops\n", i); break; } } @@ -624,7 +624,7 @@ static int lx_init_xilinx_test(struct lx6464es *chip) { u32 reg; - snd_printdd("->lx_init_xilinx_test\n"); + dev_dbg(chip->card->dev, "->lx_init_xilinx_test\n"); /* TEST if we have access to Xilinx/MicroBlaze */ lx_dsp_reg_write(chip, eReg_CSM, 0); @@ -632,19 +632,19 @@ static int lx_init_xilinx_test(struct lx6464es *chip) reg = lx_dsp_reg_read(chip, eReg_CSM); if (reg) { - snd_printk(KERN_ERR LXP "Problem: Reg_CSM %x.\n", reg); + dev_err(chip->card->dev, "Problem: Reg_CSM %x.\n", reg); /* PCI9056_SPACE0_REMAP */ lx_plx_reg_write(chip, ePLX_PCICR, 1); reg = lx_dsp_reg_read(chip, eReg_CSM); if (reg) { - snd_printk(KERN_ERR LXP "Error: Reg_CSM %x.\n", reg); + dev_err(chip->card->dev, "Error: Reg_CSM %x.\n", reg); return -EAGAIN; /* seems to be appropriate */ } } - snd_printd(LXP "Xilinx/MicroBlaze access test successful\n"); + dev_dbg(chip->card->dev, "Xilinx/MicroBlaze access test successful\n"); return 0; } @@ -661,7 +661,7 @@ static int lx_init_ethersound_config(struct lx6464es *chip) (64 << IOCR_OUTPUTS_OFFSET) | (FREQ_RATIO_SINGLE_MODE << FREQ_RATIO_OFFSET); - snd_printdd("->lx_init_ethersound\n"); + dev_dbg(chip->card->dev, "->lx_init_ethersound\n"); chip->freq_ratio = FREQ_RATIO_SINGLE_MODE; @@ -675,18 +675,18 @@ static int lx_init_ethersound_config(struct lx6464es *chip) for (i = 0; i != 1000; ++i) { if (lx_dsp_reg_read(chip, eReg_CSES) & 4) { - snd_printd(LXP "ethersound initialized after %dms\n", + dev_dbg(chip->card->dev, "ethersound initialized after %dms\n", i); goto ethersound_initialized; } msleep(1); } - snd_printk(KERN_WARNING LXP + dev_warn(chip->card->dev, "ethersound could not be initialized after %dms\n", i); return -ETIMEDOUT; ethersound_initialized: - snd_printd(LXP "ethersound initialized\n"); + dev_dbg(chip->card->dev, "ethersound initialized\n"); return 0; } @@ -696,14 +696,14 @@ static int lx_init_get_version_features(struct lx6464es *chip) int err; - snd_printdd("->lx_init_get_version_features\n"); + dev_dbg(chip->card->dev, "->lx_init_get_version_features\n"); err = lx_dsp_get_version(chip, &dsp_version); if (err == 0) { u32 freq; - snd_printk(LXP "DSP version: V%02d.%02d #%d\n", + dev_info(chip->card->dev, "DSP version: V%02d.%02d #%d\n", (dsp_version>>16) & 0xff, (dsp_version>>8) & 0xff, dsp_version & 0xff); @@ -718,9 +718,9 @@ static int lx_init_get_version_features(struct lx6464es *chip) err = lx_dsp_get_clock_frequency(chip, &freq); if (err == 0) chip->board_sample_rate = freq; - snd_printd(LXP "actual clock frequency %d\n", freq); + dev_dbg(chip->card->dev, "actual clock frequency %d\n", freq); } else { - snd_printk(KERN_ERR LXP "DSP corrupted \n"); + dev_err(chip->card->dev, "DSP corrupted \n"); err = -EAGAIN; } @@ -732,7 +732,7 @@ static int lx_set_granularity(struct lx6464es *chip, u32 gran) int err = 0; u32 snapped_gran = MICROBLAZE_IBL_MIN; - snd_printdd("->lx_set_granularity\n"); + dev_dbg(chip->card->dev, "->lx_set_granularity\n"); /* blocksize is a power of 2 */ while ((snapped_gran < gran) && @@ -745,14 +745,14 @@ static int lx_set_granularity(struct lx6464es *chip, u32 gran) err = lx_dsp_set_granularity(chip, snapped_gran); if (err < 0) { - snd_printk(KERN_WARNING LXP "could not set granularity\n"); + dev_warn(chip->card->dev, "could not set granularity\n"); err = -EAGAIN; } if (snapped_gran != gran) - snd_printk(LXP "snapped blocksize to %d\n", snapped_gran); + dev_err(chip->card->dev, "snapped blocksize to %d\n", snapped_gran); - snd_printd(LXP "set blocksize on board %d\n", snapped_gran); + dev_dbg(chip->card->dev, "set blocksize on board %d\n", snapped_gran); chip->pcm_granularity = snapped_gran; return err; @@ -764,19 +764,19 @@ static int lx_init_dsp(struct lx6464es *chip) int err; int i; - snd_printdd("->lx_init_dsp\n"); + dev_dbg(chip->card->dev, "->lx_init_dsp\n"); - snd_printd(LXP "initialize board\n"); + dev_dbg(chip->card->dev, "initialize board\n"); err = lx_init_xilinx_reset(chip); if (err) return err; - snd_printd(LXP "testing board\n"); + dev_dbg(chip->card->dev, "testing board\n"); err = lx_init_xilinx_test(chip); if (err) return err; - snd_printd(LXP "initialize ethersound configuration\n"); + dev_dbg(chip->card->dev, "initialize ethersound configuration\n"); err = lx_init_ethersound_config(chip); if (err) return err; @@ -797,8 +797,9 @@ static int lx_init_dsp(struct lx6464es *chip) return -ETIMEDOUT; mac_ready: - snd_printd(LXP "mac address ready read after: %dms\n", i); - snd_printk(LXP "mac address: %02X.%02X.%02X.%02X.%02X.%02X\n", + dev_dbg(chip->card->dev, "mac address ready read after: %dms\n", i); + dev_info(chip->card->dev, + "mac address: %02X.%02X.%02X.%02X.%02X.%02X\n", chip->mac_address[0], chip->mac_address[1], chip->mac_address[2], chip->mac_address[3], chip->mac_address[4], chip->mac_address[5]); @@ -977,7 +978,7 @@ static int snd_lx6464es_create(struct snd_card *card, .dev_free = snd_lx6464es_dev_free, }; - snd_printdd("->snd_lx6464es_create\n"); + dev_dbg(card->dev, "->snd_lx6464es_create\n"); *rchip = NULL; @@ -991,8 +992,8 @@ static int snd_lx6464es_create(struct snd_card *card, /* check if we can restrict PCI DMA transfers to 32 bits */ err = pci_set_dma_mask(pci, DMA_BIT_MASK(32)); if (err < 0) { - snd_printk(KERN_ERR "architecture does not support " - "32bit PCI busmaster DMA\n"); + dev_err(card->dev, + "architecture does not support 32bit PCI busmaster DMA\n"); pci_disable_device(pci); return -ENXIO; } @@ -1034,7 +1035,7 @@ static int snd_lx6464es_create(struct snd_card *card, err = request_irq(pci->irq, lx_interrupt, IRQF_SHARED, KBUILD_MODNAME, chip); if (err) { - snd_printk(KERN_ERR LXP "unable to grab IRQ %d\n", pci->irq); + dev_err(card->dev, "unable to grab IRQ %d\n", pci->irq); goto request_irq_failed; } chip->irq = pci->irq; @@ -1045,7 +1046,7 @@ static int snd_lx6464es_create(struct snd_card *card, err = lx_init_dsp(chip); if (err < 0) { - snd_printk(KERN_ERR LXP "error during DSP initialization\n"); + dev_err(card->dev, "error during DSP initialization\n"); return err; } @@ -1062,8 +1063,6 @@ static int snd_lx6464es_create(struct snd_card *card, if (err < 0) return err; - snd_card_set_dev(card, &pci->dev); - *rchip = chip; return 0; @@ -1090,7 +1089,7 @@ static int snd_lx6464es_probe(struct pci_dev *pci, struct lx6464es *chip; int err; - snd_printdd("->snd_lx6464es_probe\n"); + dev_dbg(&pci->dev, "->snd_lx6464es_probe\n"); if (dev >= SNDRV_CARDS) return -ENODEV; @@ -1099,13 +1098,14 @@ static int snd_lx6464es_probe(struct pci_dev *pci, return -ENOENT; } - err = snd_card_create(index[dev], id[dev], THIS_MODULE, 0, &card); + err = snd_card_new(&pci->dev, index[dev], id[dev], THIS_MODULE, + 0, &card); if (err < 0) return err; err = snd_lx6464es_create(card, pci, &chip); if (err < 0) { - snd_printk(KERN_ERR LXP "error during snd_lx6464es_create\n"); + dev_err(card->dev, "error during snd_lx6464es_create\n"); goto out_free; } @@ -1125,7 +1125,7 @@ static int snd_lx6464es_probe(struct pci_dev *pci, if (err < 0) goto out_free; - snd_printdd(LXP "initialization successful\n"); + dev_dbg(chip->card->dev, "initialization successful\n"); pci_set_drvdata(pci, card); dev++; return 0; diff --git a/sound/pci/lx6464es/lx_core.c b/sound/pci/lx6464es/lx_core.c index 626ecad4dae..2d8e95e9fbe 100644 --- a/sound/pci/lx6464es/lx_core.c +++ b/sound/pci/lx6464es/lx_core.c @@ -141,63 +141,6 @@ void lx_plx_reg_write(struct lx6464es *chip, int port, u32 data) iowrite32(data, address); } -u32 lx_plx_mbox_read(struct lx6464es *chip, int mbox_nr) -{ - int index; - - switch (mbox_nr) { - case 1: - index = ePLX_MBOX1; break; - case 2: - index = ePLX_MBOX2; break; - case 3: - index = ePLX_MBOX3; break; - case 4: - index = ePLX_MBOX4; break; - case 5: - index = ePLX_MBOX5; break; - case 6: - index = ePLX_MBOX6; break; - case 7: - index = ePLX_MBOX7; break; - case 0: /* reserved for HF flags */ - snd_BUG(); - default: - return 0xdeadbeef; - } - - return lx_plx_reg_read(chip, index); -} - -int lx_plx_mbox_write(struct lx6464es *chip, int mbox_nr, u32 value) -{ - int index = -1; - - switch (mbox_nr) { - case 1: - index = ePLX_MBOX1; break; - case 3: - index = ePLX_MBOX3; break; - case 4: - index = ePLX_MBOX4; break; - case 5: - index = ePLX_MBOX5; break; - case 6: - index = ePLX_MBOX6; break; - case 7: - index = ePLX_MBOX7; break; - case 0: /* reserved for HF flags */ - case 2: /* reserved for Pipe States - * the DSP keeps an image of it */ - snd_BUG(); - return -EBADRQC; - } - - lx_plx_reg_write(chip, index, value); - return 0; -} - - /* rmh */ #ifdef CONFIG_SND_DEBUG @@ -330,7 +273,7 @@ static int lx_message_send_atomic(struct lx6464es *chip, struct lx_rmh *rmh) int dwloop; if (lx_dsp_reg_read(chip, eReg_CSM) & (Reg_CSM_MC | Reg_CSM_MR)) { - snd_printk(KERN_ERR LXP "PIOSendMessage eReg_CSM %x\n", reg); + dev_err(chip->card->dev, "PIOSendMessage eReg_CSM %x\n", reg); return -EBUSY; } @@ -351,7 +294,7 @@ static int lx_message_send_atomic(struct lx6464es *chip, struct lx_rmh *rmh) } else udelay(1); } - snd_printk(KERN_WARNING LXP "TIMEOUT lx_message_send_atomic! " + dev_warn(chip->card->dev, "TIMEOUT lx_message_send_atomic! " "polling failed\n"); polling_successful: @@ -363,18 +306,18 @@ polling_successful: rmh->stat_len); } } else - snd_printk(LXP "rmh error: %08x\n", reg); + dev_err(chip->card->dev, "rmh error: %08x\n", reg); /* clear Reg_CSM_MR */ lx_dsp_reg_write(chip, eReg_CSM, 0); switch (reg) { case ED_DSP_TIMED_OUT: - snd_printk(KERN_WARNING LXP "lx_message_send: dsp timeout\n"); + dev_warn(chip->card->dev, "lx_message_send: dsp timeout\n"); return -ETIMEDOUT; case ED_DSP_CRASHED: - snd_printk(KERN_WARNING LXP "lx_message_send: dsp crashed\n"); + dev_warn(chip->card->dev, "lx_message_send: dsp crashed\n"); return -EAGAIN; } @@ -491,33 +434,6 @@ int lx_dsp_read_async_events(struct lx6464es *chip, u32 *data) #define CSES_BROADCAST 0x0002 #define CSES_UPDATE_LDSV 0x0004 -int lx_dsp_es_check_pipeline(struct lx6464es *chip) -{ - int i; - - for (i = 0; i != CSES_TIMEOUT; ++i) { - /* - * le bit CSES_UPDATE_LDSV est à1 dés que le macprog - * est pret. il re-passe à0 lorsque le premier read a - * été fait. pour l'instant on retire le test car ce bit - * passe a 1 environ 200 à400 ms aprés que le registre - * confES àété écrit (kick du xilinx ES). - * - * On ne teste que le bit CE. - * */ - - u32 cses = lx_dsp_reg_read(chip, eReg_CSES); - - if ((cses & CSES_CE) == 0) - return 0; - - udelay(1); - } - - return -ETIMEDOUT; -} - - #define PIPE_INFO_TO_CMD(capture, pipe) \ ((u32)((u32)(pipe) | ((capture) ? ID_IS_CAPTURE : 0L)) << ID_OFFSET) @@ -542,7 +458,7 @@ int lx_pipe_allocate(struct lx6464es *chip, u32 pipe, int is_capture, spin_unlock_irqrestore(&chip->msg_lock, flags); if (err != 0) - snd_printk(KERN_ERR "lx6464es: could not allocate pipe\n"); + dev_err(chip->card->dev, "could not allocate pipe\n"); return err; } @@ -604,11 +520,13 @@ int lx_buffer_ask(struct lx6464es *chip, u32 pipe, int is_capture, } #if 0 - snd_printdd(LXP "CMD_08_ASK_BUFFERS: needed %d, freed %d\n", + dev_dbg(chip->card->dev, + "CMD_08_ASK_BUFFERS: needed %d, freed %d\n", *r_needed, *r_freed); for (i = 0; i < MAX_STREAM_BUFFER; ++i) { for (i = 0; i != chip->rmh.stat_len; ++i) - snd_printdd(" stat[%d]: %x, %x\n", i, + dev_dbg(chip->card->dev, + " stat[%d]: %x, %x\n", i, chip->rmh.stat[i], chip->rmh.stat[i] & MASK_DATA_SIZE); } @@ -701,8 +619,8 @@ int lx_pipe_sample_count(struct lx6464es *chip, u32 pipe, int is_capture, err = lx_message_send_atomic(chip, &chip->rmh); /* don't sleep! */ if (err != 0) - snd_printk(KERN_ERR - "lx6464es: could not query pipe's sample count\n"); + dev_err(chip->card->dev, + "could not query pipe's sample count\n"); else { *rsample_count = ((u64)(chip->rmh.stat[0] & MASK_SPL_COUNT_HI) << 24) /* hi part */ @@ -728,7 +646,7 @@ int lx_pipe_state(struct lx6464es *chip, u32 pipe, int is_capture, u16 *rstate) err = lx_message_send_atomic(chip, &chip->rmh); if (err != 0) - snd_printk(KERN_ERR "lx6464es: could not query pipe's state\n"); + dev_err(chip->card->dev, "could not query pipe's state\n"); else *rstate = (chip->rmh.stat[0] >> PSTATE_OFFSET) & 0x0F; @@ -801,7 +719,7 @@ int lx_stream_set_format(struct lx6464es *chip, struct snd_pcm_runtime *runtime, u32 channels = runtime->channels; if (runtime->channels != channels) - snd_printk(KERN_ERR LXP "channel count mismatch: %d vs %d", + dev_err(chip->card->dev, "channel count mismatch: %d vs %d", runtime->channels, channels); spin_lock_irqsave(&chip->msg_lock, flags); @@ -904,13 +822,16 @@ int lx_buffer_give(struct lx6464es *chip, u32 pipe, int is_capture, } if (err == EB_RBUFFERS_TABLE_OVERFLOW) - snd_printk(LXP "lx_buffer_give EB_RBUFFERS_TABLE_OVERFLOW\n"); + dev_err(chip->card->dev, + "lx_buffer_give EB_RBUFFERS_TABLE_OVERFLOW\n"); if (err == EB_INVALID_STREAM) - snd_printk(LXP "lx_buffer_give EB_INVALID_STREAM\n"); + dev_err(chip->card->dev, + "lx_buffer_give EB_INVALID_STREAM\n"); if (err == EB_CMD_REFUSED) - snd_printk(LXP "lx_buffer_give EB_CMD_REFUSED\n"); + dev_err(chip->card->dev, + "lx_buffer_give EB_CMD_REFUSED\n"); done: spin_unlock_irqrestore(&chip->msg_lock, flags); @@ -983,7 +904,8 @@ int lx_level_unmute(struct lx6464es *chip, int is_capture, int unmute) chip->rmh.cmd[1] = (u32)(mute_mask >> (u64)32); /* hi part */ chip->rmh.cmd[2] = (u32)(mute_mask & (u64)0xFFFFFFFF); /* lo part */ - snd_printk("mute %x %x %x\n", chip->rmh.cmd[0], chip->rmh.cmd[1], + dev_dbg(chip->card->dev, + "mute %x %x %x\n", chip->rmh.cmd[0], chip->rmh.cmd[1], chip->rmh.cmd[2]); err = lx_message_send_atomic(chip, &chip->rmh); @@ -1093,7 +1015,7 @@ static int lx_interrupt_ack(struct lx6464es *chip, u32 *r_irqsrc, } if (irq_async) { - /* snd_printd("interrupt: async event pending\n"); */ + /* dev_dbg(chip->card->dev, "interrupt: async event pending\n"); */ *r_async_pending = 1; } @@ -1139,13 +1061,13 @@ static int lx_interrupt_handle_async_events(struct lx6464es *chip, u32 irqsrc, if (eb_pending_in) { *r_notified_in_pipe_mask = ((u64)stat[3] << 32) + stat[4]; - snd_printdd(LXP "interrupt: EOBI pending %llx\n", + dev_dbg(chip->card->dev, "interrupt: EOBI pending %llx\n", *r_notified_in_pipe_mask); } if (eb_pending_out) { *r_notified_out_pipe_mask = ((u64)stat[1] << 32) + stat[2]; - snd_printdd(LXP "interrupt: EOBO pending %llx\n", + dev_dbg(chip->card->dev, "interrupt: EOBO pending %llx\n", *r_notified_out_pipe_mask); } @@ -1181,17 +1103,19 @@ static int lx_interrupt_request_new_buffer(struct lx6464es *chip, u32 needed, freed; u32 size_array[MAX_STREAM_BUFFER]; - snd_printdd("->lx_interrupt_request_new_buffer\n"); + dev_dbg(chip->card->dev, "->lx_interrupt_request_new_buffer\n"); spin_lock_irqsave(&chip->lock, flags); err = lx_buffer_ask(chip, 0, is_capture, &needed, &freed, size_array); - snd_printdd(LXP "interrupt: needed %d, freed %d\n", needed, freed); + dev_dbg(chip->card->dev, + "interrupt: needed %d, freed %d\n", needed, freed); unpack_pointer(buf, &buf_lo, &buf_hi); err = lx_buffer_give(chip, 0, is_capture, period_bytes, buf_lo, buf_hi, &buffer_index); - snd_printdd(LXP "interrupt: gave buffer index %x on 0x%lx (%d bytes)\n", + dev_dbg(chip->card->dev, + "interrupt: gave buffer index %x on 0x%lx (%d bytes)\n", buffer_index, (unsigned long)buf, period_bytes); lx_stream->frame_pos = next_pos; @@ -1206,11 +1130,11 @@ void lx_tasklet_playback(unsigned long data) struct lx_stream *lx_stream = &chip->playback_stream; int err; - snd_printdd("->lx_tasklet_playback\n"); + dev_dbg(chip->card->dev, "->lx_tasklet_playback\n"); err = lx_interrupt_request_new_buffer(chip, lx_stream); if (err < 0) - snd_printk(KERN_ERR LXP + dev_err(chip->card->dev, "cannot request new buffer for playback\n"); snd_pcm_period_elapsed(lx_stream->stream); @@ -1222,10 +1146,10 @@ void lx_tasklet_capture(unsigned long data) struct lx_stream *lx_stream = &chip->capture_stream; int err; - snd_printdd("->lx_tasklet_capture\n"); + dev_dbg(chip->card->dev, "->lx_tasklet_capture\n"); err = lx_interrupt_request_new_buffer(chip, lx_stream); if (err < 0) - snd_printk(KERN_ERR LXP + dev_err(chip->card->dev, "cannot request new buffer for capture\n"); snd_pcm_period_elapsed(lx_stream->stream); @@ -1240,12 +1164,14 @@ static int lx_interrupt_handle_audio_transfer(struct lx6464es *chip, int err = 0; if (notified_in_pipe_mask) { - snd_printdd(LXP "requesting audio transfer for capture\n"); + dev_dbg(chip->card->dev, + "requesting audio transfer for capture\n"); tasklet_hi_schedule(&chip->tasklet_capture); } if (notified_out_pipe_mask) { - snd_printdd(LXP "requesting audio transfer for playback\n"); + dev_dbg(chip->card->dev, + "requesting audio transfer for playback\n"); tasklet_hi_schedule(&chip->tasklet_playback); } @@ -1261,11 +1187,12 @@ irqreturn_t lx_interrupt(int irq, void *dev_id) spin_lock(&chip->lock); - snd_printdd("**************************************************\n"); + dev_dbg(chip->card->dev, + "**************************************************\n"); if (!lx_interrupt_ack(chip, &irqsrc, &async_pending, &async_escmd)) { spin_unlock(&chip->lock); - snd_printdd("IRQ_NONE\n"); + dev_dbg(chip->card->dev, "IRQ_NONE\n"); return IRQ_NONE; /* this device did not cause the interrupt */ } @@ -1274,16 +1201,16 @@ irqreturn_t lx_interrupt(int irq, void *dev_id) #if 0 if (irqsrc & MASK_SYS_STATUS_EOBI) - snd_printdd(LXP "interrupt: EOBI\n"); + dev_dgg(chip->card->dev, "interrupt: EOBI\n"); if (irqsrc & MASK_SYS_STATUS_EOBO) - snd_printdd(LXP "interrupt: EOBO\n"); + dev_dbg(chip->card->dev, "interrupt: EOBO\n"); if (irqsrc & MASK_SYS_STATUS_URUN) - snd_printdd(LXP "interrupt: URUN\n"); + dev_dbg(chip->card->dev, "interrupt: URUN\n"); if (irqsrc & MASK_SYS_STATUS_ORUN) - snd_printdd(LXP "interrupt: ORUN\n"); + dev_dbg(chip->card->dev, "interrupt: ORUN\n"); #endif if (async_pending) { @@ -1298,7 +1225,7 @@ irqreturn_t lx_interrupt(int irq, void *dev_id) ¬ified_in_pipe_mask, ¬ified_out_pipe_mask); if (err) - snd_printk(KERN_ERR LXP + dev_err(chip->card->dev, "error handling async events\n"); err = lx_interrupt_handle_audio_transfer(chip, @@ -1306,7 +1233,7 @@ irqreturn_t lx_interrupt(int irq, void *dev_id) notified_out_pipe_mask ); if (err) - snd_printk(KERN_ERR LXP + dev_err(chip->card->dev, "error during audio transfer\n"); } @@ -1318,7 +1245,7 @@ irqreturn_t lx_interrupt(int irq, void *dev_id) * * */ - snd_printdd("lx6464es: interrupt requests escmd handling\n"); + dev_dbg(chip->card->dev, "interrupt requests escmd handling\n"); #endif } @@ -1346,12 +1273,12 @@ static void lx_irq_set(struct lx6464es *chip, int enable) void lx_irq_enable(struct lx6464es *chip) { - snd_printdd("->lx_irq_enable\n"); + dev_dbg(chip->card->dev, "->lx_irq_enable\n"); lx_irq_set(chip, 1); } void lx_irq_disable(struct lx6464es *chip) { - snd_printdd("->lx_irq_disable\n"); + dev_dbg(chip->card->dev, "->lx_irq_disable\n"); lx_irq_set(chip, 0); } diff --git a/sound/pci/maestro3.c b/sound/pci/maestro3.c index d5417360f51..0d3ea3e7995 100644 --- a/sound/pci/maestro3.c +++ b/sound/pci/maestro3.c @@ -1403,7 +1403,7 @@ static int snd_m3_pcm_hw_params(struct snd_pcm_substream *substream, /* set buffer address */ s->buffer_addr = substream->runtime->dma_addr; if (s->buffer_addr & 0x3) { - snd_printk(KERN_ERR "oh my, not aligned\n"); + dev_err(substream->pcm->card->dev, "oh my, not aligned\n"); s->buffer_addr = s->buffer_addr & ~0x3; } return 0; @@ -1900,7 +1900,7 @@ static int snd_m3_ac97_wait(struct snd_m3 *chip) cpu_relax(); } while (i-- > 0); - snd_printk(KERN_ERR "ac97 serial bus busy\n"); + dev_err(chip->card->dev, "ac97 serial bus busy\n"); return 1; } @@ -2015,7 +2015,8 @@ static void snd_m3_ac97_reset(struct snd_m3 *chip) delay1 += 10; delay2 += 100; - snd_printd("maestro3: retrying codec reset with delays of %d and %d ms\n", + dev_dbg(chip->card->dev, + "retrying codec reset with delays of %d and %d ms\n", delay1, delay2); } @@ -2194,7 +2195,8 @@ static int snd_m3_assp_client_init(struct snd_m3 *chip, struct m3_dma *s, int in address = 0x1100 + ((data_bytes/2) * index); if ((address + (data_bytes/2)) >= 0x1c00) { - snd_printk(KERN_ERR "no memory for %d bytes at ind %d (addr 0x%x)\n", + dev_err(chip->card->dev, + "no memory for %d bytes at ind %d (addr 0x%x)\n", data_bytes, index, address); return -ENOMEM; } @@ -2439,8 +2441,7 @@ static int m3_resume(struct device *dev) pci_set_power_state(pci, PCI_D0); pci_restore_state(pci); if (pci_enable_device(pci) < 0) { - printk(KERN_ERR "maestor3: pci_enable_device failed, " - "disabling device\n"); + dev_err(dev, "pci_enable_device failed, disabling device\n"); snd_card_disconnect(card); return -EIO; } @@ -2553,7 +2554,8 @@ snd_m3_create(struct snd_card *card, struct pci_dev *pci, /* check, if we can restrict PCI DMA transfers to 28 bits */ if (pci_set_dma_mask(pci, DMA_BIT_MASK(28)) < 0 || pci_set_consistent_dma_mask(pci, DMA_BIT_MASK(28)) < 0) { - snd_printk(KERN_ERR "architecture does not support 28bit PCI busmaster DMA\n"); + dev_err(card->dev, + "architecture does not support 28bit PCI busmaster DMA\n"); pci_disable_device(pci); return -ENXIO; } @@ -2586,9 +2588,8 @@ snd_m3_create(struct snd_card *card, struct pci_dev *pci, else { quirk = snd_pci_quirk_lookup(pci, m3_amp_quirk_list); if (quirk) { - snd_printdd(KERN_INFO - "maestro3: set amp-gpio for '%s'\n", - snd_pci_quirk_name(quirk)); + dev_info(card->dev, "set amp-gpio for '%s'\n", + snd_pci_quirk_name(quirk)); chip->amp_gpio = quirk->value; } else if (chip->allegro_flag) chip->amp_gpio = GPO_EXT_AMP_ALLEGRO; @@ -2598,9 +2599,8 @@ snd_m3_create(struct snd_card *card, struct pci_dev *pci, quirk = snd_pci_quirk_lookup(pci, m3_irda_quirk_list); if (quirk) { - snd_printdd(KERN_INFO - "maestro3: enabled irda workaround for '%s'\n", - snd_pci_quirk_name(quirk)); + dev_info(card->dev, "enabled irda workaround for '%s'\n", + snd_pci_quirk_name(quirk)); chip->irda_workaround = 1; } quirk = snd_pci_quirk_lookup(pci, m3_hv_quirk_list); @@ -2652,7 +2652,7 @@ snd_m3_create(struct snd_card *card, struct pci_dev *pci, if (request_irq(pci->irq, snd_m3_interrupt, IRQF_SHARED, KBUILD_MODNAME, chip)) { - snd_printk(KERN_ERR "unable to grab IRQ %d\n", pci->irq); + dev_err(card->dev, "unable to grab IRQ %d\n", pci->irq); snd_m3_free(chip); return -ENOMEM; } @@ -2661,7 +2661,7 @@ snd_m3_create(struct snd_card *card, struct pci_dev *pci, #ifdef CONFIG_PM_SLEEP chip->suspend_mem = vmalloc(sizeof(u16) * (REV_B_CODE_MEMORY_LENGTH + REV_B_DATA_MEMORY_LENGTH)); if (chip->suspend_mem == NULL) - snd_printk(KERN_WARNING "can't allocate apm buffer\n"); + dev_warn(card->dev, "can't allocate apm buffer\n"); #endif if ((err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops)) < 0) { @@ -2685,16 +2685,15 @@ snd_m3_create(struct snd_card *card, struct pci_dev *pci, if (chip->hv_config & HV_CTRL_ENABLE) { err = snd_m3_input_register(chip); if (err) - snd_printk(KERN_WARNING "Input device registration " - "failed with error %i", err); + dev_warn(card->dev, + "Input device registration failed with error %i", + err); } #endif snd_m3_enable_ints(chip); snd_m3_assp_continue(chip); - snd_card_set_dev(card, &pci->dev); - *chip_ret = chip; return 0; @@ -2721,7 +2720,8 @@ snd_m3_probe(struct pci_dev *pci, const struct pci_device_id *pci_id) return -ENOENT; } - err = snd_card_create(index[dev], id[dev], THIS_MODULE, 0, &card); + err = snd_card_new(&pci->dev, index[dev], id[dev], THIS_MODULE, + 0, &card); if (err < 0) return err; @@ -2764,7 +2764,7 @@ snd_m3_probe(struct pci_dev *pci, const struct pci_device_id *pci_id) MPU401_INFO_INTEGRATED | MPU401_INFO_IRQ_HOOK, -1, &chip->rmidi); if (err < 0) - printk(KERN_WARNING "maestro3: no MIDI support.\n"); + dev_warn(card->dev, "no MIDI support.\n"); #endif pci_set_drvdata(pci, card); diff --git a/sound/pci/mixart/mixart.c b/sound/pci/mixart/mixart.c index 1e0f6ee193f..a93e7af51ee 100644 --- a/sound/pci/mixart/mixart.c +++ b/sound/pci/mixart/mixart.c @@ -87,7 +87,8 @@ static int mixart_set_pipe_state(struct mixart_mgr *mgr, if(!start) return 0; /* already stopped */ break; default: - snd_printk(KERN_ERR "error mixart_set_pipe_state called with wrong pipe->status!\n"); + dev_err(&mgr->pci->dev, + "error mixart_set_pipe_state called with wrong pipe->status!\n"); return -EINVAL; /* function called with wrong pipe status */ } @@ -102,7 +103,8 @@ static int mixart_set_pipe_state(struct mixart_mgr *mgr, err = snd_mixart_send_msg_wait_notif(mgr, &request, system_msg_uid); if(err) { - snd_printk(KERN_ERR "error : MSG_SYSTEM_WAIT_SYNCHRO_CMD was not notified !\n"); + dev_err(&mgr->pci->dev, + "error : MSG_SYSTEM_WAIT_SYNCHRO_CMD was not notified !\n"); return err; } @@ -123,7 +125,9 @@ static int mixart_set_pipe_state(struct mixart_mgr *mgr, err = snd_mixart_send_msg(mgr, &request, sizeof(group_state_resp), &group_state_resp); if (err < 0 || group_state_resp.txx_status != 0) { - snd_printk(KERN_ERR "error MSG_STREAM_ST***_STREAM_GRP_PACKET err=%x stat=%x !\n", err, group_state_resp.txx_status); + dev_err(&mgr->pci->dev, + "error MSG_STREAM_ST***_STREAM_GRP_PACKET err=%x stat=%x !\n", + err, group_state_resp.txx_status); return -EINVAL; } @@ -134,7 +138,9 @@ static int mixart_set_pipe_state(struct mixart_mgr *mgr, err = snd_mixart_send_msg(mgr, &request, sizeof(group_state_resp), &group_state_resp); if (err < 0 || group_state_resp.txx_status != 0) { - snd_printk(KERN_ERR "error MSG_STREAM_START_STREAM_GRP_PACKET err=%x stat=%x !\n", err, group_state_resp.txx_status); + dev_err(&mgr->pci->dev, + "error MSG_STREAM_START_STREAM_GRP_PACKET err=%x stat=%x !\n", + err, group_state_resp.txx_status); return -EINVAL; } @@ -147,7 +153,9 @@ static int mixart_set_pipe_state(struct mixart_mgr *mgr, err = snd_mixart_send_msg(mgr, &request, sizeof(stat), &stat); if (err < 0 || stat != 0) { - snd_printk(KERN_ERR "error MSG_SYSTEM_SEND_SYNCHRO_CMD err=%x stat=%x !\n", err, stat); + dev_err(&mgr->pci->dev, + "error MSG_SYSTEM_SEND_SYNCHRO_CMD err=%x stat=%x !\n", + err, stat); return -EINVAL; } @@ -178,7 +186,9 @@ static int mixart_set_clock(struct mixart_mgr *mgr, if(rate == 0) return 0; /* nothing to do */ else { - snd_printk(KERN_ERR "error mixart_set_clock(%d) called with wrong pipe->status !\n", rate); + dev_err(&mgr->pci->dev, + "error mixart_set_clock(%d) called with wrong pipe->status !\n", + rate); return -EINVAL; } } @@ -190,7 +200,7 @@ static int mixart_set_clock(struct mixart_mgr *mgr, clock_properties.nb_callers = 1; /* only one entry in uid_caller ! */ clock_properties.uid_caller[0] = pipe->group_uid; - snd_printdd("mixart_set_clock to %d kHz\n", rate); + dev_dbg(&mgr->pci->dev, "mixart_set_clock to %d kHz\n", rate); request.message_id = MSG_CLOCK_SET_PROPERTIES; request.uid = mgr->uid_console_manager; @@ -199,7 +209,9 @@ static int mixart_set_clock(struct mixart_mgr *mgr, err = snd_mixart_send_msg(mgr, &request, sizeof(clock_prop_resp), &clock_prop_resp); if (err < 0 || clock_prop_resp.status != 0 || clock_prop_resp.clock_mode != CM_STANDALONE) { - snd_printk(KERN_ERR "error MSG_CLOCK_SET_PROPERTIES err=%x stat=%x mod=%x !\n", err, clock_prop_resp.status, clock_prop_resp.clock_mode); + dev_err(&mgr->pci->dev, + "error MSG_CLOCK_SET_PROPERTIES err=%x stat=%x mod=%x !\n", + err, clock_prop_resp.status, clock_prop_resp.clock_mode); return -EINVAL; } @@ -252,7 +264,9 @@ snd_mixart_add_ref_pipe(struct snd_mixart *chip, int pcm_number, int capture, struct mixart_streaming_group sgroup_resp; } *buf; - snd_printdd("add_ref_pipe audio chip(%d) pcm(%d)\n", chip->chip_idx, pcm_number); + dev_dbg(chip->card->dev, + "add_ref_pipe audio chip(%d) pcm(%d)\n", + chip->chip_idx, pcm_number); buf = kmalloc(sizeof(*buf), GFP_KERNEL); if (!buf) @@ -302,7 +316,9 @@ snd_mixart_add_ref_pipe(struct snd_mixart *chip, int pcm_number, int capture, err = snd_mixart_send_msg(chip->mgr, &request, sizeof(buf->sgroup_resp), &buf->sgroup_resp); if((err < 0) || (buf->sgroup_resp.status != 0)) { - snd_printk(KERN_ERR "error MSG_STREAM_ADD_**PUT_GROUP err=%x stat=%x !\n", err, buf->sgroup_resp.status); + dev_err(chip->card->dev, + "error MSG_STREAM_ADD_**PUT_GROUP err=%x stat=%x !\n", + err, buf->sgroup_resp.status); kfree(buf); return NULL; } @@ -343,13 +359,14 @@ int snd_mixart_kill_ref_pipe(struct mixart_mgr *mgr, /* release the clock */ err = mixart_set_clock( mgr, pipe, 0); if( err < 0 ) { - snd_printk(KERN_ERR "mixart_set_clock(0) return error!\n"); + dev_err(&mgr->pci->dev, + "mixart_set_clock(0) return error!\n"); } /* stop the pipe */ err = mixart_set_pipe_state(mgr, pipe, 0); if( err < 0 ) { - snd_printk(KERN_ERR "error stopping pipe!\n"); + dev_err(&mgr->pci->dev, "error stopping pipe!\n"); } request.message_id = MSG_STREAM_DELETE_GROUP; @@ -360,7 +377,9 @@ int snd_mixart_kill_ref_pipe(struct mixart_mgr *mgr, /* delete the pipe */ err = snd_mixart_send_msg(mgr, &request, sizeof(delete_resp), &delete_resp); if ((err < 0) || (delete_resp.status != 0)) { - snd_printk(KERN_ERR "error MSG_STREAM_DELETE_GROUP err(%x), status(%x)\n", err, delete_resp.status); + dev_err(&mgr->pci->dev, + "error MSG_STREAM_DELETE_GROUP err(%x), status(%x)\n", + err, delete_resp.status); } pipe->group_uid = (struct mixart_uid){0,0}; @@ -414,7 +433,7 @@ static int snd_mixart_trigger(struct snd_pcm_substream *subs, int cmd) switch (cmd) { case SNDRV_PCM_TRIGGER_START: - snd_printdd("SNDRV_PCM_TRIGGER_START\n"); + dev_dbg(subs->pcm->card->dev, "SNDRV_PCM_TRIGGER_START\n"); /* START_STREAM */ if( mixart_set_stream_state(stream, 1) ) @@ -431,19 +450,19 @@ static int snd_mixart_trigger(struct snd_pcm_substream *subs, int cmd) stream->status = MIXART_STREAM_STATUS_OPEN; - snd_printdd("SNDRV_PCM_TRIGGER_STOP\n"); + dev_dbg(subs->pcm->card->dev, "SNDRV_PCM_TRIGGER_STOP\n"); break; case SNDRV_PCM_TRIGGER_PAUSE_PUSH: /* TODO */ stream->status = MIXART_STREAM_STATUS_PAUSE; - snd_printdd("SNDRV_PCM_PAUSE_PUSH\n"); + dev_dbg(subs->pcm->card->dev, "SNDRV_PCM_PAUSE_PUSH\n"); break; case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: /* TODO */ stream->status = MIXART_STREAM_STATUS_RUNNING; - snd_printdd("SNDRV_PCM_PAUSE_RELEASE\n"); + dev_dbg(subs->pcm->card->dev, "SNDRV_PCM_PAUSE_RELEASE\n"); break; default: return -EINVAL; @@ -456,7 +475,8 @@ static int mixart_sync_nonblock_events(struct mixart_mgr *mgr) unsigned long timeout = jiffies + HZ; while (atomic_read(&mgr->msg_processed) > 0) { if (time_after(jiffies, timeout)) { - snd_printk(KERN_ERR "mixart: cannot process nonblock events!\n"); + dev_err(&mgr->pci->dev, + "mixart: cannot process nonblock events!\n"); return -EBUSY; } schedule_timeout_uninterruptible(1); @@ -474,7 +494,7 @@ static int snd_mixart_prepare(struct snd_pcm_substream *subs) /* TODO de façon non bloquante, réappliquer les hw_params (rate, bits, codec) */ - snd_printdd("snd_mixart_prepare\n"); + dev_dbg(chip->card->dev, "snd_mixart_prepare\n"); mixart_sync_nonblock_events(chip->mgr); @@ -542,11 +562,13 @@ static int mixart_set_format(struct mixart_stream *stream, snd_pcm_format_t form stream_param.sample_size = 32; break; default: - snd_printk(KERN_ERR "error mixart_set_format() : unknown format\n"); + dev_err(chip->card->dev, + "error mixart_set_format() : unknown format\n"); return -EINVAL; } - snd_printdd("set SNDRV_PCM_FORMAT sample_type(%d) sample_size(%d) freq(%d) channels(%d)\n", + dev_dbg(chip->card->dev, + "set SNDRV_PCM_FORMAT sample_type(%d) sample_size(%d) freq(%d) channels(%d)\n", stream_param.sample_type, stream_param.sample_size, stream_param.sampling_freq, stream->channels); /* TODO: what else to configure ? */ @@ -566,7 +588,9 @@ static int mixart_set_format(struct mixart_stream *stream, snd_pcm_format_t form err = snd_mixart_send_msg(chip->mgr, &request, sizeof(resp), &resp); if((err < 0) || resp.error_code) { - snd_printk(KERN_ERR "MSG_STREAM_SET_INPUT_STAGE_PARAM err=%x; resp=%x\n", err, resp.error_code); + dev_err(chip->card->dev, + "MSG_STREAM_SET_INPUT_STAGE_PARAM err=%x; resp=%x\n", + err, resp.error_code); return -EINVAL; } return 0; @@ -627,8 +651,9 @@ static int snd_mixart_hw_params(struct snd_pcm_substream *subs, bufferinfo[i].available_length = subs->runtime->dma_bytes; /* bufferinfo[i].buffer_id is already defined */ - snd_printdd("snd_mixart_hw_params(pcm %d) : dma_addr(%x) dma_bytes(%x) subs-number(%d)\n", i, - bufferinfo[i].buffer_address, + dev_dbg(chip->card->dev, + "snd_mixart_hw_params(pcm %d) : dma_addr(%x) dma_bytes(%x) subs-number(%d)\n", + i, bufferinfo[i].buffer_address, bufferinfo[i].available_length, subs->number); } @@ -714,14 +739,18 @@ static int snd_mixart_playback_open(struct snd_pcm_substream *subs) pcm_number = MIXART_PCM_DIGITAL; runtime->hw = snd_mixart_digital_caps; } - snd_printdd("snd_mixart_playback_open C%d/P%d/Sub%d\n", chip->chip_idx, pcm_number, subs->number); + dev_dbg(chip->card->dev, + "snd_mixart_playback_open C%d/P%d/Sub%d\n", + chip->chip_idx, pcm_number, subs->number); /* get stream info */ stream = &(chip->playback_stream[pcm_number][subs->number]); if (stream->status != MIXART_STREAM_STATUS_FREE){ /* streams in use */ - snd_printk(KERN_ERR "snd_mixart_playback_open C%d/P%d/Sub%d in use\n", chip->chip_idx, pcm_number, subs->number); + dev_err(chip->card->dev, + "snd_mixart_playback_open C%d/P%d/Sub%d in use\n", + chip->chip_idx, pcm_number, subs->number); err = -EBUSY; goto _exit_open; } @@ -737,7 +766,7 @@ static int snd_mixart_playback_open(struct snd_pcm_substream *subs) /* start the pipe if necessary */ err = mixart_set_pipe_state(chip->mgr, pipe, 1); if( err < 0 ) { - snd_printk(KERN_ERR "error starting pipe!\n"); + dev_err(chip->card->dev, "error starting pipe!\n"); snd_mixart_kill_ref_pipe(chip->mgr, pipe, 0); err = -EINVAL; goto _exit_open; @@ -792,14 +821,17 @@ static int snd_mixart_capture_open(struct snd_pcm_substream *subs) runtime->hw.channels_min = 2; /* for instance, no mono */ - snd_printdd("snd_mixart_capture_open C%d/P%d/Sub%d\n", chip->chip_idx, pcm_number, subs->number); + dev_dbg(chip->card->dev, "snd_mixart_capture_open C%d/P%d/Sub%d\n", + chip->chip_idx, pcm_number, subs->number); /* get stream info */ stream = &(chip->capture_stream[pcm_number]); if (stream->status != MIXART_STREAM_STATUS_FREE){ /* streams in use */ - snd_printk(KERN_ERR "snd_mixart_capture_open C%d/P%d/Sub%d in use\n", chip->chip_idx, pcm_number, subs->number); + dev_err(chip->card->dev, + "snd_mixart_capture_open C%d/P%d/Sub%d in use\n", + chip->chip_idx, pcm_number, subs->number); err = -EBUSY; goto _exit_open; } @@ -815,7 +847,7 @@ static int snd_mixart_capture_open(struct snd_pcm_substream *subs) /* start the pipe if necessary */ err = mixart_set_pipe_state(chip->mgr, pipe, 1); if( err < 0 ) { - snd_printk(KERN_ERR "error starting pipe!\n"); + dev_err(chip->card->dev, "error starting pipe!\n"); snd_mixart_kill_ref_pipe(chip->mgr, pipe, 0); err = -EINVAL; goto _exit_open; @@ -855,7 +887,8 @@ static int snd_mixart_close(struct snd_pcm_substream *subs) mutex_lock(&mgr->setup_mutex); - snd_printdd("snd_mixart_close C%d/P%d/Sub%d\n", chip->chip_idx, stream->pcm_number, subs->number); + dev_dbg(chip->card->dev, "snd_mixart_close C%d/P%d/Sub%d\n", + chip->chip_idx, stream->pcm_number, subs->number); /* sample rate released */ if(--mgr->ref_count_rate == 0) { @@ -865,7 +898,9 @@ static int snd_mixart_close(struct snd_pcm_substream *subs) /* delete pipe */ if (snd_mixart_kill_ref_pipe(mgr, stream->pipe, 0 ) < 0) { - snd_printk(KERN_ERR "error snd_mixart_kill_ref_pipe C%dP%d\n", chip->chip_idx, stream->pcm_number); + dev_err(chip->card->dev, + "error snd_mixart_kill_ref_pipe C%dP%d\n", + chip->chip_idx, stream->pcm_number); } stream->pipe = NULL; @@ -940,7 +975,8 @@ static int snd_mixart_pcm_analog(struct snd_mixart *chip) if ((err = snd_pcm_new(chip->card, name, MIXART_PCM_ANALOG, MIXART_PLAYBACK_STREAMS, MIXART_CAPTURE_STREAMS, &pcm)) < 0) { - snd_printk(KERN_ERR "cannot create the analog pcm %d\n", chip->chip_idx); + dev_err(chip->card->dev, + "cannot create the analog pcm %d\n", chip->chip_idx); return err; } @@ -971,7 +1007,8 @@ static int snd_mixart_pcm_digital(struct snd_mixart *chip) if ((err = snd_pcm_new(chip->card, name, MIXART_PCM_DIGITAL, MIXART_PLAYBACK_STREAMS, MIXART_CAPTURE_STREAMS, &pcm)) < 0) { - snd_printk(KERN_ERR "cannot create the digital pcm %d\n", chip->chip_idx); + dev_err(chip->card->dev, + "cannot create the digital pcm %d\n", chip->chip_idx); return err; } @@ -1014,7 +1051,7 @@ static int snd_mixart_create(struct mixart_mgr *mgr, struct snd_card *card, int chip = kzalloc(sizeof(*chip), GFP_KERNEL); if (! chip) { - snd_printk(KERN_ERR "cannot allocate chip\n"); + dev_err(card->dev, "cannot allocate chip\n"); return -ENOMEM; } @@ -1028,8 +1065,6 @@ static int snd_mixart_create(struct mixart_mgr *mgr, struct snd_card *card, int } mgr->chip[idx] = chip; - snd_card_set_dev(card, &mgr->pci->dev); - return 0; } @@ -1073,7 +1108,7 @@ static int snd_mixart_free(struct mixart_mgr *mgr) /* reset board if some firmware was loaded */ if(mgr->dsp_loaded) { snd_mixart_reset_board(mgr); - snd_printdd("reset miXart !\n"); + dev_dbg(&mgr->pci->dev, "reset miXart !\n"); } /* release the i/o ports */ @@ -1234,7 +1269,8 @@ static int snd_mixart_probe(struct pci_dev *pci, /* check if we can restrict PCI DMA transfers to 32 bits */ if (pci_set_dma_mask(pci, DMA_BIT_MASK(32)) < 0) { - snd_printk(KERN_ERR "architecture does not support 32bit PCI busmaster DMA\n"); + dev_err(&pci->dev, + "architecture does not support 32bit PCI busmaster DMA\n"); pci_disable_device(pci); return -ENXIO; } @@ -1260,7 +1296,7 @@ static int snd_mixart_probe(struct pci_dev *pci, mgr->mem[i].phys = pci_resource_start(pci, i); mgr->mem[i].virt = pci_ioremap_bar(pci, i); if (!mgr->mem[i].virt) { - printk(KERN_ERR "unable to remap resource 0x%lx\n", + dev_err(&pci->dev, "unable to remap resource 0x%lx\n", mgr->mem[i].phys); snd_mixart_free(mgr); return -EBUSY; @@ -1269,7 +1305,7 @@ static int snd_mixart_probe(struct pci_dev *pci, if (request_irq(pci->irq, snd_mixart_interrupt, IRQF_SHARED, KBUILD_MODNAME, mgr)) { - snd_printk(KERN_ERR "unable to grab IRQ %d\n", pci->irq); + dev_err(&pci->dev, "unable to grab IRQ %d\n", pci->irq); snd_mixart_free(mgr); return -EBUSY; } @@ -1308,10 +1344,11 @@ static int snd_mixart_probe(struct pci_dev *pci, else idx = index[dev] + i; snprintf(tmpid, sizeof(tmpid), "%s-%d", id[dev] ? id[dev] : "MIXART", i); - err = snd_card_create(idx, tmpid, THIS_MODULE, 0, &card); + err = snd_card_new(&pci->dev, idx, tmpid, THIS_MODULE, + 0, &card); if (err < 0) { - snd_printk(KERN_ERR "cannot allocate the card %d\n", i); + dev_err(&pci->dev, "cannot allocate the card %d\n", i); snd_mixart_free(mgr); return err; } diff --git a/sound/pci/mixart/mixart_core.c b/sound/pci/mixart/mixart_core.c index 3df0f530f67..71f4bdcc405 100644 --- a/sound/pci/mixart/mixart_core.c +++ b/sound/pci/mixart/mixart_core.c @@ -22,6 +22,7 @@ #include <linux/interrupt.h> #include <linux/mutex.h> +#include <linux/pci.h> #include <asm/io.h> #include <sound/core.h> @@ -94,7 +95,8 @@ static int get_msg(struct mixart_mgr *mgr, struct mixart_msg *resp, if( (size < MSG_DESCRIPTOR_SIZE) || (resp->size < (size - MSG_DESCRIPTOR_SIZE))) { err = -EINVAL; - snd_printk(KERN_ERR "problem with response size = %d\n", size); + dev_err(&mgr->pci->dev, + "problem with response size = %d\n", size); goto _clean_exit; } size -= MSG_DESCRIPTOR_SIZE; @@ -161,7 +163,7 @@ static int send_msg( struct mixart_mgr *mgr, headptr = readl_be(MIXART_MEM(mgr, MSG_INBOUND_FREE_HEAD)); if (tailptr == headptr) { - snd_printk(KERN_ERR "error: no message frame available\n"); + dev_err(&mgr->pci->dev, "error: no message frame available\n"); return -EBUSY; } @@ -265,7 +267,8 @@ int snd_mixart_send_msg(struct mixart_mgr *mgr, struct mixart_msg *request, int if (! timeout) { /* error - no ack */ mutex_unlock(&mgr->msg_mutex); - snd_printk(KERN_ERR "error: no response on msg %x\n", msg_frame); + dev_err(&mgr->pci->dev, + "error: no response on msg %x\n", msg_frame); return -EIO; } @@ -278,7 +281,7 @@ int snd_mixart_send_msg(struct mixart_mgr *mgr, struct mixart_msg *request, int err = get_msg(mgr, &resp, msg_frame); if( request->message_id != resp.message_id ) - snd_printk(KERN_ERR "RESPONSE ERROR!\n"); + dev_err(&mgr->pci->dev, "RESPONSE ERROR!\n"); mutex_unlock(&mgr->msg_mutex); return err; @@ -321,7 +324,8 @@ int snd_mixart_send_msg_wait_notif(struct mixart_mgr *mgr, if (! timeout) { /* error - no ack */ mutex_unlock(&mgr->msg_mutex); - snd_printk(KERN_ERR "error: notification %x not received\n", notif_event); + dev_err(&mgr->pci->dev, + "error: notification %x not received\n", notif_event); return -EIO; } @@ -378,7 +382,9 @@ void snd_mixart_msg_tasklet(unsigned long arg) resp.size = sizeof(mixart_msg_data); err = get_msg(mgr, &resp, addr); if( err < 0 ) { - snd_printk(KERN_ERR "tasklet: error(%d) reading mf %x\n", err, msg); + dev_err(&mgr->pci->dev, + "tasklet: error(%d) reading mf %x\n", + err, msg); break; } @@ -388,10 +394,13 @@ void snd_mixart_msg_tasklet(unsigned long arg) case MSG_STREAM_STOP_INPUT_STAGE_PACKET: case MSG_STREAM_STOP_OUTPUT_STAGE_PACKET: if(mixart_msg_data[0]) - snd_printk(KERN_ERR "tasklet : error MSG_STREAM_ST***_***PUT_STAGE_PACKET status=%x\n", mixart_msg_data[0]); + dev_err(&mgr->pci->dev, + "tasklet : error MSG_STREAM_ST***_***PUT_STAGE_PACKET status=%x\n", + mixart_msg_data[0]); break; default: - snd_printdd("tasklet received mf(%x) : msg_id(%x) uid(%x, %x) size(%zd)\n", + dev_dbg(&mgr->pci->dev, + "tasklet 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; } @@ -401,7 +410,9 @@ void snd_mixart_msg_tasklet(unsigned long arg) case MSG_TYPE_COMMAND: /* get_msg() necessary */ default: - snd_printk(KERN_ERR "tasklet doesn't know what to do with message %x\n", msg); + dev_err(&mgr->pci->dev, + "tasklet doesn't know what to do with message %x\n", + msg); } /* switch type */ /* decrement counter */ @@ -451,7 +462,9 @@ irqreturn_t snd_mixart_interrupt(int irq, void *dev_id) resp.size = sizeof(mixart_msg_data); err = get_msg(mgr, &resp, msg & ~MSG_TYPE_MASK); if( err < 0 ) { - snd_printk(KERN_ERR "interrupt: error(%d) reading mf %x\n", err, msg); + dev_err(&mgr->pci->dev, + "interrupt: error(%d) reading mf %x\n", + err, msg); break; } @@ -472,7 +485,8 @@ irqreturn_t snd_mixart_interrupt(int irq, void *dev_id) struct mixart_stream *stream; if ((chip_number >= mgr->num_cards) || (pcm_number >= MIXART_PCM_TOTAL) || (sub_number >= MIXART_PLAYBACK_STREAMS)) { - snd_printk(KERN_ERR "error MSG_SERVICES_TIMER_NOTIFY buffer_id (%x) pos(%d)\n", + dev_err(&mgr->pci->dev, + "error MSG_SERVICES_TIMER_NOTIFY buffer_id (%x) pos(%d)\n", buffer_id, notify->streams[i].sample_pos_low_part); break; } @@ -524,18 +538,22 @@ irqreturn_t snd_mixart_interrupt(int irq, void *dev_id) } #endif ((char*)mixart_msg_data)[resp.size - 1] = 0; - snd_printdd("MIXART TRACE : %s\n", (char*)mixart_msg_data); + dev_dbg(&mgr->pci->dev, + "MIXART TRACE : %s\n", + (char *)mixart_msg_data); } break; } - snd_printdd("command %x not handled\n", resp.message_id); + dev_dbg(&mgr->pci->dev, "command %x not handled\n", + resp.message_id); break; case MSG_TYPE_NOTIFY: if(msg & MSG_CANCEL_NOTIFY_MASK) { msg &= ~MSG_CANCEL_NOTIFY_MASK; - snd_printk(KERN_ERR "canceled notification %x !\n", msg); + dev_err(&mgr->pci->dev, + "canceled notification %x !\n", msg); } /* no break, continue ! */ case MSG_TYPE_ANSWER: @@ -556,7 +574,8 @@ irqreturn_t snd_mixart_interrupt(int irq, void *dev_id) break; case MSG_TYPE_REQUEST: default: - snd_printdd("interrupt received request %x\n", msg); + dev_dbg(&mgr->pci->dev, + "interrupt received request %x\n", msg); /* TODO : are there things to do here ? */ break; } /* switch on msg type */ diff --git a/sound/pci/mixart/mixart_hwdep.c b/sound/pci/mixart/mixart_hwdep.c index ece1f831c16..581e1e74863 100644 --- a/sound/pci/mixart/mixart_hwdep.c +++ b/sound/pci/mixart/mixart_hwdep.c @@ -165,7 +165,8 @@ static int mixart_enum_connectors(struct mixart_mgr *mgr) err = snd_mixart_send_msg(mgr, &request, sizeof(*connector), connector); if((err < 0) || (connector->error_code) || (connector->uid_count > MIXART_MAX_PHYS_CONNECTORS)) { - snd_printk(KERN_ERR "error MSG_SYSTEM_ENUM_PLAY_CONNECTOR\n"); + dev_err(&mgr->pci->dev, + "error MSG_SYSTEM_ENUM_PLAY_CONNECTOR\n"); err = -EINVAL; goto __error; } @@ -184,7 +185,7 @@ static int mixart_enum_connectors(struct mixart_mgr *mgr) pipe->uid_left_connector = connector->uid[k]; /* even */ } - /* snd_printk(KERN_DEBUG "playback connector[%d].object_id = %x\n", k, connector->uid[k].object_id); */ + /* dev_dbg(&mgr->pci->dev, "playback connector[%d].object_id = %x\n", k, connector->uid[k].object_id); */ /* TODO: really need send_msg MSG_CONNECTOR_GET_AUDIO_INFO for each connector ? perhaps for analog level caps ? */ request.message_id = MSG_CONNECTOR_GET_AUDIO_INFO; @@ -194,10 +195,11 @@ static int mixart_enum_connectors(struct mixart_mgr *mgr) err = snd_mixart_send_msg(mgr, &request, sizeof(*audio_info), audio_info); if( err < 0 ) { - snd_printk(KERN_ERR "error MSG_CONNECTOR_GET_AUDIO_INFO\n"); + dev_err(&mgr->pci->dev, + "error MSG_CONNECTOR_GET_AUDIO_INFO\n"); goto __error; } - /*snd_printk(KERN_DEBUG "play analog_info.analog_level_present = %x\n", audio_info->info.analog_info.analog_level_present);*/ + /*dev_dbg(&mgr->pci->dev, "play analog_info.analog_level_present = %x\n", audio_info->info.analog_info.analog_level_present);*/ } request.message_id = MSG_SYSTEM_ENUM_RECORD_CONNECTOR; @@ -207,7 +209,8 @@ static int mixart_enum_connectors(struct mixart_mgr *mgr) err = snd_mixart_send_msg(mgr, &request, sizeof(*connector), connector); if((err < 0) || (connector->error_code) || (connector->uid_count > MIXART_MAX_PHYS_CONNECTORS)) { - snd_printk(KERN_ERR "error MSG_SYSTEM_ENUM_RECORD_CONNECTOR\n"); + dev_err(&mgr->pci->dev, + "error MSG_SYSTEM_ENUM_RECORD_CONNECTOR\n"); err = -EINVAL; goto __error; } @@ -226,7 +229,7 @@ static int mixart_enum_connectors(struct mixart_mgr *mgr) pipe->uid_left_connector = connector->uid[k]; /* even */ } - /* snd_printk(KERN_DEBUG "capture connector[%d].object_id = %x\n", k, connector->uid[k].object_id); */ + /* dev_dbg(&mgr->pci->dev, "capture connector[%d].object_id = %x\n", k, connector->uid[k].object_id); */ /* TODO: really need send_msg MSG_CONNECTOR_GET_AUDIO_INFO for each connector ? perhaps for analog level caps ? */ request.message_id = MSG_CONNECTOR_GET_AUDIO_INFO; @@ -236,10 +239,11 @@ static int mixart_enum_connectors(struct mixart_mgr *mgr) err = snd_mixart_send_msg(mgr, &request, sizeof(*audio_info), audio_info); if( err < 0 ) { - snd_printk(KERN_ERR "error MSG_CONNECTOR_GET_AUDIO_INFO\n"); + dev_err(&mgr->pci->dev, + "error MSG_CONNECTOR_GET_AUDIO_INFO\n"); goto __error; } - /*snd_printk(KERN_DEBUG "rec analog_info.analog_level_present = %x\n", audio_info->info.analog_info.analog_level_present);*/ + /*dev_dbg(&mgr->pci->dev, "rec analog_info.analog_level_present = %x\n", audio_info->info.analog_info.analog_level_present);*/ } err = 0; @@ -272,7 +276,9 @@ static int mixart_enum_physio(struct mixart_mgr *mgr) err = snd_mixart_send_msg(mgr, &request, sizeof(console_mgr), &console_mgr); if( (err < 0) || (console_mgr.error_code != 0) ) { - snd_printk(KERN_DEBUG "error MSG_CONSOLE_GET_CLOCK_UID : err=%x\n", console_mgr.error_code); + dev_dbg(&mgr->pci->dev, + "error MSG_CONSOLE_GET_CLOCK_UID : err=%x\n", + console_mgr.error_code); return -EINVAL; } @@ -286,7 +292,9 @@ static int mixart_enum_physio(struct mixart_mgr *mgr) err = snd_mixart_send_msg(mgr, &request, sizeof(phys_io), &phys_io); if( (err < 0) || ( phys_io.error_code != 0 ) ) { - snd_printk(KERN_ERR "error MSG_SYSTEM_ENUM_PHYSICAL_IO err(%x) error_code(%x)\n", err, phys_io.error_code ); + dev_err(&mgr->pci->dev, + "error MSG_SYSTEM_ENUM_PHYSICAL_IO err(%x) error_code(%x)\n", + err, phys_io.error_code); return -EINVAL; } @@ -322,7 +330,7 @@ static int mixart_first_init(struct mixart_mgr *mgr) /* this command has no data. response is a 32 bit status */ err = snd_mixart_send_msg(mgr, &request, sizeof(k), &k); if( (err < 0) || (k != 0) ) { - snd_printk(KERN_ERR "error MSG_SYSTEM_SEND_SYNCHRO_CMD\n"); + dev_err(&mgr->pci->dev, "error MSG_SYSTEM_SEND_SYNCHRO_CMD\n"); return err == 0 ? -EINVAL : err; } @@ -348,7 +356,7 @@ static int mixart_dsp_load(struct mixart_mgr* mgr, int index, const struct firmw /* motherboard xilinx status 5 will say that the board is performing a reset */ if (status_xilinx == 5) { - snd_printk(KERN_ERR "miXart is resetting !\n"); + dev_err(&mgr->pci->dev, "miXart is resetting !\n"); return -EAGAIN; /* try again later */ } @@ -357,12 +365,13 @@ static int mixart_dsp_load(struct mixart_mgr* mgr, int index, const struct firmw /* xilinx already loaded ? */ if (status_xilinx == 4) { - snd_printk(KERN_DEBUG "xilinx is already loaded !\n"); + dev_dbg(&mgr->pci->dev, "xilinx is already loaded !\n"); return 0; } /* the status should be 0 == "idle" */ if (status_xilinx != 0) { - snd_printk(KERN_ERR "xilinx load error ! status = %d\n", + dev_err(&mgr->pci->dev, + "xilinx load error ! status = %d\n", status_xilinx); return -EIO; /* modprob -r may help ? */ } @@ -393,13 +402,14 @@ static int mixart_dsp_load(struct mixart_mgr* mgr, int index, const struct firmw case MIXART_MOTHERBOARD_ELF_INDEX: if (status_elf == 4) { - snd_printk(KERN_DEBUG "elf file already loaded !\n"); + dev_dbg(&mgr->pci->dev, "elf file already loaded !\n"); return 0; } /* the status should be 0 == "idle" */ if (status_elf != 0) { - snd_printk(KERN_ERR "elf load error ! status = %d\n", + dev_err(&mgr->pci->dev, + "elf load error ! status = %d\n", status_elf); return -EIO; /* modprob -r may help ? */ } @@ -407,7 +417,7 @@ static int mixart_dsp_load(struct mixart_mgr* mgr, int index, const struct firmw /* wait for xilinx status == 4 */ err = mixart_wait_nice_for_register_value( mgr, MIXART_PSEUDOREG_MXLX_STATUS_OFFSET, 1, 4, 500); /* 5sec */ if (err < 0) { - snd_printk(KERN_ERR "xilinx was not loaded or " + dev_err(&mgr->pci->dev, "xilinx was not loaded or " "could not be started\n"); return err; } @@ -429,7 +439,7 @@ static int mixart_dsp_load(struct mixart_mgr* mgr, int index, const struct firmw /* wait for elf status == 4 */ err = mixart_wait_nice_for_register_value( mgr, MIXART_PSEUDOREG_ELF_STATUS_OFFSET, 1, 4, 300); /* 3sec */ if (err < 0) { - snd_printk(KERN_ERR "elf could not be started\n"); + dev_err(&mgr->pci->dev, "elf could not be started\n"); return err; } @@ -443,7 +453,7 @@ static int mixart_dsp_load(struct mixart_mgr* mgr, int index, const struct firmw /* elf and xilinx should be loaded */ if (status_elf != 4 || status_xilinx != 4) { - printk(KERN_ERR "xilinx or elf not " + dev_err(&mgr->pci->dev, "xilinx or elf not " "successfully loaded\n"); return -EIO; /* modprob -r may help ? */ } @@ -451,7 +461,7 @@ static int mixart_dsp_load(struct mixart_mgr* mgr, int index, const struct firmw /* wait for daughter detection != 0 */ err = mixart_wait_nice_for_register_value( mgr, MIXART_PSEUDOREG_DBRD_PRESENCE_OFFSET, 0, 0, 30); /* 300msec */ if (err < 0) { - snd_printk(KERN_ERR "error starting elf file\n"); + dev_err(&mgr->pci->dev, "error starting elf file\n"); return err; } @@ -467,7 +477,8 @@ static int mixart_dsp_load(struct mixart_mgr* mgr, int index, const struct firmw /* daughter should be idle */ if (status_daught != 0) { - printk(KERN_ERR "daughter load error ! status = %d\n", + dev_err(&mgr->pci->dev, + "daughter load error ! status = %d\n", status_daught); return -EIO; /* modprob -r may help ? */ } @@ -487,7 +498,7 @@ static int mixart_dsp_load(struct mixart_mgr* mgr, int index, const struct firmw /* wait for status == 2 */ err = mixart_wait_nice_for_register_value( mgr, MIXART_PSEUDOREG_DXLX_STATUS_OFFSET, 1, 2, 30); /* 300msec */ if (err < 0) { - snd_printk(KERN_ERR "daughter board load error\n"); + dev_err(&mgr->pci->dev, "daughter board load error\n"); return err; } @@ -509,7 +520,7 @@ static int mixart_dsp_load(struct mixart_mgr* mgr, int index, const struct firmw /* wait for daughter status == 3 */ err = mixart_wait_nice_for_register_value( mgr, MIXART_PSEUDOREG_DXLX_STATUS_OFFSET, 1, 3, 300); /* 3sec */ if (err < 0) { - snd_printk(KERN_ERR + dev_err(&mgr->pci->dev, "daughter board could not be initialised\n"); return err; } @@ -520,7 +531,7 @@ static int mixart_dsp_load(struct mixart_mgr* mgr, int index, const struct firmw /* first communication with embedded */ err = mixart_first_init(mgr); if (err < 0) { - snd_printk(KERN_ERR "miXart could not be set up\n"); + dev_err(&mgr->pci->dev, "miXart could not be set up\n"); return err; } @@ -540,7 +551,8 @@ static int mixart_dsp_load(struct mixart_mgr* mgr, int index, const struct firmw return err; } - snd_printdd("miXart firmware downloaded and successfully set up\n"); + dev_dbg(&mgr->pci->dev, + "miXart firmware downloaded and successfully set up\n"); return 0; } @@ -559,7 +571,8 @@ int snd_mixart_setup_firmware(struct mixart_mgr *mgr) for (i = 0; i < 3; i++) { sprintf(path, "mixart/%s", fw_files[i]); if (request_firmware(&fw_entry, path, &mgr->pci->dev)) { - snd_printk(KERN_ERR "miXart: can't load firmware %s\n", path); + dev_err(&mgr->pci->dev, + "miXart: can't load firmware %s\n", path); return -ENOENT; } /* fake hwdep dsp record */ diff --git a/sound/pci/mixart/mixart_mixer.c b/sound/pci/mixart/mixart_mixer.c index 3ba6174c3df..24a1955b8c2 100644 --- a/sound/pci/mixart/mixart_mixer.c +++ b/sound/pci/mixart/mixart_mixer.c @@ -329,7 +329,9 @@ static int mixart_update_analog_audio_level(struct snd_mixart* chip, int is_capt err = snd_mixart_send_msg(chip->mgr, &request, sizeof(resp), &resp); if((err<0) || (resp.error_code)) { - snd_printk(KERN_DEBUG "error MSG_PHYSICALIO_SET_LEVEL card(%d) is_capture(%d) error_code(%x)\n", chip->chip_idx, is_capture, resp.error_code); + dev_dbg(chip->card->dev, + "error MSG_PHYSICALIO_SET_LEVEL card(%d) is_capture(%d) error_code(%x)\n", + chip->chip_idx, is_capture, resp.error_code); return -EINVAL; } return 0; @@ -762,7 +764,9 @@ int mixart_update_playback_stream_level(struct snd_mixart* chip, int is_aes, int err = snd_mixart_send_msg(chip->mgr, &request, sizeof(status), &status); if((err<0) || status) { - snd_printk(KERN_DEBUG "error MSG_STREAM_SET_OUT_STREAM_LEVEL card(%d) status(%x)\n", chip->chip_idx, status); + dev_dbg(chip->card->dev, + "error MSG_STREAM_SET_OUT_STREAM_LEVEL card(%d) status(%x)\n", + chip->chip_idx, status); return -EINVAL; } return 0; @@ -805,7 +809,9 @@ int mixart_update_capture_stream_level(struct snd_mixart* chip, int is_aes) err = snd_mixart_send_msg(chip->mgr, &request, sizeof(status), &status); if((err<0) || status) { - snd_printk(KERN_DEBUG "error MSG_STREAM_SET_IN_AUDIO_LEVEL card(%d) status(%x)\n", chip->chip_idx, status); + dev_dbg(chip->card->dev, + "error MSG_STREAM_SET_IN_AUDIO_LEVEL card(%d) status(%x)\n", + chip->chip_idx, status); return -EINVAL; } return 0; @@ -977,7 +983,9 @@ static int mixart_update_monitoring(struct snd_mixart* chip, int channel) err = snd_mixart_send_msg(chip->mgr, &request, sizeof(resp), &resp); if((err<0) || resp) { - snd_printk(KERN_DEBUG "error MSG_CONNECTOR_SET_OUT_AUDIO_LEVEL card(%d) resp(%x)\n", chip->chip_idx, resp); + dev_dbg(chip->card->dev, + "error MSG_CONNECTOR_SET_OUT_AUDIO_LEVEL card(%d) resp(%x)\n", + chip->chip_idx, resp); return -EINVAL; } return 0; diff --git a/sound/pci/nm256/nm256.c b/sound/pci/nm256/nm256.c index fe79fff4c6d..ddc60215cc1 100644 --- a/sound/pci/nm256/nm256.c +++ b/sound/pci/nm256/nm256.c @@ -318,7 +318,8 @@ snd_nm256_write_buffer(struct nm256 *chip, void *src, int offset, int size) offset -= chip->buffer_start; #ifdef CONFIG_SND_DEBUG if (offset < 0 || offset >= chip->buffer_size) { - snd_printk(KERN_ERR "write_buffer invalid offset = %d size = %d\n", + dev_err(chip->card->dev, + "write_buffer invalid offset = %d size = %d\n", offset, size); return; } @@ -366,7 +367,8 @@ snd_nm256_load_coefficient(struct nm256 *chip, int stream, int number) NM_RECORD_REG_OFFSET : NM_PLAYBACK_REG_OFFSET); if (snd_nm256_readb(chip, poffset) & 1) { - snd_printd("NM256: Engine was enabled while loading coefficients!\n"); + dev_dbg(chip->card->dev, + "NM256: Engine was enabled while loading coefficients!\n"); return; } @@ -466,7 +468,8 @@ static int snd_nm256_acquire_irq(struct nm256 *chip) if (chip->irq < 0) { if (request_irq(chip->pci->irq, chip->interrupt, IRQF_SHARED, KBUILD_MODNAME, chip)) { - snd_printk(KERN_ERR "unable to grab IRQ %d\n", chip->pci->irq); + dev_err(chip->card->dev, + "unable to grab IRQ %d\n", chip->pci->irq); mutex_unlock(&chip->irq_mutex); return -EBUSY; } @@ -1039,7 +1042,7 @@ snd_nm256_interrupt(int irq, void *dev_id) if (status & NM_MISC_INT_1) { status &= ~NM_MISC_INT_1; NM_ACK_INT(chip, NM_MISC_INT_1); - snd_printd("NM256: Got misc interrupt #1\n"); + dev_dbg(chip->card->dev, "NM256: Got misc interrupt #1\n"); snd_nm256_writew(chip, NM_INT_REG, 0x8000); cbyte = snd_nm256_readb(chip, 0x400); snd_nm256_writeb(chip, 0x400, cbyte | 2); @@ -1048,14 +1051,15 @@ snd_nm256_interrupt(int irq, void *dev_id) if (status & NM_MISC_INT_2) { status &= ~NM_MISC_INT_2; NM_ACK_INT(chip, NM_MISC_INT_2); - snd_printd("NM256: Got misc interrupt #2\n"); + dev_dbg(chip->card->dev, "NM256: Got misc interrupt #2\n"); cbyte = snd_nm256_readb(chip, 0x400); snd_nm256_writeb(chip, 0x400, cbyte & ~2); } /* Unknown interrupt. */ if (status) { - snd_printd("NM256: Fire in the hole! Unknown status 0x%x\n", + dev_dbg(chip->card->dev, + "NM256: Fire in the hole! Unknown status 0x%x\n", status); /* Pray. */ NM_ACK_INT(chip, status); @@ -1104,7 +1108,7 @@ snd_nm256_interrupt_zx(int irq, void *dev_id) if (status & NM2_MISC_INT_1) { status &= ~NM2_MISC_INT_1; NM2_ACK_INT(chip, NM2_MISC_INT_1); - snd_printd("NM256: Got misc interrupt #1\n"); + dev_dbg(chip->card->dev, "NM256: Got misc interrupt #1\n"); cbyte = snd_nm256_readb(chip, 0x400); snd_nm256_writeb(chip, 0x400, cbyte | 2); } @@ -1112,14 +1116,15 @@ snd_nm256_interrupt_zx(int irq, void *dev_id) if (status & NM2_MISC_INT_2) { status &= ~NM2_MISC_INT_2; NM2_ACK_INT(chip, NM2_MISC_INT_2); - snd_printd("NM256: Got misc interrupt #2\n"); + dev_dbg(chip->card->dev, "NM256: Got misc interrupt #2\n"); cbyte = snd_nm256_readb(chip, 0x400); snd_nm256_writeb(chip, 0x400, cbyte & ~2); } /* Unknown interrupt. */ if (status) { - snd_printd("NM256: Fire in the hole! Unknown status 0x%x\n", + dev_dbg(chip->card->dev, + "NM256: Fire in the hole! Unknown status 0x%x\n", status); /* Pray. */ NM2_ACK_INT(chip, status); @@ -1245,7 +1250,7 @@ snd_nm256_ac97_write(struct snd_ac97 *ac97, return; } } - snd_printd("nm256: ac97 codec not ready..\n"); + dev_dbg(chip->card->dev, "nm256: ac97 codec not ready..\n"); } /* static resolution table */ @@ -1347,7 +1352,8 @@ snd_nm256_peek_for_sig(struct nm256 *chip) temp = ioremap_nocache(chip->buffer_addr + chip->buffer_end - 0x400, 16); if (temp == NULL) { - snd_printk(KERN_ERR "Unable to scan for card signature in video RAM\n"); + dev_err(chip->card->dev, + "Unable to scan for card signature in video RAM\n"); return -EBUSY; } @@ -1361,12 +1367,14 @@ snd_nm256_peek_for_sig(struct nm256 *chip) if (pointer == 0xffffffff || pointer < chip->buffer_size || pointer > chip->buffer_end) { - snd_printk(KERN_ERR "invalid signature found: 0x%x\n", pointer); + dev_err(chip->card->dev, + "invalid signature found: 0x%x\n", pointer); iounmap(temp); return -ENODEV; } else { pointer_found = pointer; - printk(KERN_INFO "nm256: found card signature in video RAM: 0x%x\n", + dev_info(chip->card->dev, + "found card signature in video RAM: 0x%x\n", pointer); } } @@ -1411,8 +1419,7 @@ static int nm256_resume(struct device *dev) pci_set_power_state(pci, PCI_D0); pci_restore_state(pci); if (pci_enable_device(pci) < 0) { - printk(KERN_ERR "nm256: pci_enable_device failed, " - "disabling device\n"); + dev_err(dev, "pci_enable_device failed, disabling device\n"); snd_card_disconnect(card); return -EIO; } @@ -1520,14 +1527,15 @@ snd_nm256_create(struct snd_card *card, struct pci_dev *pci, chip->res_cport = request_mem_region(chip->cport_addr, NM_PORT2_SIZE, card->driver); if (chip->res_cport == NULL) { - snd_printk(KERN_ERR "memory region 0x%lx (size 0x%x) busy\n", + dev_err(card->dev, "memory region 0x%lx (size 0x%x) busy\n", chip->cport_addr, NM_PORT2_SIZE); err = -EBUSY; goto __error; } chip->cport = ioremap_nocache(chip->cport_addr, NM_PORT2_SIZE); if (chip->cport == NULL) { - snd_printk(KERN_ERR "unable to map control port %lx\n", chip->cport_addr); + dev_err(card->dev, "unable to map control port %lx\n", + chip->cport_addr); err = -ENOMEM; goto __error; } @@ -1537,12 +1545,14 @@ snd_nm256_create(struct snd_card *card, struct pci_dev *pci, pval = snd_nm256_readw(chip, NM_MIXER_PRESENCE); if ((pval & NM_PRESENCE_MASK) != NM_PRESENCE_VALUE) { if (! force_ac97) { - printk(KERN_ERR "nm256: no ac97 is found!\n"); - printk(KERN_ERR " force the driver to load by " - "passing in the module parameter\n"); - printk(KERN_ERR " force_ac97=1\n"); - printk(KERN_ERR " or try sb16, opl3sa2, or " - "cs423x drivers instead.\n"); + dev_err(card->dev, + "no ac97 is found!\n"); + dev_err(card->dev, + "force the driver to load by passing in the module parameter\n"); + dev_err(card->dev, + " force_ac97=1\n"); + dev_err(card->dev, + "or try sb16, opl3sa2, or cs423x drivers instead.\n"); err = -ENXIO; goto __error; } @@ -1581,14 +1591,14 @@ snd_nm256_create(struct snd_card *card, struct pci_dev *pci, chip->buffer_start = chip->buffer_end - chip->buffer_size; chip->buffer_addr += chip->buffer_start; - printk(KERN_INFO "nm256: Mapping port 1 from 0x%x - 0x%x\n", + dev_info(card->dev, "Mapping port 1 from 0x%x - 0x%x\n", chip->buffer_start, chip->buffer_end); chip->res_buffer = request_mem_region(chip->buffer_addr, chip->buffer_size, card->driver); if (chip->res_buffer == NULL) { - snd_printk(KERN_ERR "nm256: buffer 0x%lx (size 0x%x) busy\n", + dev_err(card->dev, "buffer 0x%lx (size 0x%x) busy\n", chip->buffer_addr, chip->buffer_size); err = -EBUSY; goto __error; @@ -1596,7 +1606,8 @@ snd_nm256_create(struct snd_card *card, struct pci_dev *pci, chip->buffer = ioremap_nocache(chip->buffer_addr, chip->buffer_size); if (chip->buffer == NULL) { err = -ENOMEM; - snd_printk(KERN_ERR "unable to map ring buffer at %lx\n", chip->buffer_addr); + dev_err(card->dev, "unable to map ring buffer at %lx\n", + chip->buffer_addr); goto __error; } @@ -1626,8 +1637,6 @@ snd_nm256_create(struct snd_card *card, struct pci_dev *pci, if ((err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops)) < 0) goto __error; - snd_card_set_dev(card, &pci->dev); - *chip_ret = chip; return 0; @@ -1660,12 +1669,12 @@ static int snd_nm256_probe(struct pci_dev *pci, q = snd_pci_quirk_lookup(pci, nm256_quirks); if (q) { - snd_printdd(KERN_INFO "nm256: Enabled quirk for %s.\n", + dev_dbg(&pci->dev, "Enabled quirk for %s.\n", snd_pci_quirk_name(q)); switch (q->value) { case NM_BLACKLISTED: - printk(KERN_INFO "nm256: The device is blacklisted. " - "Loading stopped\n"); + dev_info(&pci->dev, + "The device is blacklisted. Loading stopped\n"); return -ENODEV; case NM_RESET_WORKAROUND_2: reset_workaround_2 = 1; @@ -1676,7 +1685,7 @@ static int snd_nm256_probe(struct pci_dev *pci, } } - err = snd_card_create(index, id, THIS_MODULE, 0, &card); + err = snd_card_new(&pci->dev, index, id, THIS_MODULE, 0, &card); if (err < 0) return err; @@ -1691,7 +1700,7 @@ static int snd_nm256_probe(struct pci_dev *pci, strcpy(card->driver, "NM256XL+"); break; default: - snd_printk(KERN_ERR "invalid device id 0x%x\n", pci->device); + dev_err(&pci->dev, "invalid device id 0x%x\n", pci->device); snd_card_free(card); return -EINVAL; } @@ -1714,12 +1723,12 @@ static int snd_nm256_probe(struct pci_dev *pci, card->private_data = chip; if (reset_workaround) { - snd_printdd(KERN_INFO "nm256: reset_workaround activated\n"); + dev_dbg(&pci->dev, "reset_workaround activated\n"); chip->reset_workaround = 1; } if (reset_workaround_2) { - snd_printdd(KERN_INFO "nm256: reset_workaround_2 activated\n"); + dev_dbg(&pci->dev, "reset_workaround_2 activated\n"); chip->reset_workaround_2 = 1; } diff --git a/sound/pci/oxygen/oxygen_io.c b/sound/pci/oxygen/oxygen_io.c index 3274907189f..4b8a32c37e3 100644 --- a/sound/pci/oxygen/oxygen_io.c +++ b/sound/pci/oxygen/oxygen_io.c @@ -147,7 +147,7 @@ void oxygen_write_ac97(struct oxygen *chip, unsigned int codec, return; } } - snd_printk(KERN_ERR "AC'97 write timeout\n"); + dev_err(chip->card->dev, "AC'97 write timeout\n"); } EXPORT_SYMBOL(oxygen_write_ac97); @@ -179,7 +179,7 @@ u16 oxygen_read_ac97(struct oxygen *chip, unsigned int codec, reg ^= 0xffff; } } - snd_printk(KERN_ERR "AC'97 read timeout on codec %u\n", codec); + dev_err(chip->card->dev, "AC'97 read timeout on codec %u\n", codec); return 0; } EXPORT_SYMBOL(oxygen_read_ac97); @@ -208,7 +208,7 @@ static int oxygen_wait_spi(struct oxygen *chip) OXYGEN_SPI_BUSY) == 0) return 0; } - snd_printk(KERN_ERR "oxygen: SPI wait timeout\n"); + dev_err(chip->card->dev, "oxygen: SPI wait timeout\n"); return -EIO; } @@ -288,5 +288,5 @@ void oxygen_write_eeprom(struct oxygen *chip, unsigned int index, u16 value) & OXYGEN_EEPROM_BUSY)) return; } - snd_printk(KERN_ERR "EEPROM write timeout\n"); + dev_err(chip->card->dev, "EEPROM write timeout\n"); } diff --git a/sound/pci/oxygen/oxygen_lib.c b/sound/pci/oxygen/oxygen_lib.c index b0cb48adddc..b67e3060247 100644 --- a/sound/pci/oxygen/oxygen_lib.c +++ b/sound/pci/oxygen/oxygen_lib.c @@ -313,7 +313,7 @@ static void oxygen_restore_eeprom(struct oxygen *chip, oxygen_clear_bits8(chip, OXYGEN_MISC, OXYGEN_MISC_WRITE_PCI_SUBID); - snd_printk(KERN_INFO "EEPROM ID restored\n"); + dev_info(chip->card->dev, "EEPROM ID restored\n"); } } @@ -595,7 +595,8 @@ int oxygen_pci_probe(struct pci_dev *pci, int index, char *id, const struct pci_device_id *pci_id; int err; - err = snd_card_create(index, id, owner, sizeof(*chip), &card); + err = snd_card_new(&pci->dev, index, id, owner, + sizeof(*chip), &card); if (err < 0) return err; @@ -616,13 +617,13 @@ int oxygen_pci_probe(struct pci_dev *pci, int index, char *id, err = pci_request_regions(pci, DRIVER); if (err < 0) { - snd_printk(KERN_ERR "cannot reserve PCI resources\n"); + dev_err(card->dev, "cannot reserve PCI resources\n"); goto err_pci_enable; } if (!(pci_resource_flags(pci, 0) & IORESOURCE_IO) || pci_resource_len(pci, 0) < OXYGEN_IO_SIZE) { - snd_printk(KERN_ERR "invalid PCI I/O range\n"); + dev_err(card->dev, "invalid PCI I/O range\n"); err = -ENXIO; goto err_pci_regions; } @@ -648,7 +649,6 @@ int oxygen_pci_probe(struct pci_dev *pci, int index, char *id, } pci_set_master(pci); - snd_card_set_dev(card, &pci->dev); card->private_free = oxygen_card_free; configure_pcie_bridge(pci); @@ -658,7 +658,7 @@ int oxygen_pci_probe(struct pci_dev *pci, int index, char *id, err = request_irq(pci->irq, oxygen_interrupt, IRQF_SHARED, KBUILD_MODNAME, chip); if (err < 0) { - snd_printk(KERN_ERR "cannot grab interrupt %d\n", pci->irq); + dev_err(card->dev, "cannot grab interrupt %d\n", pci->irq); goto err_card; } chip->irq = pci->irq; @@ -796,7 +796,7 @@ static int oxygen_pci_resume(struct device *dev) pci_set_power_state(pci, PCI_D0); pci_restore_state(pci); if (pci_enable_device(pci) < 0) { - snd_printk(KERN_ERR "cannot reenable device"); + dev_err(dev, "cannot reenable device"); snd_card_disconnect(card); return -EIO; } diff --git a/sound/pci/oxygen/xonar_hdmi.c b/sound/pci/oxygen/xonar_hdmi.c index 136dac6a396..91d92bc32b7 100644 --- a/sound/pci/oxygen/xonar_hdmi.c +++ b/sound/pci/oxygen/xonar_hdmi.c @@ -120,7 +120,7 @@ void xonar_hdmi_uart_input(struct oxygen *chip) if (chip->uart_input_count >= 2 && chip->uart_input[chip->uart_input_count - 2] == 'O' && chip->uart_input[chip->uart_input_count - 1] == 'K') { - printk(KERN_DEBUG "message from HDMI chip received:\n"); + dev_dbg(chip->card->dev, "message from HDMI chip received:\n"); print_hex_dump_bytes("", DUMP_PREFIX_OFFSET, chip->uart_input, chip->uart_input_count); chip->uart_input_count = 0; diff --git a/sound/pci/oxygen/xonar_lib.c b/sound/pci/oxygen/xonar_lib.c index 0ebe7f5916f..706b1a42163 100644 --- a/sound/pci/oxygen/xonar_lib.c +++ b/sound/pci/oxygen/xonar_lib.c @@ -56,9 +56,9 @@ static void xonar_ext_power_gpio_changed(struct oxygen *chip) if (has_power != data->has_power) { data->has_power = has_power; if (has_power) { - snd_printk(KERN_NOTICE "power restored\n"); + dev_notice(chip->card->dev, "power restored\n"); } else { - snd_printk(KERN_CRIT + dev_crit(chip->card->dev, "Hey! Don't unplug the power cable!\n"); /* TODO: stop PCMs */ } diff --git a/sound/pci/pcxhr/pcxhr.c b/sound/pci/pcxhr/pcxhr.c index d379b284955..8d09444ff88 100644 --- a/sound/pci/pcxhr/pcxhr.c +++ b/sound/pci/pcxhr/pcxhr.c @@ -284,7 +284,7 @@ static int pcxhr_get_clock_reg(struct pcxhr_mgr *mgr, unsigned int rate, rmh.cmd_len = 3; err = pcxhr_send_msg(mgr, &rmh); if (err < 0) { - snd_printk(KERN_ERR + dev_err(&mgr->pci->dev, "error CMD_ACCESS_IO_WRITE " "for PLL register : %x!\n", err); return err; @@ -357,7 +357,7 @@ static int pcxhr_sub_set_clock(struct pcxhr_mgr *mgr, return err; } /* set the new frequency */ - snd_printdd("clock register : set %x\n", val); + dev_dbg(&mgr->pci->dev, "clock register : set %x\n", val); err = pcxhr_write_io_num_reg_cont(mgr, PCXHR_FREQ_REG_MASK, val, changed); if (err) @@ -380,7 +380,7 @@ static int pcxhr_sub_set_clock(struct pcxhr_mgr *mgr, mgr->codec_speed = speed; /* save new codec speed */ } - snd_printdd("pcxhr_sub_set_clock to %dHz (realfreq=%d)\n", + dev_dbg(&mgr->pci->dev, "pcxhr_sub_set_clock to %dHz (realfreq=%d)\n", rate, realfreq); return 0; } @@ -480,7 +480,7 @@ static int pcxhr_sub_get_external_clock(struct pcxhr_mgr *mgr, case REG_STATUS_SYNC_192000 : rate = 192000; break; default: rate = 0; } - snd_printdd("External clock is at %d Hz\n", rate); + dev_dbg(&mgr->pci->dev, "External clock is at %d Hz\n", rate); *sample_rate = rate; return 0; } @@ -537,8 +537,8 @@ static int pcxhr_set_stream_state(struct pcxhr_stream *stream) err = pcxhr_send_msg(chip->mgr, &rmh); if (err) - snd_printk(KERN_ERR "ERROR pcxhr_set_stream_state err=%x;\n", - err); + dev_err(chip->card->dev, + "ERROR pcxhr_set_stream_state err=%x;\n", err); stream->status = start ? PCXHR_STREAM_STATUS_STARTED : PCXHR_STREAM_STATUS_STOPPED; return err; @@ -628,7 +628,8 @@ static int pcxhr_set_format(struct pcxhr_stream *stream) rmh.cmd[rmh.cmd_len++] = (header & 0xff) << 16; err = pcxhr_send_msg(chip->mgr, &rmh); if (err) - snd_printk(KERN_ERR "ERROR pcxhr_set_format err=%x;\n", err); + dev_err(chip->card->dev, + "ERROR pcxhr_set_format err=%x;\n", err); return err; } @@ -665,7 +666,7 @@ static int pcxhr_update_r_buffer(struct pcxhr_stream *stream) rmh.cmd_len = 4; err = pcxhr_send_msg(chip->mgr, &rmh); if (err) - snd_printk(KERN_ERR + dev_err(chip->card->dev, "ERROR CMD_UPDATE_R_BUFFERS err=%x;\n", err); return err; } @@ -735,11 +736,11 @@ static void pcxhr_trigger_tasklet(unsigned long arg) } if (capture_mask == 0 && playback_mask == 0) { mutex_unlock(&mgr->setup_mutex); - snd_printk(KERN_ERR "pcxhr_trigger_tasklet : no pipes\n"); + dev_err(&mgr->pci->dev, "pcxhr_trigger_tasklet : no pipes\n"); return; } - snd_printdd("pcxhr_trigger_tasklet : " + dev_dbg(&mgr->pci->dev, "pcxhr_trigger_tasklet : " "playback_mask=%x capture_mask=%x\n", playback_mask, capture_mask); @@ -747,7 +748,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); - snd_printk(KERN_ERR "pcxhr_trigger_tasklet : " + dev_err(&mgr->pci->dev, "pcxhr_trigger_tasklet : " "error stop pipes (P%x C%x)\n", playback_mask, capture_mask); return; @@ -792,7 +793,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); - snd_printk(KERN_ERR "pcxhr_trigger_tasklet : " + dev_err(&mgr->pci->dev, "pcxhr_trigger_tasklet : " "error start pipes (P%x C%x)\n", playback_mask, capture_mask); return; @@ -825,7 +826,7 @@ static void pcxhr_trigger_tasklet(unsigned long arg) #ifdef CONFIG_SND_DEBUG_VERBOSE do_gettimeofday(&my_tv2); - snd_printdd("***TRIGGER TASKLET*** TIME = %ld (err = %x)\n", + dev_dbg(&mgr->pci->dev, "***TRIGGER TASKLET*** TIME = %ld (err = %x)\n", (long)(my_tv2.tv_usec - my_tv1.tv_usec), err); #endif } @@ -902,7 +903,7 @@ static int pcxhr_hardware_timer(struct pcxhr_mgr *mgr, int start) } err = pcxhr_send_msg(mgr, &rmh); if (err < 0) - snd_printk(KERN_ERR "error pcxhr_hardware_timer err(%x)\n", + dev_err(&mgr->pci->dev, "error pcxhr_hardware_timer err(%x)\n", err); return err; } @@ -916,7 +917,8 @@ static int pcxhr_prepare(struct snd_pcm_substream *subs) struct pcxhr_mgr *mgr = chip->mgr; int err = 0; - snd_printdd("pcxhr_prepare : period_size(%lx) periods(%x) buffer_size(%lx)\n", + dev_dbg(chip->card->dev, + "pcxhr_prepare : period_size(%lx) periods(%x) buffer_size(%lx)\n", subs->runtime->period_size, subs->runtime->periods, subs->runtime->buffer_size); @@ -1025,11 +1027,11 @@ static int pcxhr_open(struct snd_pcm_substream *subs) runtime->hw = pcxhr_caps; if( subs->stream == SNDRV_PCM_STREAM_PLAYBACK ) { - snd_printdd("pcxhr_open playback chip%d subs%d\n", + dev_dbg(chip->card->dev, "pcxhr_open playback chip%d subs%d\n", chip->chip_idx, subs->number); stream = &chip->playback_stream[subs->number]; } else { - snd_printdd("pcxhr_open capture chip%d subs%d\n", + dev_dbg(chip->card->dev, "pcxhr_open capture chip%d subs%d\n", chip->chip_idx, subs->number); if (mgr->mono_capture) runtime->hw.channels_max = 1; @@ -1039,7 +1041,7 @@ static int pcxhr_open(struct snd_pcm_substream *subs) } if (stream->status != PCXHR_STREAM_STATUS_FREE){ /* streams in use */ - snd_printk(KERN_ERR "pcxhr_open chip%d subs%d in use\n", + dev_err(chip->card->dev, "pcxhr_open chip%d subs%d in use\n", chip->chip_idx, subs->number); mutex_unlock(&mgr->setup_mutex); return -EBUSY; @@ -1105,7 +1107,7 @@ static int pcxhr_close(struct snd_pcm_substream *subs) mutex_lock(&mgr->setup_mutex); - snd_printdd("pcxhr_close chip%d subs%d\n", + dev_dbg(chip->card->dev, "pcxhr_close chip%d subs%d\n", chip->chip_idx, subs->number); /* sample rate released */ @@ -1168,7 +1170,7 @@ int pcxhr_create_pcm(struct snd_pcxhr *chip) if ((err = snd_pcm_new(chip->card, name, 0, chip->nb_streams_play, chip->nb_streams_capt, &pcm)) < 0) { - snd_printk(KERN_ERR "cannot create pcm %s\n", name); + dev_err(chip->card->dev, "cannot create pcm %s\n", name); return err; } pcm->private_data = chip; @@ -1214,7 +1216,7 @@ static int pcxhr_create(struct pcxhr_mgr *mgr, chip = kzalloc(sizeof(*chip), GFP_KERNEL); if (! chip) { - snd_printk(KERN_ERR "cannot allocate chip\n"); + dev_err(card->dev, "cannot allocate chip\n"); return -ENOMEM; } @@ -1239,7 +1241,6 @@ static int pcxhr_create(struct pcxhr_mgr *mgr, } mgr->chip[idx] = chip; - snd_card_set_dev(card, &mgr->pci->dev); return 0; } @@ -1488,7 +1489,7 @@ static int pcxhr_free(struct pcxhr_mgr *mgr) /* reset board if some firmware was loaded */ if(mgr->dsp_loaded) { pcxhr_reset_board(mgr); - snd_printdd("reset pcxhr !\n"); + dev_dbg(&mgr->pci->dev, "reset pcxhr !\n"); } /* release irq */ @@ -1537,8 +1538,8 @@ static int pcxhr_probe(struct pci_dev *pci, /* check if we can restrict PCI DMA transfers to 32 bits */ if (pci_set_dma_mask(pci, DMA_BIT_MASK(32)) < 0) { - snd_printk(KERN_ERR "architecture does not support " - "32bit PCI busmaster DMA\n"); + dev_err(&pci->dev, + "architecture does not support 32bit PCI busmaster DMA\n"); pci_disable_device(pci); return -ENXIO; } @@ -1589,7 +1590,7 @@ static int pcxhr_probe(struct pci_dev *pci, if (request_irq(pci->irq, pcxhr_interrupt, IRQF_SHARED, KBUILD_MODNAME, mgr)) { - snd_printk(KERN_ERR "unable to grab IRQ %d\n", pci->irq); + dev_err(&pci->dev, "unable to grab IRQ %d\n", pci->irq); pcxhr_free(mgr); return -EBUSY; } @@ -1638,10 +1639,11 @@ static int pcxhr_probe(struct pci_dev *pci, snprintf(tmpid, sizeof(tmpid), "%s-%d", id[dev] ? id[dev] : card_name, i); - err = snd_card_create(idx, tmpid, THIS_MODULE, 0, &card); + err = snd_card_new(&pci->dev, idx, tmpid, THIS_MODULE, + 0, &card); if (err < 0) { - snd_printk(KERN_ERR "cannot allocate the card %d\n", i); + dev_err(card->dev, "cannot allocate the card %d\n", i); pcxhr_free(mgr); return err; } diff --git a/sound/pci/pcxhr/pcxhr_core.c b/sound/pci/pcxhr/pcxhr_core.c index 37b431b9b69..df937191860 100644 --- a/sound/pci/pcxhr/pcxhr_core.c +++ b/sound/pci/pcxhr/pcxhr_core.c @@ -23,6 +23,7 @@ #include <linux/delay.h> #include <linux/firmware.h> #include <linux/interrupt.h> +#include <linux/pci.h> #include <asm/io.h> #include <sound/core.h> #include "pcxhr.h" @@ -132,14 +133,14 @@ static int pcxhr_check_reg_bit(struct pcxhr_mgr *mgr, unsigned int reg, *read = PCXHR_INPB(mgr, reg); if ((*read & mask) == bit) { if (i > 100) - snd_printdd("ATTENTION! check_reg(%x) " - "loopcount=%d\n", + dev_dbg(&mgr->pci->dev, + "ATTENTION! check_reg(%x) loopcount=%d\n", reg, i); return 0; } i++; } while (time_after_eq(end_time, jiffies)); - snd_printk(KERN_ERR + dev_err(&mgr->pci->dev, "pcxhr_check_reg_bit: timeout, reg=%x, mask=0x%x, val=%x\n", reg, mask, *read); return -EIO; @@ -216,7 +217,7 @@ static int pcxhr_send_it_dsp(struct pcxhr_mgr *mgr, err = pcxhr_check_reg_bit(mgr, PCXHR_DSP_CVR, PCXHR_CVR_HI08_HC, 0, PCXHR_TIMEOUT_DSP, ®); if (err) { - snd_printk(KERN_ERR "pcxhr_send_it_dsp : TIMEOUT CVR\n"); + dev_err(&mgr->pci->dev, "pcxhr_send_it_dsp : TIMEOUT CVR\n"); return err; } if (itdsp & PCXHR_MASK_IT_MANAGE_HF5) { @@ -227,7 +228,7 @@ static int pcxhr_send_it_dsp(struct pcxhr_mgr *mgr, PCXHR_TIMEOUT_DSP, ®); if (err) { - snd_printk(KERN_ERR + dev_err(&mgr->pci->dev, "pcxhr_send_it_dsp : TIMEOUT HF5\n"); return err; } @@ -294,7 +295,7 @@ int pcxhr_load_xilinx_binary(struct pcxhr_mgr *mgr, */ if(second) { if ((chipsc & PCXHR_CHIPSC_GPI_USERI) == 0) { - snd_printk(KERN_ERR "error loading first xilinx\n"); + dev_err(&mgr->pci->dev, "error loading first xilinx\n"); return -EINVAL; } /* activate second xilinx */ @@ -360,7 +361,7 @@ static int pcxhr_download_dsp(struct pcxhr_mgr *mgr, const struct firmware *dsp) PCXHR_ISR_HI08_TRDY, PCXHR_TIMEOUT_DSP, &dummy); if (err) { - snd_printk(KERN_ERR + dev_err(&mgr->pci->dev, "dsp loading error at position %d\n", i); return err; } @@ -396,7 +397,7 @@ int pcxhr_load_eeprom_binary(struct pcxhr_mgr *mgr, msleep(PCXHR_WAIT_DEFAULT); PCXHR_OUTPB(mgr, PCXHR_DSP_ICR, reg); msleep(PCXHR_WAIT_DEFAULT); - snd_printdd("no need to load eeprom boot\n"); + dev_dbg(&mgr->pci->dev, "no need to load eeprom boot\n"); return 0; } PCXHR_OUTPB(mgr, PCXHR_DSP_ICR, reg); @@ -561,9 +562,9 @@ static int pcxhr_read_rmh_status(struct pcxhr_mgr *mgr, struct pcxhr_rmh *rmh) PCXHR_ISR_HI08_RXDF, PCXHR_TIMEOUT_DSP, ®); if (err) { - snd_printk(KERN_ERR "ERROR RMH stat: " - "ISR:RXDF=1 (ISR = %x; i=%d )\n", - reg, i); + dev_err(&mgr->pci->dev, + "ERROR RMH stat: ISR:RXDF=1 (ISR = %x; i=%d )\n", + reg, i); return err; } /* read data */ @@ -591,13 +592,13 @@ static int pcxhr_read_rmh_status(struct pcxhr_mgr *mgr, struct pcxhr_rmh *rmh) } #ifdef CONFIG_SND_DEBUG_VERBOSE if (rmh->cmd_idx < CMD_LAST_INDEX) - snd_printdd(" stat[%d]=%x\n", i, data); + dev_dbg(&mgr->pci->dev, " stat[%d]=%x\n", i, data); #endif if (i < max_stat_len) rmh->stat[i] = data; } if (rmh->stat_len > max_stat_len) { - snd_printdd("PCXHR : rmh->stat_len=%x too big\n", + dev_dbg(&mgr->pci->dev, "PCXHR : rmh->stat_len=%x too big\n", rmh->stat_len); rmh->stat_len = max_stat_len; } @@ -615,7 +616,8 @@ static int pcxhr_send_msg_nolock(struct pcxhr_mgr *mgr, struct pcxhr_rmh *rmh) return -EINVAL; err = pcxhr_send_it_dsp(mgr, PCXHR_IT_MESSAGE, 1); if (err) { - snd_printk(KERN_ERR "pcxhr_send_message : ED_DSP_CRASHED\n"); + dev_err(&mgr->pci->dev, + "pcxhr_send_message : ED_DSP_CRASHED\n"); return err; } /* wait for chk bit */ @@ -641,7 +643,7 @@ static int pcxhr_send_msg_nolock(struct pcxhr_mgr *mgr, struct pcxhr_rmh *rmh) data &= 0xff7fff; /* MASK_1_WORD_COMMAND */ #ifdef CONFIG_SND_DEBUG_VERBOSE if (rmh->cmd_idx < CMD_LAST_INDEX) - snd_printdd("MSG cmd[0]=%x (%s)\n", + dev_dbg(&mgr->pci->dev, "MSG cmd[0]=%x (%s)\n", data, cmd_names[rmh->cmd_idx]); #endif @@ -671,7 +673,8 @@ static int pcxhr_send_msg_nolock(struct pcxhr_mgr *mgr, struct pcxhr_rmh *rmh) data = rmh->cmd[i]; #ifdef CONFIG_SND_DEBUG_VERBOSE if (rmh->cmd_idx < CMD_LAST_INDEX) - snd_printdd(" cmd[%d]=%x\n", i, data); + dev_dbg(&mgr->pci->dev, + " cmd[%d]=%x\n", i, data); #endif err = pcxhr_check_reg_bit(mgr, PCXHR_DSP_ISR, PCXHR_ISR_HI08_TRDY, @@ -697,14 +700,15 @@ static int pcxhr_send_msg_nolock(struct pcxhr_mgr *mgr, struct pcxhr_rmh *rmh) PCXHR_ISR_HI08_RXDF, PCXHR_TIMEOUT_DSP, ®); if (err) { - snd_printk(KERN_ERR "ERROR RMH: ISR:RXDF=1 (ISR = %x)\n", reg); + dev_err(&mgr->pci->dev, + "ERROR RMH: ISR:RXDF=1 (ISR = %x)\n", reg); return err; } /* read error code */ data = PCXHR_INPB(mgr, PCXHR_DSP_TXH) << 16; data |= PCXHR_INPB(mgr, PCXHR_DSP_TXM) << 8; data |= PCXHR_INPB(mgr, PCXHR_DSP_TXL); - snd_printk(KERN_ERR "ERROR RMH(%d): 0x%x\n", + dev_err(&mgr->pci->dev, "ERROR RMH(%d): 0x%x\n", rmh->cmd_idx, data); err = -EINVAL; } else { @@ -780,7 +784,7 @@ static inline int pcxhr_pipes_running(struct pcxhr_mgr *mgr) * (PCXHR_PIPE_STATE_CAPTURE_OFFSET) */ start_mask &= 0xffffff; - snd_printdd("CMD_PIPE_STATE MBOX2=0x%06x\n", start_mask); + dev_dbg(&mgr->pci->dev, "CMD_PIPE_STATE MBOX2=0x%06x\n", start_mask); return start_mask; } @@ -809,7 +813,7 @@ static int pcxhr_prepair_pipe_start(struct pcxhr_mgr *mgr, } err = pcxhr_send_msg(mgr, &rmh); if (err) { - snd_printk(KERN_ERR + dev_err(&mgr->pci->dev, "error pipe start " "(CMD_CAN_START_PIPE) err=%x!\n", err); @@ -847,7 +851,7 @@ static int pcxhr_stop_pipes(struct pcxhr_mgr *mgr, int audio_mask) } err = pcxhr_send_msg(mgr, &rmh); if (err) { - snd_printk(KERN_ERR + dev_err(&mgr->pci->dev, "error pipe stop " "(CMD_STOP_PIPE) err=%x!\n", err); return err; @@ -876,7 +880,7 @@ static int pcxhr_toggle_pipes(struct pcxhr_mgr *mgr, int audio_mask) 1 << (audio - PCXHR_PIPE_STATE_CAPTURE_OFFSET)); err = pcxhr_send_msg(mgr, &rmh); if (err) { - snd_printk(KERN_ERR + dev_err(&mgr->pci->dev, "error pipe start " "(CMD_CONF_PIPE) err=%x!\n", err); return err; @@ -889,7 +893,7 @@ static int pcxhr_toggle_pipes(struct pcxhr_mgr *mgr, int audio_mask) pcxhr_init_rmh(&rmh, CMD_SEND_IRQA); err = pcxhr_send_msg(mgr, &rmh); if (err) { - snd_printk(KERN_ERR + dev_err(&mgr->pci->dev, "error pipe start (CMD_SEND_IRQA) err=%x!\n", err); return err; @@ -913,7 +917,8 @@ int pcxhr_set_pipe_state(struct pcxhr_mgr *mgr, int playback_mask, (capture_mask << PCXHR_PIPE_STATE_CAPTURE_OFFSET)); /* current pipe state (playback + record) */ state = pcxhr_pipes_running(mgr); - snd_printdd("pcxhr_set_pipe_state %s (mask %x current %x)\n", + dev_dbg(&mgr->pci->dev, + "pcxhr_set_pipe_state %s (mask %x current %x)\n", start ? "START" : "STOP", audio_mask, state); if (start) { /* start only pipes that are not yet started */ @@ -944,7 +949,7 @@ int pcxhr_set_pipe_state(struct pcxhr_mgr *mgr, int playback_mask, if ((state & audio_mask) == (start ? audio_mask : 0)) break; if (++i >= MAX_WAIT_FOR_DSP * 100) { - snd_printk(KERN_ERR "error pipe start/stop\n"); + dev_err(&mgr->pci->dev, "error pipe start/stop\n"); return -EBUSY; } udelay(10); /* wait 10 microseconds */ @@ -956,7 +961,7 @@ int pcxhr_set_pipe_state(struct pcxhr_mgr *mgr, int playback_mask, } #ifdef CONFIG_SND_DEBUG_VERBOSE do_gettimeofday(&my_tv2); - snd_printdd("***SET PIPE STATE*** TIME = %ld (err = %x)\n", + dev_dbg(&mgr->pci->dev, "***SET PIPE STATE*** TIME = %ld (err = %x)\n", (long)(my_tv2.tv_usec - my_tv1.tv_usec), err); #endif return 0; @@ -971,7 +976,8 @@ int pcxhr_write_io_num_reg_cont(struct pcxhr_mgr *mgr, unsigned int mask, spin_lock_irqsave(&mgr->msg_lock, flags); if ((mgr->io_num_reg_cont & mask) == value) { - snd_printdd("IO_NUM_REG_CONT mask %x already is set to %x\n", + dev_dbg(&mgr->pci->dev, + "IO_NUM_REG_CONT mask %x already is set to %x\n", mask, value); if (changed) *changed = 0; @@ -1024,7 +1030,7 @@ static int pcxhr_handle_async_err(struct pcxhr_mgr *mgr, u32 err, err = ((err >> 12) & 0xfff); if (!err) return 0; - snd_printdd("CMD_ASYNC : Error %s %s Pipe %d err=%x\n", + dev_dbg(&mgr->pci->dev, "CMD_ASYNC : Error %s %s Pipe %d err=%x\n", err_src_name[err_src], is_capture ? "Record" : "Play", pipe, err); if (err == 0xe01) @@ -1045,20 +1051,24 @@ void pcxhr_msg_tasklet(unsigned long arg) int i, j; if (mgr->src_it_dsp & PCXHR_IRQ_FREQ_CHANGE) - snd_printdd("TASKLET : PCXHR_IRQ_FREQ_CHANGE event occurred\n"); + dev_dbg(&mgr->pci->dev, + "TASKLET : PCXHR_IRQ_FREQ_CHANGE event occurred\n"); if (mgr->src_it_dsp & PCXHR_IRQ_TIME_CODE) - snd_printdd("TASKLET : PCXHR_IRQ_TIME_CODE event occurred\n"); + dev_dbg(&mgr->pci->dev, + "TASKLET : PCXHR_IRQ_TIME_CODE event occurred\n"); if (mgr->src_it_dsp & PCXHR_IRQ_NOTIFY) - snd_printdd("TASKLET : PCXHR_IRQ_NOTIFY event occurred\n"); + dev_dbg(&mgr->pci->dev, + "TASKLET : 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); err = pcxhr_send_msg(mgr, prmh); - snd_printdd("CMD_TEST_IT : err=%x, stat=%x\n", + dev_dbg(&mgr->pci->dev, "CMD_TEST_IT : err=%x, stat=%x\n", err, prmh->stat[0]); } if (mgr->src_it_dsp & PCXHR_IRQ_ASYNC) { - snd_printdd("TASKLET : PCXHR_IRQ_ASYNC event occurred\n"); + dev_dbg(&mgr->pci->dev, + "TASKLET : PCXHR_IRQ_ASYNC event occurred\n"); pcxhr_init_rmh(prmh, CMD_ASYNC); prmh->cmd[0] |= 1; /* add SEL_ASYNC_EVENTS */ @@ -1066,7 +1076,7 @@ void pcxhr_msg_tasklet(unsigned long arg) prmh->stat_len = PCXHR_SIZE_MAX_LONG_STATUS; err = pcxhr_send_msg(mgr, prmh); if (err) - snd_printk(KERN_ERR "ERROR pcxhr_msg_tasklet=%x;\n", + dev_err(&mgr->pci->dev, "ERROR pcxhr_msg_tasklet=%x;\n", err); i = 1; while (i < prmh->stat_len) { @@ -1079,7 +1089,8 @@ void pcxhr_msg_tasklet(unsigned long arg) u32 err2; if (prmh->stat[i] & 0x800000) { /* if BIT_END */ - snd_printdd("TASKLET : End%sPipe %d\n", + dev_dbg(&mgr->pci->dev, + "TASKLET : End%sPipe %d\n", is_capture ? "Record" : "Play", pipe); } @@ -1136,7 +1147,8 @@ static u_int64_t pcxhr_stream_read_position(struct pcxhr_mgr *mgr, hw_sample_count = ((u_int64_t)rmh.stat[0]) << 24; hw_sample_count += (u_int64_t)rmh.stat[1]; - snd_printdd("stream %c%d : abs samples real(%llu) timer(%llu)\n", + dev_dbg(&mgr->pci->dev, + "stream %c%d : abs samples real(%llu) timer(%llu)\n", stream->pipe->is_capture ? 'C' : 'P', stream->substream->number, hw_sample_count, @@ -1202,7 +1214,7 @@ static void pcxhr_update_timer_pos(struct pcxhr_mgr *mgr, (u_int32_t)(new_sample_count - stream->timer_abs_periods); } else { - snd_printk(KERN_ERR + dev_err(&mgr->pci->dev, "ERROR new_sample_count too small ??? %ld\n", (long unsigned int)new_sample_count); } @@ -1247,33 +1259,39 @@ irqreturn_t pcxhr_interrupt(int irq, void *dev_id) (mgr->dsp_time_last != PCXHR_DSP_TIME_INVALID)) { /* handle dsp counter wraparound without resync */ int tmp_diff = dsp_time_diff + PCXHR_DSP_TIME_MASK + 1; - snd_printdd("WARNING DSP timestamp old(%d) new(%d)", + dev_dbg(&mgr->pci->dev, + "WARNING DSP timestamp old(%d) new(%d)", mgr->dsp_time_last, dsp_time_new); if (tmp_diff > 0 && tmp_diff <= (2*mgr->granularity)) { - snd_printdd("-> timestamp wraparound OK: " + dev_dbg(&mgr->pci->dev, + "-> timestamp wraparound OK: " "diff=%d\n", tmp_diff); dsp_time_diff = tmp_diff; } else { - snd_printdd("-> resynchronize all streams\n"); + dev_dbg(&mgr->pci->dev, + "-> resynchronize all streams\n"); mgr->dsp_time_err++; } } #ifdef CONFIG_SND_DEBUG_VERBOSE if (dsp_time_diff == 0) - snd_printdd("ERROR DSP TIME NO DIFF time(%d)\n", + dev_dbg(&mgr->pci->dev, + "ERROR DSP TIME NO DIFF time(%d)\n", dsp_time_new); else if (dsp_time_diff >= (2*mgr->granularity)) - snd_printdd("ERROR DSP TIME TOO BIG old(%d) add(%d)\n", + dev_dbg(&mgr->pci->dev, + "ERROR DSP TIME TOO BIG old(%d) add(%d)\n", mgr->dsp_time_last, dsp_time_new - mgr->dsp_time_last); else if (dsp_time_diff % mgr->granularity) - snd_printdd("ERROR DSP TIME increased by %d\n", + dev_dbg(&mgr->pci->dev, + "ERROR DSP TIME increased by %d\n", dsp_time_diff); #endif mgr->dsp_time_last = dsp_time_new; if (timer_toggle == mgr->timer_toggle) { - snd_printdd("ERROR TIMER TOGGLE\n"); + dev_dbg(&mgr->pci->dev, "ERROR TIMER TOGGLE\n"); mgr->dsp_time_err++; } mgr->timer_toggle = timer_toggle; @@ -1308,7 +1326,7 @@ irqreturn_t pcxhr_interrupt(int irq, void *dev_id) } #ifdef CONFIG_SND_DEBUG_VERBOSE if (reg & PCXHR_FATAL_DSP_ERR) - snd_printdd("FATAL DSP ERROR : %x\n", reg); + dev_dbg(&mgr->pci->dev, "FATAL DSP ERROR : %x\n", reg); #endif spin_unlock(&mgr->lock); return IRQ_HANDLED; /* this device caused the interrupt */ diff --git a/sound/pci/pcxhr/pcxhr_hwdep.c b/sound/pci/pcxhr/pcxhr_hwdep.c index d995175c1c4..15a8ce5f1f4 100644 --- a/sound/pci/pcxhr/pcxhr_hwdep.c +++ b/sound/pci/pcxhr/pcxhr_hwdep.c @@ -72,7 +72,8 @@ static int pcxhr_init_board(struct pcxhr_mgr *mgr) /* test max nb substream per pipe */ if (((rmh.stat[1] >> 7) & 0x5F) < PCXHR_PLAYBACK_STREAMS) return -EINVAL; - snd_printdd("supported formats : playback=%x capture=%x\n", + dev_dbg(&mgr->pci->dev, + "supported formats : playback=%x capture=%x\n", rmh.stat[2], rmh.stat[3]); pcxhr_init_rmh(&rmh, CMD_VERSION); @@ -84,7 +85,8 @@ static int pcxhr_init_board(struct pcxhr_mgr *mgr) err = pcxhr_send_msg(mgr, &rmh); if (err) return err; - snd_printdd("PCXHR DSP version is %d.%d.%d\n", (rmh.stat[0]>>16)&0xff, + dev_dbg(&mgr->pci->dev, + "PCXHR DSP version is %d.%d.%d\n", (rmh.stat[0]>>16)&0xff, (rmh.stat[0]>>8)&0xff, rmh.stat[0]&0xff); mgr->dsp_version = rmh.stat[0]; @@ -179,7 +181,7 @@ static int pcxhr_dsp_allocate_pipe(struct pcxhr_mgr *mgr, stream_count = PCXHR_PLAYBACK_STREAMS; audio_count = 2; /* always stereo */ } - snd_printdd("snd_add_ref_pipe pin(%d) pcm%c0\n", + dev_dbg(&mgr->pci->dev, "snd_add_ref_pipe pin(%d) pcm%c0\n", pin, is_capture ? 'c' : 'p'); pipe->is_capture = is_capture; pipe->first_audio = pin; @@ -194,7 +196,7 @@ static int pcxhr_dsp_allocate_pipe(struct pcxhr_mgr *mgr, } err = pcxhr_send_msg(mgr, &rmh); if (err < 0) { - snd_printk(KERN_ERR "error pipe allocation " + dev_err(&mgr->pci->dev, "error pipe allocation " "(CMD_RES_PIPE) err=%x!\n", err); return err; } @@ -222,14 +224,14 @@ static int pcxhr_dsp_free_pipe( struct pcxhr_mgr *mgr, struct pcxhr_pipe *pipe) /* stop one pipe */ err = pcxhr_set_pipe_state(mgr, playback_mask, capture_mask, 0); if (err < 0) - snd_printk(KERN_ERR "error stopping pipe!\n"); + dev_err(&mgr->pci->dev, "error stopping pipe!\n"); /* release the pipe */ pcxhr_init_rmh(&rmh, CMD_FREE_PIPE); pcxhr_set_pipe_cmd_params(&rmh, pipe->is_capture, pipe->first_audio, 0, 0); err = pcxhr_send_msg(mgr, &rmh); if (err < 0) - snd_printk(KERN_ERR "error pipe release " + dev_err(&mgr->pci->dev, "error pipe release " "(CMD_FREE_PIPE) err(%x)\n", err); pipe->status = PCXHR_PIPE_UNDEFINED; return err; @@ -289,7 +291,8 @@ static int pcxhr_dsp_load(struct pcxhr_mgr *mgr, int index, { int err, card_index; - snd_printdd("loading dsp [%d] size = %Zd\n", index, dsp->size); + dev_dbg(&mgr->pci->dev, + "loading dsp [%d] size = %Zd\n", index, dsp->size); switch (index) { case PCXHR_FIRMWARE_XLX_INT_INDEX: @@ -313,19 +316,19 @@ static int pcxhr_dsp_load(struct pcxhr_mgr *mgr, int index, return err; break; /* continue with first init */ default: - snd_printk(KERN_ERR "wrong file index\n"); + dev_err(&mgr->pci->dev, "wrong file index\n"); return -EFAULT; } /* end of switch file index*/ /* first communication with embedded */ err = pcxhr_init_board(mgr); if (err < 0) { - snd_printk(KERN_ERR "pcxhr could not be set up\n"); + dev_err(&mgr->pci->dev, "pcxhr could not be set up\n"); return err; } err = pcxhr_config_pipes(mgr); if (err < 0) { - snd_printk(KERN_ERR "pcxhr pipes could not be set up\n"); + dev_err(&mgr->pci->dev, "pcxhr pipes could not be set up\n"); return err; } /* create devices and mixer in accordance with HW options*/ @@ -344,10 +347,11 @@ static int pcxhr_dsp_load(struct pcxhr_mgr *mgr, int index, } err = pcxhr_start_pipes(mgr); if (err < 0) { - snd_printk(KERN_ERR "pcxhr pipes could not be started\n"); + dev_err(&mgr->pci->dev, "pcxhr pipes could not be started\n"); return err; } - snd_printdd("pcxhr firmware downloaded and successfully set up\n"); + dev_dbg(&mgr->pci->dev, + "pcxhr firmware downloaded and successfully set up\n"); return 0; } @@ -382,7 +386,8 @@ int pcxhr_setup_firmware(struct pcxhr_mgr *mgr) continue; sprintf(path, "pcxhr/%s", fw_files[fw_set][i]); if (request_firmware(&fw_entry, path, &mgr->pci->dev)) { - snd_printk(KERN_ERR "pcxhr: can't load firmware %s\n", + dev_err(&mgr->pci->dev, + "pcxhr: can't load firmware %s\n", path); return -ENOENT; } diff --git a/sound/pci/pcxhr/pcxhr_mix22.c b/sound/pci/pcxhr/pcxhr_mix22.c index 84fe57626eb..6a56e5306a6 100644 --- a/sound/pci/pcxhr/pcxhr_mix22.c +++ b/sound/pci/pcxhr/pcxhr_mix22.c @@ -22,6 +22,7 @@ #include <linux/delay.h> #include <linux/io.h> +#include <linux/pci.h> #include <sound/core.h> #include <sound/control.h> #include <sound/tlv.h> @@ -290,7 +291,8 @@ int hr222_sub_init(struct pcxhr_mgr *mgr) reg = PCXHR_INPB(mgr, PCXHR_XLX_STATUS); if (reg & PCXHR_STAT_MIC_CAPS) mgr->board_has_mic = 1; /* microphone available */ - snd_printdd("MIC input available = %d\n", mgr->board_has_mic); + dev_dbg(&mgr->pci->dev, + "MIC input available = %d\n", mgr->board_has_mic); /* reset codec */ PCXHR_OUTPB(mgr, PCXHR_DSP_RESET, @@ -405,7 +407,7 @@ int hr222_sub_set_clock(struct pcxhr_mgr *mgr, hr222_config_akm(mgr, AKM_UNMUTE_CMD); - snd_printdd("set_clock to %dHz (realfreq=%d pllreg=%x)\n", + dev_dbg(&mgr->pci->dev, "set_clock to %dHz (realfreq=%d pllreg=%x)\n", rate, realfreq, pllreg); return 0; } @@ -431,13 +433,15 @@ int hr222_get_external_clock(struct pcxhr_mgr *mgr, reg = PCXHR_STAT_FREQ_UER1_MASK; } else { - snd_printdd("get_external_clock : type %d not supported\n", + dev_dbg(&mgr->pci->dev, + "get_external_clock : type %d not supported\n", clock_type); return -EINVAL; /* other clocks not supported */ } if ((PCXHR_INPB(mgr, PCXHR_XLX_CSUER) & mask) != mask) { - snd_printdd("get_external_clock(%d) = 0 Hz\n", clock_type); + dev_dbg(&mgr->pci->dev, + "get_external_clock(%d) = 0 Hz\n", clock_type); *sample_rate = 0; return 0; /* no external clock locked */ } @@ -495,7 +499,7 @@ int hr222_get_external_clock(struct pcxhr_mgr *mgr, else rate = 0; - snd_printdd("External clock is at %d Hz (measured %d Hz)\n", + dev_dbg(&mgr->pci->dev, "External clock is at %d Hz (measured %d Hz)\n", rate, calc_rate); *sample_rate = rate; return 0; @@ -542,7 +546,8 @@ int hr222_manage_timecode(struct pcxhr_mgr *mgr, int enable) int hr222_update_analog_audio_level(struct snd_pcxhr *chip, int is_capture, int channel) { - snd_printdd("hr222_update_analog_audio_level(%s chan=%d)\n", + dev_dbg(chip->card->dev, + "hr222_update_analog_audio_level(%s chan=%d)\n", is_capture ? "capture" : "playback", channel); if (is_capture) { int level_l, level_r, level_mic; @@ -642,7 +647,7 @@ int hr222_iec958_capture_byte(struct snd_pcxhr *chip, if (PCXHR_INPB(chip->mgr, PCXHR_XLX_CSUER) & mask) temp |= 1; } - snd_printdd("read iec958 AES %d byte %d = 0x%x\n", + dev_dbg(chip->card->dev, "read iec958 AES %d byte %d = 0x%x\n", chip->chip_idx, aes_idx, temp); *aes_bits = temp; return 0; @@ -684,7 +689,7 @@ static void hr222_micro_boost(struct pcxhr_mgr *mgr, int level) PCXHR_OUTPB(mgr, PCXHR_XLX_SELMIC, mgr->xlx_selmic); - snd_printdd("hr222_micro_boost : set %x\n", boost_mask); + dev_dbg(&mgr->pci->dev, "hr222_micro_boost : set %x\n", boost_mask); } static void hr222_phantom_power(struct pcxhr_mgr *mgr, int power) @@ -696,7 +701,7 @@ static void hr222_phantom_power(struct pcxhr_mgr *mgr, int power) PCXHR_OUTPB(mgr, PCXHR_XLX_SELMIC, mgr->xlx_selmic); - snd_printdd("hr222_phantom_power : set %d\n", power); + dev_dbg(&mgr->pci->dev, "hr222_phantom_power : set %d\n", power); } diff --git a/sound/pci/pcxhr/pcxhr_mixer.c b/sound/pci/pcxhr/pcxhr_mixer.c index fec04934462..95c9571780d 100644 --- a/sound/pci/pcxhr/pcxhr_mixer.c +++ b/sound/pci/pcxhr/pcxhr_mixer.c @@ -72,7 +72,8 @@ static int pcxhr_update_analog_audio_level(struct snd_pcxhr *chip, rmh.cmd_len = 3; err = pcxhr_send_msg(chip->mgr, &rmh); if (err < 0) { - snd_printk(KERN_DEBUG "error update_analog_audio_level card(%d)" + dev_dbg(chip->card->dev, + "error update_analog_audio_level card(%d)" " is_capture(%d) err(%x)\n", chip->chip_idx, is_capture, err); return -EINVAL; @@ -284,7 +285,7 @@ static int pcxhr_update_playback_stream_level(struct snd_pcxhr* chip, int idx) err = pcxhr_send_msg(chip->mgr, &rmh); if (err < 0) { - snd_printk(KERN_DEBUG "error update_playback_stream_level " + dev_dbg(chip->card->dev, "error update_playback_stream_level " "card(%d) err(%x)\n", chip->chip_idx, err); return -EINVAL; } @@ -335,7 +336,8 @@ static int pcxhr_update_audio_pipe_level(struct snd_pcxhr *chip, err = pcxhr_send_msg(chip->mgr, &rmh); if (err < 0) { - snd_printk(KERN_DEBUG "error update_audio_level(%d) err=%x\n", + dev_dbg(chip->card->dev, + "error update_audio_level(%d) err=%x\n", chip->chip_idx, err); return -EINVAL; } @@ -930,7 +932,7 @@ static int pcxhr_iec958_capture_byte(struct snd_pcxhr *chip, temp |= 1; } } - snd_printdd("read iec958 AES %d byte %d = 0x%x\n", + dev_dbg(chip->card->dev, "read iec958 AES %d byte %d = 0x%x\n", chip->chip_idx, aes_idx, temp); *aes_bits = temp; return 0; @@ -992,7 +994,8 @@ static int pcxhr_iec958_update_byte(struct snd_pcxhr *chip, rmh.cmd[0] |= IO_NUM_REG_CUER; rmh.cmd[1] = cmd; rmh.cmd_len = 2; - snd_printdd("write iec958 AES %d byte %d bit %d (cmd %x)\n", + dev_dbg(chip->card->dev, + "write iec958 AES %d byte %d bit %d (cmd %x)\n", chip->chip_idx, aes_idx, i, cmd); err = pcxhr_send_msg(chip->mgr, &rmh); if (err) diff --git a/sound/pci/riptide/riptide.c b/sound/pci/riptide/riptide.c index 56cc891e395..b4a8278241b 100644 --- a/sound/pci/riptide/riptide.c +++ b/sound/pci/riptide/riptide.c @@ -1916,8 +1916,6 @@ snd_riptide_create(struct snd_card *card, struct pci_dev *pci, return err; } - snd_card_set_dev(card, &pci->dev); - *rchip = chip; return 0; } @@ -2086,7 +2084,8 @@ snd_card_riptide_probe(struct pci_dev *pci, const struct pci_device_id *pci_id) return -ENOENT; } - err = snd_card_create(index[dev], id[dev], THIS_MODULE, 0, &card); + err = snd_card_new(&pci->dev, index[dev], id[dev], THIS_MODULE, + 0, &card); if (err < 0) return err; err = snd_riptide_create(card, pci, &chip); diff --git a/sound/pci/rme32.c b/sound/pci/rme32.c index cc26346ae66..cc2f0c1b648 100644 --- a/sound/pci/rme32.c +++ b/sound/pci/rme32.c @@ -1349,14 +1349,15 @@ static int snd_rme32_create(struct rme32 *rme32) rme32->iobase = ioremap_nocache(rme32->port, RME32_IO_SIZE); if (!rme32->iobase) { - snd_printk(KERN_ERR "unable to remap memory region 0x%lx-0x%lx\n", + dev_err(rme32->card->dev, + "unable to remap memory region 0x%lx-0x%lx\n", rme32->port, rme32->port + RME32_IO_SIZE - 1); return -ENOMEM; } if (request_irq(pci->irq, snd_rme32_interrupt, IRQF_SHARED, KBUILD_MODNAME, rme32)) { - snd_printk(KERN_ERR "unable to grab IRQ %d\n", pci->irq); + dev_err(rme32->card->dev, "unable to grab IRQ %d\n", pci->irq); return -EBUSY; } rme32->irq = pci->irq; @@ -1938,15 +1939,14 @@ snd_rme32_probe(struct pci_dev *pci, const struct pci_device_id *pci_id) return -ENOENT; } - err = snd_card_create(index[dev], id[dev], THIS_MODULE, - sizeof(struct rme32), &card); + err = snd_card_new(&pci->dev, index[dev], id[dev], THIS_MODULE, + sizeof(struct rme32), &card); if (err < 0) return err; card->private_free = snd_rme32_card_free; rme32 = (struct rme32 *) card->private_data; rme32->card = card; rme32->pci = pci; - snd_card_set_dev(card, &pci->dev); if (fullduplex[dev]) rme32->fullduplex_mode = 1; if ((err = snd_rme32_create(rme32)) < 0) { diff --git a/sound/pci/rme96.c b/sound/pci/rme96.c index 0236363c301..76169929770 100644 --- a/sound/pci/rme96.c +++ b/sound/pci/rme96.c @@ -240,7 +240,7 @@ struct rme96 { u8 rev; /* card revision number */ -#ifdef CONFIG_PM +#ifdef CONFIG_PM_SLEEP u32 playback_pointer; u32 capture_pointer; void *playback_suspend_buffer; @@ -1570,7 +1570,7 @@ snd_rme96_free(void *private_data) pci_release_regions(rme96->pci); rme96->port = 0; } -#ifdef CONFIG_PM +#ifdef CONFIG_PM_SLEEP vfree(rme96->playback_suspend_buffer); vfree(rme96->capture_suspend_buffer); #endif @@ -1609,13 +1609,15 @@ snd_rme96_create(struct rme96 *rme96) rme96->iobase = ioremap_nocache(rme96->port, RME96_IO_SIZE); if (!rme96->iobase) { - snd_printk(KERN_ERR "unable to remap memory region 0x%lx-0x%lx\n", rme96->port, rme96->port + RME96_IO_SIZE - 1); + dev_err(rme96->card->dev, + "unable to remap memory region 0x%lx-0x%lx\n", + rme96->port, rme96->port + RME96_IO_SIZE - 1); return -ENOMEM; } if (request_irq(pci->irq, snd_rme96_interrupt, IRQF_SHARED, KBUILD_MODNAME, rme96)) { - snd_printk(KERN_ERR "unable to grab IRQ %d\n", pci->irq); + dev_err(rme96->card->dev, "unable to grab IRQ %d\n", pci->irq); return -EBUSY; } rme96->irq = pci->irq; @@ -2372,13 +2374,12 @@ snd_rme96_create_switches(struct snd_card *card, * Card initialisation */ -#ifdef CONFIG_PM +#ifdef CONFIG_PM_SLEEP -static int -snd_rme96_suspend(struct pci_dev *pci, - pm_message_t state) +static int rme96_suspend(struct device *dev) { - struct snd_card *card = pci_get_drvdata(pci); + struct pci_dev *pci = to_pci_dev(dev); + struct snd_card *card = dev_get_drvdata(dev); struct rme96 *rme96 = card->private_data; snd_power_change_state(card, SNDRV_CTL_POWER_D3hot); @@ -2407,15 +2408,15 @@ snd_rme96_suspend(struct pci_dev *pci, return 0; } -static int -snd_rme96_resume(struct pci_dev *pci) +static int rme96_resume(struct device *dev) { - struct snd_card *card = pci_get_drvdata(pci); + struct pci_dev *pci = to_pci_dev(dev); + struct snd_card *card = dev_get_drvdata(dev); struct rme96 *rme96 = card->private_data; pci_restore_state(pci); if (pci_enable_device(pci) < 0) { - printk(KERN_ERR "rme96: pci_enable_device failed, disabling device\n"); + dev_err(dev, "pci_enable_device failed, disabling device\n"); snd_card_disconnect(card); return -EIO; } @@ -2451,7 +2452,11 @@ snd_rme96_resume(struct pci_dev *pci) return 0; } -#endif +static SIMPLE_DEV_PM_OPS(rme96_pm, rme96_suspend, rme96_resume); +#define RME96_PM_OPS &rme96_pm +#else +#define RME96_PM_OPS NULL +#endif /* CONFIG_PM_SLEEP */ static void snd_rme96_card_free(struct snd_card *card) { @@ -2475,31 +2480,30 @@ snd_rme96_probe(struct pci_dev *pci, dev++; return -ENOENT; } - err = snd_card_create(index[dev], id[dev], THIS_MODULE, - sizeof(struct rme96), &card); + err = snd_card_new(&pci->dev, index[dev], id[dev], THIS_MODULE, + sizeof(struct rme96), &card); if (err < 0) return err; card->private_free = snd_rme96_card_free; rme96 = card->private_data; rme96->card = card; rme96->pci = pci; - snd_card_set_dev(card, &pci->dev); if ((err = snd_rme96_create(rme96)) < 0) { snd_card_free(card); return err; } -#ifdef CONFIG_PM +#ifdef CONFIG_PM_SLEEP rme96->playback_suspend_buffer = vmalloc(RME96_BUFFER_SIZE); if (!rme96->playback_suspend_buffer) { - snd_printk(KERN_ERR + dev_err(card->dev, "Failed to allocate playback suspend buffer!\n"); snd_card_free(card); return -ENOMEM; } rme96->capture_suspend_buffer = vmalloc(RME96_BUFFER_SIZE); if (!rme96->capture_suspend_buffer) { - snd_printk(KERN_ERR + dev_err(card->dev, "Failed to allocate capture suspend buffer!\n"); snd_card_free(card); return -ENOMEM; @@ -2548,10 +2552,9 @@ static struct pci_driver rme96_driver = { .id_table = snd_rme96_ids, .probe = snd_rme96_probe, .remove = snd_rme96_remove, -#ifdef CONFIG_PM - .suspend = snd_rme96_suspend, - .resume = snd_rme96_resume, -#endif + .driver = { + .pm = RME96_PM_OPS, + }, }; module_pci_driver(rme96_driver); diff --git a/sound/pci/rme9652/hdsp.c b/sound/pci/rme9652/hdsp.c index bd90c80bb49..4c6f5d1c988 100644 --- a/sound/pci/rme9652/hdsp.c +++ b/sound/pci/rme9652/hdsp.c @@ -675,14 +675,15 @@ static int hdsp_check_for_iobox (struct hdsp *hdsp) if (0 == (hdsp_read(hdsp, HDSP_statusRegister) & HDSP_ConfigError)) { if (i) { - snd_printd("Hammerfall-DSP: IO box found after %d ms\n", + dev_dbg(hdsp->card->dev, + "IO box found after %d ms\n", (20 * i)); } return 0; } msleep(20); } - snd_printk(KERN_ERR "Hammerfall-DSP: no IO box connected!\n"); + dev_err(hdsp->card->dev, "no IO box connected!\n"); hdsp->state &= ~HDSP_FirmwareLoaded; return -EIO; } @@ -699,13 +700,13 @@ static int hdsp_wait_for_iobox(struct hdsp *hdsp, unsigned int loops, if (hdsp_read(hdsp, HDSP_statusRegister) & HDSP_ConfigError) msleep(delay); else { - snd_printd("Hammerfall-DSP: iobox found after %ums!\n", + dev_dbg(hdsp->card->dev, "iobox found after %ums!\n", i * delay); return 0; } } - snd_printk("Hammerfall-DSP: no IO box connected!\n"); + dev_info(hdsp->card->dev, "no IO box connected!\n"); hdsp->state &= ~HDSP_FirmwareLoaded; return -EIO; } @@ -728,13 +729,14 @@ static int snd_hdsp_load_firmware_from_cache(struct hdsp *hdsp) { if ((hdsp_read (hdsp, HDSP_statusRegister) & HDSP_DllError) != 0) { - snd_printk ("Hammerfall-DSP: loading firmware\n"); + dev_info(hdsp->card->dev, "loading firmware\n"); hdsp_write (hdsp, HDSP_control2Reg, HDSP_S_PROGRAM); hdsp_write (hdsp, HDSP_fifoData, 0); if (hdsp_fifo_wait (hdsp, 0, HDSP_LONG_WAIT)) { - snd_printk ("Hammerfall-DSP: timeout waiting for download preparation\n"); + dev_info(hdsp->card->dev, + "timeout waiting for download preparation\n"); hdsp_write(hdsp, HDSP_control2Reg, HDSP_S200); return -EIO; } @@ -744,7 +746,8 @@ static int snd_hdsp_load_firmware_from_cache(struct hdsp *hdsp) { for (i = 0; i < HDSP_FIRMWARE_SIZE / 4; ++i) { hdsp_write(hdsp, HDSP_fifoData, cache[i]); if (hdsp_fifo_wait (hdsp, 127, HDSP_LONG_WAIT)) { - snd_printk ("Hammerfall-DSP: timeout during firmware loading\n"); + dev_info(hdsp->card->dev, + "timeout during firmware loading\n"); hdsp_write(hdsp, HDSP_control2Reg, HDSP_S200); return -EIO; } @@ -760,11 +763,12 @@ static int snd_hdsp_load_firmware_from_cache(struct hdsp *hdsp) { hdsp->control2_register = 0; #endif hdsp_write (hdsp, HDSP_control2Reg, hdsp->control2_register); - snd_printk ("Hammerfall-DSP: finished firmware loading\n"); + dev_info(hdsp->card->dev, "finished firmware loading\n"); } if (hdsp->state & HDSP_InitializationComplete) { - snd_printk(KERN_INFO "Hammerfall-DSP: firmware loaded from cache, restoring defaults\n"); + dev_info(hdsp->card->dev, + "firmware loaded from cache, restoring defaults\n"); spin_lock_irqsave(&hdsp->lock, flags); snd_hdsp_set_defaults(hdsp); spin_unlock_irqrestore(&hdsp->lock, flags); @@ -791,7 +795,7 @@ static int hdsp_get_iobox_version (struct hdsp *hdsp) hdsp_write (hdsp, HDSP_fifoData, 0); if (hdsp_fifo_wait(hdsp, 0, HDSP_SHORT_WAIT) < 0) { hdsp->io_type = Multiface; - snd_printk("Hammerfall-DSP: Multiface found\n"); + dev_info(hdsp->card->dev, "Multiface found\n"); return 0; } @@ -799,7 +803,7 @@ static int hdsp_get_iobox_version (struct hdsp *hdsp) hdsp_write(hdsp, HDSP_fifoData, 0); if (hdsp_fifo_wait(hdsp, 0, HDSP_SHORT_WAIT) == 0) { hdsp->io_type = Digiface; - snd_printk("Hammerfall-DSP: Digiface found\n"); + dev_info(hdsp->card->dev, "Digiface found\n"); return 0; } @@ -808,7 +812,7 @@ static int hdsp_get_iobox_version (struct hdsp *hdsp) hdsp_write(hdsp, HDSP_fifoData, 0); if (hdsp_fifo_wait(hdsp, 0, HDSP_SHORT_WAIT) == 0) { hdsp->io_type = Multiface; - snd_printk("Hammerfall-DSP: Multiface found\n"); + dev_info(hdsp->card->dev, "Multiface found\n"); return 0; } @@ -817,12 +821,12 @@ static int hdsp_get_iobox_version (struct hdsp *hdsp) hdsp_write(hdsp, HDSP_fifoData, 0); if (hdsp_fifo_wait(hdsp, 0, HDSP_SHORT_WAIT) < 0) { hdsp->io_type = Multiface; - snd_printk("Hammerfall-DSP: Multiface found\n"); + dev_info(hdsp->card->dev, "Multiface found\n"); return 0; } hdsp->io_type = RPM; - snd_printk("Hammerfall-DSP: RPM found\n"); + dev_info(hdsp->card->dev, "RPM found\n"); return 0; } else { /* firmware was already loaded, get iobox type */ @@ -847,20 +851,18 @@ static int hdsp_check_for_firmware (struct hdsp *hdsp, int load_on_demand) hdsp->state &= ~HDSP_FirmwareLoaded; if (! load_on_demand) return -EIO; - snd_printk(KERN_ERR "Hammerfall-DSP: firmware not present.\n"); + dev_err(hdsp->card->dev, "firmware not present.\n"); /* try to load firmware */ if (! (hdsp->state & HDSP_FirmwareCached)) { if (! hdsp_request_fw_loader(hdsp)) return 0; - snd_printk(KERN_ERR - "Hammerfall-DSP: No firmware loaded nor " - "cached, please upload firmware.\n"); + dev_err(hdsp->card->dev, + "No firmware loaded nor cached, please upload firmware.\n"); return -EIO; } if (snd_hdsp_load_firmware_from_cache(hdsp) != 0) { - snd_printk(KERN_ERR - "Hammerfall-DSP: Firmware loading from " - "cache failed, please upload manually.\n"); + dev_err(hdsp->card->dev, + "Firmware loading from cache failed, please upload manually.\n"); return -EIO; } } @@ -888,7 +890,8 @@ static int hdsp_fifo_wait(struct hdsp *hdsp, int count, int timeout) udelay (100); } - snd_printk ("Hammerfall-DSP: wait for FIFO status <= %d failed after %d iterations\n", + dev_warn(hdsp->card->dev, + "wait for FIFO status <= %d failed after %d iterations\n", count, timeout); return -1; } @@ -1005,7 +1008,9 @@ static int hdsp_spdif_sample_rate(struct hdsp *hdsp) default: break; } - snd_printk ("Hammerfall-DSP: unknown spdif frequency status; bits = 0x%x, status = 0x%x\n", rate_bits, status); + dev_warn(hdsp->card->dev, + "unknown spdif frequency status; bits = 0x%x, status = 0x%x\n", + rate_bits, status); return 0; } @@ -1139,7 +1144,8 @@ static int hdsp_set_rate(struct hdsp *hdsp, int rate, int called_internally) if (!(hdsp->control_register & HDSP_ClockModeMaster)) { if (called_internally) { /* request from ctl or card initialization */ - snd_printk(KERN_ERR "Hammerfall-DSP: device is not running as a clock master: cannot set sample rate.\n"); + dev_err(hdsp->card->dev, + "device is not running as a clock master: cannot set sample rate.\n"); return -1; } else { /* hw_param request while in AutoSync mode */ @@ -1147,11 +1153,14 @@ static int hdsp_set_rate(struct hdsp *hdsp, int rate, int called_internally) int spdif_freq = hdsp_spdif_sample_rate(hdsp); if ((spdif_freq == external_freq*2) && (hdsp_autosync_ref(hdsp) >= HDSP_AUTOSYNC_FROM_ADAT1)) - snd_printk(KERN_INFO "Hammerfall-DSP: Detected ADAT in double speed mode\n"); + dev_info(hdsp->card->dev, + "Detected ADAT in double speed mode\n"); else if (hdsp->io_type == H9632 && (spdif_freq == external_freq*4) && (hdsp_autosync_ref(hdsp) >= HDSP_AUTOSYNC_FROM_ADAT1)) - snd_printk(KERN_INFO "Hammerfall-DSP: Detected ADAT in quad speed mode\n"); + dev_info(hdsp->card->dev, + "Detected ADAT in quad speed mode\n"); else if (rate != external_freq) { - snd_printk(KERN_INFO "Hammerfall-DSP: No AutoSync source for requested rate\n"); + dev_info(hdsp->card->dev, + "No AutoSync source for requested rate\n"); return -1; } } @@ -1223,7 +1232,8 @@ static int hdsp_set_rate(struct hdsp *hdsp, int rate, int called_internally) } if (reject_if_open && (hdsp->capture_pid >= 0 || hdsp->playback_pid >= 0)) { - snd_printk ("Hammerfall-DSP: cannot change speed mode (capture PID = %d, playback PID = %d)\n", + dev_warn(hdsp->card->dev, + "cannot change speed mode (capture PID = %d, playback PID = %d)\n", hdsp->capture_pid, hdsp->playback_pid); return -EBUSY; @@ -3785,7 +3795,8 @@ static int snd_hdsp_initialize_memory(struct hdsp *hdsp) snd_hammerfall_get_buffer(hdsp->pci, &hdsp->playback_dma_buf, HDSP_DMA_AREA_BYTES) < 0) { if (hdsp->capture_dma_buf.area) snd_dma_free_pages(&hdsp->capture_dma_buf); - printk(KERN_ERR "%s: no buffers available\n", hdsp->card_name); + dev_err(hdsp->card->dev, + "%s: no buffers available\n", hdsp->card_name); return -ENOMEM; } @@ -4747,7 +4758,8 @@ static int snd_hdsp_hwdep_ioctl(struct snd_hwdep *hw, struct file *file, unsigne return err; if (!(hdsp->state & HDSP_FirmwareLoaded)) { - snd_printk(KERN_ERR "Hammerfall-DSP: firmware needs to be uploaded to the card.\n"); + dev_err(hdsp->card->dev, + "firmware needs to be uploaded to the card.\n"); return -EINVAL; } @@ -4858,7 +4870,8 @@ static int snd_hdsp_hwdep_ioctl(struct snd_hwdep *hw, struct file *file, unsigne if (hdsp->state & (HDSP_FirmwareCached | HDSP_FirmwareLoaded)) return -EBUSY; - snd_printk(KERN_INFO "Hammerfall-DSP: initializing firmware upload\n"); + dev_info(hdsp->card->dev, + "initializing firmware upload\n"); firmware = (struct hdsp_firmware __user *)argp; if (get_user(firmware_data, &firmware->firmware_data)) @@ -4893,7 +4906,8 @@ static int snd_hdsp_hwdep_ioctl(struct snd_hwdep *hw, struct file *file, unsigne snd_hdsp_initialize_midi_flush(hdsp); if ((err = snd_hdsp_create_alsa_devices(hdsp->card, hdsp)) < 0) { - snd_printk(KERN_ERR "Hammerfall-DSP: error creating alsa devices\n"); + dev_err(hdsp->card->dev, + "error creating alsa devices\n"); return err; } } @@ -4983,7 +4997,8 @@ static int snd_hdsp_enable_io (struct hdsp *hdsp) int i; if (hdsp_fifo_wait (hdsp, 0, 100)) { - snd_printk(KERN_ERR "Hammerfall-DSP: enable_io fifo_wait failed\n"); + dev_err(hdsp->card->dev, + "enable_io fifo_wait failed\n"); return -EIO; } @@ -5057,25 +5072,29 @@ static int snd_hdsp_create_alsa_devices(struct snd_card *card, struct hdsp *hdsp int err; if ((err = snd_hdsp_create_pcm(card, hdsp)) < 0) { - snd_printk(KERN_ERR "Hammerfall-DSP: Error creating pcm interface\n"); + dev_err(card->dev, + "Error creating pcm interface\n"); return err; } if ((err = snd_hdsp_create_midi(card, hdsp, 0)) < 0) { - snd_printk(KERN_ERR "Hammerfall-DSP: Error creating first midi interface\n"); + dev_err(card->dev, + "Error creating first midi interface\n"); return err; } if (hdsp->io_type == Digiface || hdsp->io_type == H9652) { if ((err = snd_hdsp_create_midi(card, hdsp, 1)) < 0) { - snd_printk(KERN_ERR "Hammerfall-DSP: Error creating second midi interface\n"); + dev_err(card->dev, + "Error creating second midi interface\n"); return err; } } if ((err = snd_hdsp_create_controls(card, hdsp)) < 0) { - snd_printk(KERN_ERR "Hammerfall-DSP: Error creating ctl interface\n"); + dev_err(card->dev, + "Error creating ctl interface\n"); return err; } @@ -5088,7 +5107,8 @@ static int snd_hdsp_create_alsa_devices(struct snd_card *card, struct hdsp *hdsp hdsp->playback_substream = NULL; if ((err = snd_hdsp_set_defaults(hdsp)) < 0) { - snd_printk(KERN_ERR "Hammerfall-DSP: Error setting default values\n"); + dev_err(card->dev, + "Error setting default values\n"); return err; } @@ -5098,7 +5118,8 @@ static int snd_hdsp_create_alsa_devices(struct snd_card *card, struct hdsp *hdsp hdsp->port, hdsp->irq); if ((err = snd_card_register(card)) < 0) { - snd_printk(KERN_ERR "Hammerfall-DSP: error registering card\n"); + dev_err(card->dev, + "error registering card\n"); return err; } hdsp->state |= HDSP_InitializationComplete; @@ -5141,16 +5162,19 @@ static int hdsp_request_fw_loader(struct hdsp *hdsp) fwfile = "digiface_firmware_rev11.bin"; break; default: - snd_printk(KERN_ERR "Hammerfall-DSP: invalid io_type %d\n", hdsp->io_type); + dev_err(hdsp->card->dev, + "invalid io_type %d\n", hdsp->io_type); return -EINVAL; } if (request_firmware(&fw, fwfile, &hdsp->pci->dev)) { - snd_printk(KERN_ERR "Hammerfall-DSP: cannot load firmware %s\n", fwfile); + dev_err(hdsp->card->dev, + "cannot load firmware %s\n", fwfile); return -ENOENT; } if (fw->size < HDSP_FIRMWARE_SIZE) { - snd_printk(KERN_ERR "Hammerfall-DSP: too short firmware size %d (expected %d)\n", + dev_err(hdsp->card->dev, + "too short firmware size %d (expected %d)\n", (int)fw->size, HDSP_FIRMWARE_SIZE); return -EINVAL; } @@ -5167,13 +5191,15 @@ static int hdsp_request_fw_loader(struct hdsp *hdsp) return err; if ((err = snd_hdsp_create_hwdep(hdsp->card, hdsp)) < 0) { - snd_printk(KERN_ERR "Hammerfall-DSP: error creating hwdep device\n"); + dev_err(hdsp->card->dev, + "error creating hwdep device\n"); return err; } snd_hdsp_initialize_channels(hdsp); snd_hdsp_initialize_midi_flush(hdsp); if ((err = snd_hdsp_create_alsa_devices(hdsp->card, hdsp)) < 0) { - snd_printk(KERN_ERR "Hammerfall-DSP: error creating alsa devices\n"); + dev_err(hdsp->card->dev, + "error creating alsa devices\n"); return err; } } @@ -5249,13 +5275,14 @@ static int snd_hdsp_create(struct snd_card *card, return err; hdsp->port = pci_resource_start(pci, 0); if ((hdsp->iobase = ioremap_nocache(hdsp->port, HDSP_IO_EXTENT)) == NULL) { - snd_printk(KERN_ERR "Hammerfall-DSP: unable to remap region 0x%lx-0x%lx\n", hdsp->port, hdsp->port + HDSP_IO_EXTENT - 1); + dev_err(hdsp->card->dev, "unable to remap region 0x%lx-0x%lx\n", + hdsp->port, hdsp->port + HDSP_IO_EXTENT - 1); return -EBUSY; } if (request_irq(pci->irq, snd_hdsp_interrupt, IRQF_SHARED, KBUILD_MODNAME, hdsp)) { - snd_printk(KERN_ERR "Hammerfall-DSP: unable to use IRQ %d\n", pci->irq); + dev_err(hdsp->card->dev, "unable to use IRQ %d\n", pci->irq); return -EBUSY; } @@ -5281,17 +5308,20 @@ static int snd_hdsp_create(struct snd_card *card, if userspace is not ready for firmware upload */ - snd_printk(KERN_ERR "Hammerfall-DSP: couldn't get firmware from userspace. try using hdsploader\n"); + dev_err(hdsp->card->dev, + "couldn't get firmware from userspace. try using hdsploader\n"); else /* init is complete, we return */ return 0; /* we defer initialization */ - snd_printk(KERN_INFO "Hammerfall-DSP: card initialization pending : waiting for firmware\n"); + dev_info(hdsp->card->dev, + "card initialization pending : waiting for firmware\n"); if ((err = snd_hdsp_create_hwdep(card, hdsp)) < 0) return err; return 0; } else { - snd_printk(KERN_INFO "Hammerfall-DSP: Firmware already present, initializing card.\n"); + dev_info(hdsp->card->dev, + "Firmware already present, initializing card.\n"); if (hdsp_read(hdsp, HDSP_status2Register) & HDSP_version2) hdsp->io_type = RPM; else if (hdsp_read(hdsp, HDSP_status2Register) & HDSP_version1) @@ -5375,8 +5405,8 @@ static int snd_hdsp_probe(struct pci_dev *pci, return -ENOENT; } - err = snd_card_create(index[dev], id[dev], THIS_MODULE, - sizeof(struct hdsp), &card); + err = snd_card_new(&pci->dev, index[dev], id[dev], THIS_MODULE, + sizeof(struct hdsp), &card); if (err < 0) return err; @@ -5384,7 +5414,6 @@ static int snd_hdsp_probe(struct pci_dev *pci, card->private_free = snd_hdsp_card_free; hdsp->dev = dev; hdsp->pci = pci; - snd_card_set_dev(card, &pci->dev); if ((err = snd_hdsp_create(card, hdsp)) < 0) { snd_card_free(card); diff --git a/sound/pci/rme9652/hdspm.c b/sound/pci/rme9652/hdspm.c index e98dc008de0..cb82b593473 100644 --- a/sound/pci/rme9652/hdspm.c +++ b/sound/pci/rme9652/hdspm.c @@ -1651,9 +1651,8 @@ static int hdspm_set_rate(struct hdspm * hdspm, int rate, int called_internally) just make a warning an remember setting for future master mode switching */ - snd_printk(KERN_WARNING "HDSPM: " - "Warning: device is not running " - "as a clock master.\n"); + dev_warn(hdspm->card->dev, + "Warning: device is not running as a clock master.\n"); not_set = 1; } else { @@ -1664,15 +1663,14 @@ static int hdspm_set_rate(struct hdspm * hdspm, int rate, int called_internally) if (hdspm_autosync_ref(hdspm) == HDSPM_AUTOSYNC_FROM_NONE) { - snd_printk(KERN_WARNING "HDSPM: " - "Detected no Externel Sync \n"); + dev_warn(hdspm->card->dev, + "Detected no Externel Sync\n"); not_set = 1; } else if (rate != external_freq) { - snd_printk(KERN_WARNING "HDSPM: " - "Warning: No AutoSync source for " - "requested rate\n"); + dev_warn(hdspm->card->dev, + "Warning: No AutoSync source for requested rate\n"); not_set = 1; } } @@ -1738,13 +1736,11 @@ static int hdspm_set_rate(struct hdspm * hdspm, int rate, int called_internally) if (current_speed != target_speed && (hdspm->capture_pid >= 0 || hdspm->playback_pid >= 0)) { - snd_printk - (KERN_ERR "HDSPM: " - "cannot change from %s speed to %s speed mode " - "(capture PID = %d, playback PID = %d)\n", - hdspm_speed_names[current_speed], - hdspm_speed_names[target_speed], - hdspm->capture_pid, hdspm->playback_pid); + dev_err(hdspm->card->dev, + "cannot change from %s speed to %s speed mode (capture PID = %d, playback PID = %d)\n", + hdspm_speed_names[current_speed], + hdspm_speed_names[target_speed], + hdspm->capture_pid, hdspm->playback_pid); return -EBUSY; } @@ -5446,7 +5442,7 @@ static irqreturn_t snd_hdspm_interrupt(int irq, void *dev_id) * 0 64 ~3998231 ~8191558 **/ /* - snd_printk(KERN_INFO "snd_hdspm_interrupt %llu @ %llx\n", + dev_info(hdspm->card->dev, "snd_hdspm_interrupt %llu @ %llx\n", now-hdspm->last_interrupt, status & 0xFFC0); hdspm->last_interrupt = now; */ @@ -5583,7 +5579,7 @@ static int snd_hdspm_hw_params(struct snd_pcm_substream *substream, spin_lock_irq(&hdspm->lock); err = hdspm_set_rate(hdspm, params_rate(params), 0); if (err < 0) { - snd_printk(KERN_INFO "err on hdspm_set_rate: %d\n", err); + dev_info(hdspm->card->dev, "err on hdspm_set_rate: %d\n", err); spin_unlock_irq(&hdspm->lock); _snd_pcm_hw_param_setempty(params, SNDRV_PCM_HW_PARAM_RATE); @@ -5594,7 +5590,8 @@ static int snd_hdspm_hw_params(struct snd_pcm_substream *substream, err = hdspm_set_interrupt_interval(hdspm, params_period_size(params)); if (err < 0) { - snd_printk(KERN_INFO "err on hdspm_set_interrupt_interval: %d\n", err); + dev_info(hdspm->card->dev, + "err on hdspm_set_interrupt_interval: %d\n", err); _snd_pcm_hw_param_setempty(params, SNDRV_PCM_HW_PARAM_PERIOD_SIZE); return err; @@ -5610,7 +5607,8 @@ static int snd_hdspm_hw_params(struct snd_pcm_substream *substream, err = snd_pcm_lib_malloc_pages(substream, HDSPM_DMA_AREA_BYTES); if (err < 0) { - snd_printk(KERN_INFO "err on snd_pcm_lib_malloc_pages: %d\n", err); + dev_info(hdspm->card->dev, + "err on snd_pcm_lib_malloc_pages: %d\n", err); return err; } @@ -5624,7 +5622,8 @@ static int snd_hdspm_hw_params(struct snd_pcm_substream *substream, hdspm->playback_buffer = (unsigned char *) substream->runtime->dma_area; - snd_printdd("Allocated sample buffer for playback at %p\n", + dev_dbg(hdspm->card->dev, + "Allocated sample buffer for playback at %p\n", hdspm->playback_buffer); } else { hdspm_set_sgbuf(hdspm, substream, HDSPM_pageAddressBufferIn, @@ -5635,18 +5634,21 @@ static int snd_hdspm_hw_params(struct snd_pcm_substream *substream, hdspm->capture_buffer = (unsigned char *) substream->runtime->dma_area; - snd_printdd("Allocated sample buffer for capture at %p\n", + dev_dbg(hdspm->card->dev, + "Allocated sample buffer for capture at %p\n", hdspm->capture_buffer); } /* - snd_printdd("Allocated sample buffer for %s at 0x%08X\n", + dev_dbg(hdspm->card->dev, + "Allocated sample buffer for %s at 0x%08X\n", substream->stream == SNDRV_PCM_STREAM_PLAYBACK ? "playback" : "capture", snd_pcm_sgbuf_get_addr(substream, 0)); */ /* - snd_printdd("set_hwparams: %s %d Hz, %d channels, bs = %d\n", + dev_dbg(hdspm->card->dev, + "set_hwparams: %s %d Hz, %d channels, bs = %d\n", substream->stream == SNDRV_PCM_STREAM_PLAYBACK ? "playback" : "capture", params_rate(params), params_channels(params), @@ -5667,12 +5669,14 @@ static int snd_hdspm_hw_params(struct snd_pcm_substream *substream, /* Switch to native float format if requested */ if (SNDRV_PCM_FORMAT_FLOAT_LE == params_format(params)) { if (!(hdspm->control_register & HDSPe_FLOAT_FORMAT)) - snd_printk(KERN_INFO "hdspm: Switching to native 32bit LE float format.\n"); + dev_info(hdspm->card->dev, + "Switching to native 32bit LE float format.\n"); hdspm->control_register |= HDSPe_FLOAT_FORMAT; } else if (SNDRV_PCM_FORMAT_S32_LE == params_format(params)) { if (hdspm->control_register & HDSPe_FLOAT_FORMAT) - snd_printk(KERN_INFO "hdspm: Switching to native 32bit LE integer format.\n"); + dev_info(hdspm->card->dev, + "Switching to native 32bit LE integer format.\n"); hdspm->control_register &= ~HDSPe_FLOAT_FORMAT; } @@ -5715,12 +5719,16 @@ static int snd_hdspm_channel_info(struct snd_pcm_substream *substream, if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { if (snd_BUG_ON(info->channel >= hdspm->max_channels_out)) { - snd_printk(KERN_INFO "snd_hdspm_channel_info: output channel out of range (%d)\n", info->channel); + dev_info(hdspm->card->dev, + "snd_hdspm_channel_info: output channel out of range (%d)\n", + info->channel); return -EINVAL; } if (hdspm->channel_map_out[info->channel] < 0) { - snd_printk(KERN_INFO "snd_hdspm_channel_info: output channel %d mapped out\n", info->channel); + dev_info(hdspm->card->dev, + "snd_hdspm_channel_info: output channel %d mapped out\n", + info->channel); return -EINVAL; } @@ -5728,12 +5736,16 @@ static int snd_hdspm_channel_info(struct snd_pcm_substream *substream, HDSPM_CHANNEL_BUFFER_BYTES; } else { if (snd_BUG_ON(info->channel >= hdspm->max_channels_in)) { - snd_printk(KERN_INFO "snd_hdspm_channel_info: input channel out of range (%d)\n", info->channel); + dev_info(hdspm->card->dev, + "snd_hdspm_channel_info: input channel out of range (%d)\n", + info->channel); return -EINVAL; } if (hdspm->channel_map_in[info->channel] < 0) { - snd_printk(KERN_INFO "snd_hdspm_channel_info: input channel %d mapped out\n", info->channel); + dev_info(hdspm->card->dev, + "snd_hdspm_channel_info: input channel %d mapped out\n", + info->channel); return -EINVAL; } @@ -6283,7 +6295,7 @@ static int snd_hdspm_hwdep_ioctl(struct snd_hwdep *hw, struct file *file, s = copy_to_user(argp, levels, sizeof(struct hdspm_peak_rms)); if (0 != s) { - /* snd_printk(KERN_ERR "copy_to_user(.., .., %lu): %lu + /* dev_err(hdspm->card->dev, "copy_to_user(.., .., %lu): %lu [Levels]\n", sizeof(struct hdspm_peak_rms), s); */ return -EFAULT; @@ -6329,7 +6341,7 @@ static int snd_hdspm_hwdep_ioctl(struct snd_hwdep *hw, struct file *file, s = copy_to_user(argp, <c, sizeof(struct hdspm_ltc)); if (0 != s) { /* - snd_printk(KERN_ERR "copy_to_user(.., .., %lu): %lu [LTC]\n", sizeof(struct hdspm_ltc), s); */ + dev_err(hdspm->card->dev, "copy_to_user(.., .., %lu): %lu [LTC]\n", sizeof(struct hdspm_ltc), s); */ return -EFAULT; } @@ -6494,11 +6506,13 @@ static int snd_hdspm_preallocate_memory(struct hdspm *hdspm) wanted, wanted); if (err < 0) { - snd_printdd("Could not preallocate %zd Bytes\n", wanted); + dev_dbg(hdspm->card->dev, + "Could not preallocate %zd Bytes\n", wanted); return err; } else - snd_printdd(" Preallocated %zd Bytes\n", wanted); + dev_dbg(hdspm->card->dev, + " Preallocated %zd Bytes\n", wanted); return 0; } @@ -6559,7 +6573,7 @@ static int snd_hdspm_create_alsa_devices(struct snd_card *card, { int err, i; - snd_printdd("Create card...\n"); + dev_dbg(card->dev, "Create card...\n"); err = snd_hdspm_create_pcm(card, hdspm); if (err < 0) return err; @@ -6581,7 +6595,7 @@ static int snd_hdspm_create_alsa_devices(struct snd_card *card, if (err < 0) return err; - snd_printdd("proc init...\n"); + dev_dbg(card->dev, "proc init...\n"); snd_hdspm_proc_init(hdspm); hdspm->system_sample_rate = -1; @@ -6592,23 +6606,23 @@ static int snd_hdspm_create_alsa_devices(struct snd_card *card, hdspm->capture_substream = NULL; hdspm->playback_substream = NULL; - snd_printdd("Set defaults...\n"); + dev_dbg(card->dev, "Set defaults...\n"); err = snd_hdspm_set_defaults(hdspm); if (err < 0) return err; - snd_printdd("Update mixer controls...\n"); + dev_dbg(card->dev, "Update mixer controls...\n"); hdspm_update_simple_mixer_controls(hdspm); - snd_printdd("Initializeing complete ???\n"); + dev_dbg(card->dev, "Initializeing complete ???\n"); err = snd_card_register(card); if (err < 0) { - snd_printk(KERN_ERR "HDSPM: error registering card\n"); + dev_err(card->dev, "error registering card\n"); return err; } - snd_printdd("... yes now\n"); + dev_dbg(card->dev, "... yes now\n"); return 0; } @@ -6662,8 +6676,8 @@ static int snd_hdspm_create(struct snd_card *card, hdspm->card_name = "RME MADI"; hdspm->midiPorts = 3; } else { - snd_printk(KERN_ERR - "HDSPM: unknown firmware revision %x\n", + dev_err(card->dev, + "unknown firmware revision %x\n", hdspm->firmware_rev); return -ENODEV; } @@ -6682,36 +6696,35 @@ static int snd_hdspm_create(struct snd_card *card, hdspm->port = pci_resource_start(pci, 0); io_extent = pci_resource_len(pci, 0); - snd_printdd("grabbed memory region 0x%lx-0x%lx\n", + dev_dbg(card->dev, "grabbed memory region 0x%lx-0x%lx\n", hdspm->port, hdspm->port + io_extent - 1); hdspm->iobase = ioremap_nocache(hdspm->port, io_extent); if (!hdspm->iobase) { - snd_printk(KERN_ERR "HDSPM: " - "unable to remap region 0x%lx-0x%lx\n", + dev_err(card->dev, "unable to remap region 0x%lx-0x%lx\n", hdspm->port, hdspm->port + io_extent - 1); return -EBUSY; } - snd_printdd("remapped region (0x%lx) 0x%lx-0x%lx\n", + dev_dbg(card->dev, "remapped region (0x%lx) 0x%lx-0x%lx\n", (unsigned long)hdspm->iobase, hdspm->port, hdspm->port + io_extent - 1); if (request_irq(pci->irq, snd_hdspm_interrupt, IRQF_SHARED, KBUILD_MODNAME, hdspm)) { - snd_printk(KERN_ERR "HDSPM: unable to use IRQ %d\n", pci->irq); + dev_err(card->dev, "unable to use IRQ %d\n", pci->irq); return -EBUSY; } - snd_printdd("use IRQ %d\n", pci->irq); + dev_dbg(card->dev, "use IRQ %d\n", pci->irq); hdspm->irq = pci->irq; - snd_printdd("kmalloc Mixer memory of %zd Bytes\n", + dev_dbg(card->dev, "kmalloc Mixer memory of %zd Bytes\n", sizeof(struct hdspm_mixer)); hdspm->mixer = kzalloc(sizeof(struct hdspm_mixer), GFP_KERNEL); if (!hdspm->mixer) { - snd_printk(KERN_ERR "HDSPM: " - "unable to kmalloc Mixer memory of %d Bytes\n", + dev_err(card->dev, + "unable to kmalloc Mixer memory of %d Bytes\n", (int)sizeof(struct hdspm_mixer)); return -ENOMEM; } @@ -6780,14 +6793,14 @@ static int snd_hdspm_create(struct snd_card *card, hdspm->qs_out_channels = AIO_OUT_QS_CHANNELS; if (0 == (hdspm_read(hdspm, HDSPM_statusRegister2) & HDSPM_s2_AEBI_D)) { - snd_printk(KERN_INFO "HDSPM: AEB input board found\n"); + dev_info(card->dev, "AEB input board found\n"); hdspm->ss_in_channels += 4; hdspm->ds_in_channels += 4; hdspm->qs_in_channels += 4; } if (0 == (hdspm_read(hdspm, HDSPM_statusRegister2) & HDSPM_s2_AEBO_D)) { - snd_printk(KERN_INFO "HDSPM: AEB output board found\n"); + dev_info(card->dev, "AEB output board found\n"); hdspm->ss_out_channels += 4; hdspm->ds_out_channels += 4; hdspm->qs_out_channels += 4; @@ -6854,7 +6867,7 @@ static int snd_hdspm_create(struct snd_card *card, if (NULL != hdspm->tco) { hdspm_tco_write(hdspm); } - snd_printk(KERN_INFO "HDSPM: AIO/RayDAT TCO module found\n"); + dev_info(card->dev, "AIO/RayDAT TCO module found\n"); } else { hdspm->tco = NULL; } @@ -6869,7 +6882,7 @@ static int snd_hdspm_create(struct snd_card *card, if (NULL != hdspm->tco) { hdspm_tco_write(hdspm); } - snd_printk(KERN_INFO "HDSPM: MADI/AES TCO module found\n"); + dev_info(card->dev, "MADI/AES TCO module found\n"); } else { hdspm->tco = NULL; } @@ -6951,7 +6964,7 @@ static int snd_hdspm_create(struct snd_card *card, } } - snd_printdd("create alsa devices.\n"); + dev_dbg(card->dev, "create alsa devices.\n"); err = snd_hdspm_create_alsa_devices(card, hdspm); if (err < 0) return err; @@ -7016,8 +7029,8 @@ static int snd_hdspm_probe(struct pci_dev *pci, return -ENOENT; } - err = snd_card_create(index[dev], id[dev], - THIS_MODULE, sizeof(struct hdspm), &card); + err = snd_card_new(&pci->dev, index[dev], id[dev], + THIS_MODULE, sizeof(struct hdspm), &card); if (err < 0) return err; @@ -7026,8 +7039,6 @@ static int snd_hdspm_probe(struct pci_dev *pci, hdspm->dev = dev; hdspm->pci = pci; - snd_card_set_dev(card, &pci->dev); - err = snd_hdspm_create(card, hdspm); if (err < 0) { snd_card_free(card); diff --git a/sound/pci/rme9652/rme9652.c b/sound/pci/rme9652/rme9652.c index 1503ee3585f..1d9be90f774 100644 --- a/sound/pci/rme9652/rme9652.c +++ b/sound/pci/rme9652/rme9652.c @@ -394,7 +394,9 @@ static snd_pcm_uframes_t rme9652_hw_pointer(struct snd_rme9652 *rme9652) if (offset < period_size) { if (offset > rme9652->max_jitter) { if (frag) - printk(KERN_ERR "Unexpected hw_pointer position (bufid == 0): status: %x offset: %d\n", status, offset); + dev_err(rme9652->card->dev, + "Unexpected hw_pointer position (bufid == 0): status: %x offset: %d\n", + status, offset); } else if (!frag) return 0; offset -= rme9652->max_jitter; @@ -403,7 +405,9 @@ static snd_pcm_uframes_t rme9652_hw_pointer(struct snd_rme9652 *rme9652) } else { if (offset > period_size + rme9652->max_jitter) { if (!frag) - printk(KERN_ERR "Unexpected hw_pointer position (bufid == 1): status: %x offset: %d\n", status, offset); + dev_err(rme9652->card->dev, + "Unexpected hw_pointer position (bufid == 1): status: %x offset: %d\n", + status, offset); } else if (frag) return period_size; offset -= rme9652->max_jitter; @@ -769,7 +773,8 @@ static inline int rme9652_spdif_sample_rate(struct snd_rme9652 *s) break; default: - snd_printk(KERN_ERR "%s: unknown S/PDIF input rate (bits = 0x%x)\n", + dev_err(s->card->dev, + "%s: unknown S/PDIF input rate (bits = 0x%x)\n", s->card_name, rate_bits); return 0; break; @@ -1790,7 +1795,8 @@ static int snd_rme9652_initialize_memory(struct snd_rme9652 *rme9652) snd_hammerfall_get_buffer(rme9652->pci, &rme9652->playback_dma_buf, RME9652_DMA_AREA_BYTES) < 0) { if (rme9652->capture_dma_buf.area) snd_dma_free_pages(&rme9652->capture_dma_buf); - printk(KERN_ERR "%s: no buffers available\n", rme9652->card_name); + dev_err(rme9652->card->dev, + "%s: no buffers available\n", rme9652->card_name); return -ENOMEM; } @@ -2468,13 +2474,14 @@ static int snd_rme9652_create(struct snd_card *card, rme9652->port = pci_resource_start(pci, 0); rme9652->iobase = ioremap_nocache(rme9652->port, RME9652_IO_EXTENT); if (rme9652->iobase == NULL) { - snd_printk(KERN_ERR "unable to remap region 0x%lx-0x%lx\n", rme9652->port, rme9652->port + RME9652_IO_EXTENT - 1); + dev_err(card->dev, "unable to remap region 0x%lx-0x%lx\n", + rme9652->port, rme9652->port + RME9652_IO_EXTENT - 1); return -EBUSY; } if (request_irq(pci->irq, snd_rme9652_interrupt, IRQF_SHARED, KBUILD_MODNAME, rme9652)) { - snd_printk(KERN_ERR "unable to request IRQ %d\n", pci->irq); + dev_err(card->dev, "unable to request IRQ %d\n", pci->irq); return -EBUSY; } rme9652->irq = pci->irq; @@ -2587,8 +2594,8 @@ static int snd_rme9652_probe(struct pci_dev *pci, return -ENOENT; } - err = snd_card_create(index[dev], id[dev], THIS_MODULE, - sizeof(struct snd_rme9652), &card); + err = snd_card_new(&pci->dev, index[dev], id[dev], THIS_MODULE, + sizeof(struct snd_rme9652), &card); if (err < 0) return err; @@ -2597,7 +2604,6 @@ static int snd_rme9652_probe(struct pci_dev *pci, card->private_free = snd_rme9652_card_free; rme9652->dev = dev; rme9652->pci = pci; - snd_card_set_dev(card, &pci->dev); if ((err = snd_rme9652_create(card, rme9652, precise_ptr[dev])) < 0) { snd_card_free(card); diff --git a/sound/pci/sis7019.c b/sound/pci/sis7019.c index e413b4e2c81..6b26b93e001 100644 --- a/sound/pci/sis7019.c +++ b/sound/pci/sis7019.c @@ -1404,8 +1404,6 @@ static int sis_chip_create(struct snd_card *card, if (rc) goto error_out_cleanup; - snd_card_set_dev(card, &pci->dev); - return 0; error_out_cleanup: @@ -1440,7 +1438,8 @@ static int snd_sis7019_probe(struct pci_dev *pci, if (!codecs) codecs = SIS_PRIMARY_CODEC_PRESENT; - rc = snd_card_create(index, id, THIS_MODULE, sizeof(*sis), &card); + rc = snd_card_new(&pci->dev, index, id, THIS_MODULE, + sizeof(*sis), &card); if (rc < 0) goto error_out; diff --git a/sound/pci/sonicvibes.c b/sound/pci/sonicvibes.c index 2a46bf98af3..2044dc74207 100644 --- a/sound/pci/sonicvibes.c +++ b/sound/pci/sonicvibes.c @@ -273,7 +273,7 @@ static inline void snd_sonicvibes_setdmaa(struct sonicvibes * sonic, outl(count, sonic->dmaa_port + SV_DMA_COUNT0); outb(0x18, sonic->dmaa_port + SV_DMA_MODE); #if 0 - printk(KERN_DEBUG "program dmaa: addr = 0x%x, paddr = 0x%x\n", + dev_dbg(sonic->card->dev, "program dmaa: addr = 0x%x, paddr = 0x%x\n", addr, inl(sonic->dmaa_port + SV_DMA_ADDR0)); #endif } @@ -289,7 +289,7 @@ static inline void snd_sonicvibes_setdmac(struct sonicvibes * sonic, outl(count, sonic->dmac_port + SV_DMA_COUNT0); outb(0x14, sonic->dmac_port + SV_DMA_MODE); #if 0 - printk(KERN_DEBUG "program dmac: addr = 0x%x, paddr = 0x%x\n", + dev_dbg(sonic->card->dev, "program dmac: addr = 0x%x, paddr = 0x%x\n", addr, inl(sonic->dmac_port + SV_DMA_ADDR0)); #endif } @@ -357,105 +357,105 @@ static unsigned char snd_sonicvibes_in(struct sonicvibes * sonic, unsigned char #if 0 static void snd_sonicvibes_debug(struct sonicvibes * sonic) { - printk(KERN_DEBUG - "SV REGS: INDEX = 0x%02x ", inb(SV_REG(sonic, INDEX))); - printk(" STATUS = 0x%02x\n", inb(SV_REG(sonic, STATUS))); - printk(KERN_DEBUG - " 0x00: left input = 0x%02x ", snd_sonicvibes_in(sonic, 0x00)); - printk(" 0x20: synth rate low = 0x%02x\n", snd_sonicvibes_in(sonic, 0x20)); - printk(KERN_DEBUG - " 0x01: right input = 0x%02x ", snd_sonicvibes_in(sonic, 0x01)); - printk(" 0x21: synth rate high = 0x%02x\n", snd_sonicvibes_in(sonic, 0x21)); - printk(KERN_DEBUG - " 0x02: left AUX1 = 0x%02x ", snd_sonicvibes_in(sonic, 0x02)); - printk(" 0x22: ADC clock = 0x%02x\n", snd_sonicvibes_in(sonic, 0x22)); - printk(KERN_DEBUG - " 0x03: right AUX1 = 0x%02x ", snd_sonicvibes_in(sonic, 0x03)); - printk(" 0x23: ADC alt rate = 0x%02x\n", snd_sonicvibes_in(sonic, 0x23)); - printk(KERN_DEBUG - " 0x04: left CD = 0x%02x ", snd_sonicvibes_in(sonic, 0x04)); - printk(" 0x24: ADC pll M = 0x%02x\n", snd_sonicvibes_in(sonic, 0x24)); - printk(KERN_DEBUG - " 0x05: right CD = 0x%02x ", snd_sonicvibes_in(sonic, 0x05)); - printk(" 0x25: ADC pll N = 0x%02x\n", snd_sonicvibes_in(sonic, 0x25)); - printk(KERN_DEBUG - " 0x06: left line = 0x%02x ", snd_sonicvibes_in(sonic, 0x06)); - printk(" 0x26: Synth pll M = 0x%02x\n", snd_sonicvibes_in(sonic, 0x26)); - printk(KERN_DEBUG - " 0x07: right line = 0x%02x ", snd_sonicvibes_in(sonic, 0x07)); - printk(" 0x27: Synth pll N = 0x%02x\n", snd_sonicvibes_in(sonic, 0x27)); - printk(KERN_DEBUG - " 0x08: MIC = 0x%02x ", snd_sonicvibes_in(sonic, 0x08)); - printk(" 0x28: --- = 0x%02x\n", snd_sonicvibes_in(sonic, 0x28)); - printk(KERN_DEBUG - " 0x09: Game port = 0x%02x ", snd_sonicvibes_in(sonic, 0x09)); - printk(" 0x29: --- = 0x%02x\n", snd_sonicvibes_in(sonic, 0x29)); - printk(KERN_DEBUG - " 0x0a: left synth = 0x%02x ", snd_sonicvibes_in(sonic, 0x0a)); - printk(" 0x2a: MPU401 = 0x%02x\n", snd_sonicvibes_in(sonic, 0x2a)); - printk(KERN_DEBUG - " 0x0b: right synth = 0x%02x ", snd_sonicvibes_in(sonic, 0x0b)); - printk(" 0x2b: drive ctrl = 0x%02x\n", snd_sonicvibes_in(sonic, 0x2b)); - printk(KERN_DEBUG - " 0x0c: left AUX2 = 0x%02x ", snd_sonicvibes_in(sonic, 0x0c)); - printk(" 0x2c: SRS space = 0x%02x\n", snd_sonicvibes_in(sonic, 0x2c)); - printk(KERN_DEBUG - " 0x0d: right AUX2 = 0x%02x ", snd_sonicvibes_in(sonic, 0x0d)); - printk(" 0x2d: SRS center = 0x%02x\n", snd_sonicvibes_in(sonic, 0x2d)); - printk(KERN_DEBUG - " 0x0e: left analog = 0x%02x ", snd_sonicvibes_in(sonic, 0x0e)); - printk(" 0x2e: wave source = 0x%02x\n", snd_sonicvibes_in(sonic, 0x2e)); - printk(KERN_DEBUG - " 0x0f: right analog = 0x%02x ", snd_sonicvibes_in(sonic, 0x0f)); - printk(" 0x2f: --- = 0x%02x\n", snd_sonicvibes_in(sonic, 0x2f)); - printk(KERN_DEBUG - " 0x10: left PCM = 0x%02x ", snd_sonicvibes_in(sonic, 0x10)); - printk(" 0x30: analog power = 0x%02x\n", snd_sonicvibes_in(sonic, 0x30)); - printk(KERN_DEBUG - " 0x11: right PCM = 0x%02x ", snd_sonicvibes_in(sonic, 0x11)); - printk(" 0x31: analog power = 0x%02x\n", snd_sonicvibes_in(sonic, 0x31)); - printk(KERN_DEBUG - " 0x12: DMA data format = 0x%02x ", snd_sonicvibes_in(sonic, 0x12)); - printk(" 0x32: --- = 0x%02x\n", snd_sonicvibes_in(sonic, 0x32)); - printk(KERN_DEBUG - " 0x13: P/C enable = 0x%02x ", snd_sonicvibes_in(sonic, 0x13)); - printk(" 0x33: --- = 0x%02x\n", snd_sonicvibes_in(sonic, 0x33)); - printk(KERN_DEBUG - " 0x14: U/D button = 0x%02x ", snd_sonicvibes_in(sonic, 0x14)); - printk(" 0x34: --- = 0x%02x\n", snd_sonicvibes_in(sonic, 0x34)); - printk(KERN_DEBUG - " 0x15: revision = 0x%02x ", snd_sonicvibes_in(sonic, 0x15)); - printk(" 0x35: --- = 0x%02x\n", snd_sonicvibes_in(sonic, 0x35)); - printk(KERN_DEBUG - " 0x16: ADC output ctrl = 0x%02x ", snd_sonicvibes_in(sonic, 0x16)); - printk(" 0x36: --- = 0x%02x\n", snd_sonicvibes_in(sonic, 0x36)); - printk(KERN_DEBUG - " 0x17: --- = 0x%02x ", snd_sonicvibes_in(sonic, 0x17)); - printk(" 0x37: --- = 0x%02x\n", snd_sonicvibes_in(sonic, 0x37)); - printk(KERN_DEBUG - " 0x18: DMA A upper cnt = 0x%02x ", snd_sonicvibes_in(sonic, 0x18)); - printk(" 0x38: --- = 0x%02x\n", snd_sonicvibes_in(sonic, 0x38)); - printk(KERN_DEBUG - " 0x19: DMA A lower cnt = 0x%02x ", snd_sonicvibes_in(sonic, 0x19)); - printk(" 0x39: --- = 0x%02x\n", snd_sonicvibes_in(sonic, 0x39)); - printk(KERN_DEBUG - " 0x1a: --- = 0x%02x ", snd_sonicvibes_in(sonic, 0x1a)); - printk(" 0x3a: --- = 0x%02x\n", snd_sonicvibes_in(sonic, 0x3a)); - printk(KERN_DEBUG - " 0x1b: --- = 0x%02x ", snd_sonicvibes_in(sonic, 0x1b)); - printk(" 0x3b: --- = 0x%02x\n", snd_sonicvibes_in(sonic, 0x3b)); - printk(KERN_DEBUG - " 0x1c: DMA C upper cnt = 0x%02x ", snd_sonicvibes_in(sonic, 0x1c)); - printk(" 0x3c: --- = 0x%02x\n", snd_sonicvibes_in(sonic, 0x3c)); - printk(KERN_DEBUG - " 0x1d: DMA C upper cnt = 0x%02x ", snd_sonicvibes_in(sonic, 0x1d)); - printk(" 0x3d: --- = 0x%02x\n", snd_sonicvibes_in(sonic, 0x3d)); - printk(KERN_DEBUG - " 0x1e: PCM rate low = 0x%02x ", snd_sonicvibes_in(sonic, 0x1e)); - printk(" 0x3e: --- = 0x%02x\n", snd_sonicvibes_in(sonic, 0x3e)); - printk(KERN_DEBUG - " 0x1f: PCM rate high = 0x%02x ", snd_sonicvibes_in(sonic, 0x1f)); - printk(" 0x3f: --- = 0x%02x\n", snd_sonicvibes_in(sonic, 0x3f)); + dev_dbg(sonic->card->dev, + "SV REGS: INDEX = 0x%02x STATUS = 0x%02x\n", + inb(SV_REG(sonic, INDEX)), inb(SV_REG(sonic, STATUS))); + dev_dbg(sonic->card->dev, + " 0x00: left input = 0x%02x 0x20: synth rate low = 0x%02x\n", + snd_sonicvibes_in(sonic, 0x00), snd_sonicvibes_in(sonic, 0x20)); + dev_dbg(sonic->card->dev, + " 0x01: right input = 0x%02x 0x21: synth rate high = 0x%02x\n", + snd_sonicvibes_in(sonic, 0x01), snd_sonicvibes_in(sonic, 0x21)); + dev_dbg(sonic->card->dev, + " 0x02: left AUX1 = 0x%02x 0x22: ADC clock = 0x%02x\n", + snd_sonicvibes_in(sonic, 0x02), snd_sonicvibes_in(sonic, 0x22)); + dev_dbg(sonic->card->dev, + " 0x03: right AUX1 = 0x%02x 0x23: ADC alt rate = 0x%02x\n", + snd_sonicvibes_in(sonic, 0x03), snd_sonicvibes_in(sonic, 0x23)); + dev_dbg(sonic->card->dev, + " 0x04: left CD = 0x%02x 0x24: ADC pll M = 0x%02x\n", + snd_sonicvibes_in(sonic, 0x04), snd_sonicvibes_in(sonic, 0x24)); + dev_dbg(sonic->card->dev, + " 0x05: right CD = 0x%02x 0x25: ADC pll N = 0x%02x\n", + snd_sonicvibes_in(sonic, 0x05), snd_sonicvibes_in(sonic, 0x25)); + dev_dbg(sonic->card->dev, + " 0x06: left line = 0x%02x 0x26: Synth pll M = 0x%02x\n", + snd_sonicvibes_in(sonic, 0x06), snd_sonicvibes_in(sonic, 0x26)); + dev_dbg(sonic->card->dev, + " 0x07: right line = 0x%02x 0x27: Synth pll N = 0x%02x\n", + snd_sonicvibes_in(sonic, 0x07), snd_sonicvibes_in(sonic, 0x27)); + dev_dbg(sonic->card->dev, + " 0x08: MIC = 0x%02x 0x28: --- = 0x%02x\n", + snd_sonicvibes_in(sonic, 0x08), snd_sonicvibes_in(sonic, 0x28)); + dev_dbg(sonic->card->dev, + " 0x09: Game port = 0x%02x 0x29: --- = 0x%02x\n", + snd_sonicvibes_in(sonic, 0x09), snd_sonicvibes_in(sonic, 0x29)); + dev_dbg(sonic->card->dev, + " 0x0a: left synth = 0x%02x 0x2a: MPU401 = 0x%02x\n", + snd_sonicvibes_in(sonic, 0x0a), snd_sonicvibes_in(sonic, 0x2a)); + dev_dbg(sonic->card->dev, + " 0x0b: right synth = 0x%02x 0x2b: drive ctrl = 0x%02x\n", + snd_sonicvibes_in(sonic, 0x0b), snd_sonicvibes_in(sonic, 0x2b)); + dev_dbg(sonic->card->dev, + " 0x0c: left AUX2 = 0x%02x 0x2c: SRS space = 0x%02x\n", + snd_sonicvibes_in(sonic, 0x0c), snd_sonicvibes_in(sonic, 0x2c)); + dev_dbg(sonic->card->dev, + " 0x0d: right AUX2 = 0x%02x 0x2d: SRS center = 0x%02x\n", + snd_sonicvibes_in(sonic, 0x0d), snd_sonicvibes_in(sonic, 0x2d)); + dev_dbg(sonic->card->dev, + " 0x0e: left analog = 0x%02x 0x2e: wave source = 0x%02x\n", + snd_sonicvibes_in(sonic, 0x0e), snd_sonicvibes_in(sonic, 0x2e)); + dev_dbg(sonic->card->dev, + " 0x0f: right analog = 0x%02x 0x2f: --- = 0x%02x\n", + snd_sonicvibes_in(sonic, 0x0f), snd_sonicvibes_in(sonic, 0x2f)); + dev_dbg(sonic->card->dev, + " 0x10: left PCM = 0x%02x 0x30: analog power = 0x%02x\n", + snd_sonicvibes_in(sonic, 0x10), snd_sonicvibes_in(sonic, 0x30)); + dev_dbg(sonic->card->dev, + " 0x11: right PCM = 0x%02x 0x31: analog power = 0x%02x\n", + snd_sonicvibes_in(sonic, 0x11), snd_sonicvibes_in(sonic, 0x31)); + dev_dbg(sonic->card->dev, + " 0x12: DMA data format = 0x%02x 0x32: --- = 0x%02x\n", + snd_sonicvibes_in(sonic, 0x12), snd_sonicvibes_in(sonic, 0x32)); + dev_dbg(sonic->card->dev, + " 0x13: P/C enable = 0x%02x 0x33: --- = 0x%02x\n", + snd_sonicvibes_in(sonic, 0x13), snd_sonicvibes_in(sonic, 0x33)); + dev_dbg(sonic->card->dev, + " 0x14: U/D button = 0x%02x 0x34: --- = 0x%02x\n", + snd_sonicvibes_in(sonic, 0x14), snd_sonicvibes_in(sonic, 0x34)); + dev_dbg(sonic->card->dev, + " 0x15: revision = 0x%02x 0x35: --- = 0x%02x\n", + snd_sonicvibes_in(sonic, 0x15), snd_sonicvibes_in(sonic, 0x35)); + dev_dbg(sonic->card->dev, + " 0x16: ADC output ctrl = 0x%02x 0x36: --- = 0x%02x\n", + snd_sonicvibes_in(sonic, 0x16), snd_sonicvibes_in(sonic, 0x36)); + dev_dbg(sonic->card->dev, + " 0x17: --- = 0x%02x 0x37: --- = 0x%02x\n", + snd_sonicvibes_in(sonic, 0x17), snd_sonicvibes_in(sonic, 0x37)); + dev_dbg(sonic->card->dev, + " 0x18: DMA A upper cnt = 0x%02x 0x38: --- = 0x%02x\n", + snd_sonicvibes_in(sonic, 0x18), snd_sonicvibes_in(sonic, 0x38)); + dev_dbg(sonic->card->dev, + " 0x19: DMA A lower cnt = 0x%02x 0x39: --- = 0x%02x\n", + snd_sonicvibes_in(sonic, 0x19), snd_sonicvibes_in(sonic, 0x39)); + dev_dbg(sonic->card->dev, + " 0x1a: --- = 0x%02x 0x3a: --- = 0x%02x\n", + snd_sonicvibes_in(sonic, 0x1a), snd_sonicvibes_in(sonic, 0x3a)); + dev_dbg(sonic->card->dev, + " 0x1b: --- = 0x%02x 0x3b: --- = 0x%02x\n", + snd_sonicvibes_in(sonic, 0x1b), snd_sonicvibes_in(sonic, 0x3b)); + dev_dbg(sonic->card->dev, + " 0x1c: DMA C upper cnt = 0x%02x 0x3c: --- = 0x%02x\n", + snd_sonicvibes_in(sonic, 0x1c), snd_sonicvibes_in(sonic, 0x3c)); + dev_dbg(sonic->card->dev, + " 0x1d: DMA C upper cnt = 0x%02x 0x3d: --- = 0x%02x\n", + snd_sonicvibes_in(sonic, 0x1d), snd_sonicvibes_in(sonic, 0x3d)); + dev_dbg(sonic->card->dev, + " 0x1e: PCM rate low = 0x%02x 0x3e: --- = 0x%02x\n", + snd_sonicvibes_in(sonic, 0x1e), snd_sonicvibes_in(sonic, 0x3e)); + dev_dbg(sonic->card->dev, + " 0x1f: PCM rate high = 0x%02x 0x3f: --- = 0x%02x\n", + snd_sonicvibes_in(sonic, 0x1f), snd_sonicvibes_in(sonic, 0x3f)); } #endif @@ -511,8 +511,10 @@ static void snd_sonicvibes_pll(unsigned int rate, *res_m = m; *res_n = n; #if 0 - printk(KERN_DEBUG "metric = %i, xm = %i, xn = %i\n", metric, xm, xn); - printk(KERN_DEBUG "pll: m = 0x%x, r = 0x%x, n = 0x%x\n", reg, m, r, n); + dev_dbg(sonic->card->dev, + "metric = %i, xm = %i, xn = %i\n", metric, xm, xn); + dev_dbg(sonic->card->dev, + "pll: m = 0x%x, r = 0x%x, n = 0x%x\n", reg, m, r, n); #endif } @@ -624,7 +626,8 @@ static irqreturn_t snd_sonicvibes_interrupt(int irq, void *dev_id) return IRQ_NONE; if (status == 0xff) { /* failure */ outb(sonic->irqmask = ~0, SV_REG(sonic, IRQMASK)); - snd_printk(KERN_ERR "IRQ failure - interrupts disabled!!\n"); + dev_err(sonic->card->dev, + "IRQ failure - interrupts disabled!!\n"); return IRQ_HANDLED; } if (sonic->pcm) { @@ -1198,7 +1201,8 @@ static int snd_sonicvibes_create_gameport(struct sonicvibes *sonic) sonic->gameport = gp = gameport_allocate_port(); if (!gp) { - printk(KERN_ERR "sonicvibes: cannot allocate memory for gameport\n"); + dev_err(sonic->card->dev, + "sonicvibes: cannot allocate memory for gameport\n"); return -ENOMEM; } @@ -1267,7 +1271,8 @@ static int snd_sonicvibes_create(struct snd_card *card, /* check, if we can restrict PCI DMA transfers to 24 bits */ if (pci_set_dma_mask(pci, DMA_BIT_MASK(24)) < 0 || pci_set_consistent_dma_mask(pci, DMA_BIT_MASK(24)) < 0) { - snd_printk(KERN_ERR "architecture does not support 24bit PCI busmaster DMA\n"); + dev_err(card->dev, + "architecture does not support 24bit PCI busmaster DMA\n"); pci_disable_device(pci); return -ENXIO; } @@ -1296,7 +1301,7 @@ static int snd_sonicvibes_create(struct snd_card *card, if (request_irq(pci->irq, snd_sonicvibes_interrupt, IRQF_SHARED, KBUILD_MODNAME, sonic)) { - snd_printk(KERN_ERR "unable to grab IRQ %d\n", pci->irq); + dev_err(card->dev, "unable to grab IRQ %d\n", pci->irq); snd_sonicvibes_free(sonic); return -EBUSY; } @@ -1310,24 +1315,32 @@ static int snd_sonicvibes_create(struct snd_card *card, if (!dmaa) { dmaa = dmaio; dmaio += 0x10; - snd_printk(KERN_INFO "BIOS did not allocate DDMA channel A i/o, allocated at 0x%x\n", dmaa); + dev_info(card->dev, + "BIOS did not allocate DDMA channel A i/o, allocated at 0x%x\n", + dmaa); } if (!dmac) { dmac = dmaio; dmaio += 0x10; - snd_printk(KERN_INFO "BIOS did not allocate DDMA channel C i/o, allocated at 0x%x\n", dmac); + dev_info(card->dev, + "BIOS did not allocate DDMA channel C i/o, allocated at 0x%x\n", + dmac); } pci_write_config_dword(pci, 0x40, dmaa); pci_write_config_dword(pci, 0x48, dmac); if ((sonic->res_dmaa = request_region(dmaa, 0x10, "S3 SonicVibes DDMA-A")) == NULL) { snd_sonicvibes_free(sonic); - snd_printk(KERN_ERR "unable to grab DDMA-A port at 0x%x-0x%x\n", dmaa, dmaa + 0x10 - 1); + dev_err(card->dev, + "unable to grab DDMA-A port at 0x%x-0x%x\n", + dmaa, dmaa + 0x10 - 1); return -EBUSY; } if ((sonic->res_dmac = request_region(dmac, 0x10, "S3 SonicVibes DDMA-C")) == NULL) { snd_sonicvibes_free(sonic); - snd_printk(KERN_ERR "unable to grab DDMA-C port at 0x%x-0x%x\n", dmac, dmac + 0x10 - 1); + dev_err(card->dev, + "unable to grab DDMA-C port at 0x%x-0x%x\n", + dmac, dmac + 0x10 - 1); return -EBUSY; } @@ -1392,8 +1405,6 @@ static int snd_sonicvibes_create(struct snd_card *card, snd_sonicvibes_proc_init(sonic); - snd_card_set_dev(card, &pci->dev); - *rsonic = sonic; return 0; } @@ -1459,7 +1470,8 @@ static int snd_sonic_probe(struct pci_dev *pci, return -ENOENT; } - err = snd_card_create(index[dev], id[dev], THIS_MODULE, 0, &card); + err = snd_card_new(&pci->dev, index[dev], id[dev], THIS_MODULE, + 0, &card); if (err < 0) return err; for (idx = 0; idx < 5; idx++) { diff --git a/sound/pci/trident/trident.c b/sound/pci/trident/trident.c index b3b588bc94c..d852458caf3 100644 --- a/sound/pci/trident/trident.c +++ b/sound/pci/trident/trident.c @@ -89,7 +89,8 @@ static int snd_trident_probe(struct pci_dev *pci, return -ENOENT; } - err = snd_card_create(index[dev], id[dev], THIS_MODULE, 0, &card); + err = snd_card_new(&pci->dev, index[dev], id[dev], THIS_MODULE, + 0, &card); if (err < 0) return err; diff --git a/sound/pci/trident/trident_main.c b/sound/pci/trident/trident_main.c index fb0e1586a6f..1272c18a254 100644 --- a/sound/pci/trident/trident_main.c +++ b/sound/pci/trident/trident_main.c @@ -69,40 +69,40 @@ static void snd_trident_print_voice_regs(struct snd_trident *trident, int voice) { unsigned int val, tmp; - printk(KERN_DEBUG "Trident voice %i:\n", voice); + dev_dbg(trident->card->dev, "Trident voice %i:\n", voice); outb(voice, TRID_REG(trident, T4D_LFO_GC_CIR)); val = inl(TRID_REG(trident, CH_LBA)); - printk(KERN_DEBUG "LBA: 0x%x\n", val); + dev_dbg(trident->card->dev, "LBA: 0x%x\n", val); val = inl(TRID_REG(trident, CH_GVSEL_PAN_VOL_CTRL_EC)); - printk(KERN_DEBUG "GVSel: %i\n", val >> 31); - printk(KERN_DEBUG "Pan: 0x%x\n", (val >> 24) & 0x7f); - printk(KERN_DEBUG "Vol: 0x%x\n", (val >> 16) & 0xff); - printk(KERN_DEBUG "CTRL: 0x%x\n", (val >> 12) & 0x0f); - printk(KERN_DEBUG "EC: 0x%x\n", val & 0x0fff); + dev_dbg(trident->card->dev, "GVSel: %i\n", val >> 31); + dev_dbg(trident->card->dev, "Pan: 0x%x\n", (val >> 24) & 0x7f); + dev_dbg(trident->card->dev, "Vol: 0x%x\n", (val >> 16) & 0xff); + dev_dbg(trident->card->dev, "CTRL: 0x%x\n", (val >> 12) & 0x0f); + dev_dbg(trident->card->dev, "EC: 0x%x\n", val & 0x0fff); if (trident->device != TRIDENT_DEVICE_ID_NX) { val = inl(TRID_REG(trident, CH_DX_CSO_ALPHA_FMS)); - printk(KERN_DEBUG "CSO: 0x%x\n", val >> 16); - printk("Alpha: 0x%x\n", (val >> 4) & 0x0fff); - printk(KERN_DEBUG "FMS: 0x%x\n", val & 0x0f); + dev_dbg(trident->card->dev, "CSO: 0x%x\n", val >> 16); + dev_dbg(trident->card->dev, "Alpha: 0x%x\n", (val >> 4) & 0x0fff); + dev_dbg(trident->card->dev, "FMS: 0x%x\n", val & 0x0f); val = inl(TRID_REG(trident, CH_DX_ESO_DELTA)); - printk(KERN_DEBUG "ESO: 0x%x\n", val >> 16); - printk(KERN_DEBUG "Delta: 0x%x\n", val & 0xffff); + dev_dbg(trident->card->dev, "ESO: 0x%x\n", val >> 16); + dev_dbg(trident->card->dev, "Delta: 0x%x\n", val & 0xffff); val = inl(TRID_REG(trident, CH_DX_FMC_RVOL_CVOL)); } else { // TRIDENT_DEVICE_ID_NX val = inl(TRID_REG(trident, CH_NX_DELTA_CSO)); tmp = (val >> 24) & 0xff; - printk(KERN_DEBUG "CSO: 0x%x\n", val & 0x00ffffff); + dev_dbg(trident->card->dev, "CSO: 0x%x\n", val & 0x00ffffff); val = inl(TRID_REG(trident, CH_NX_DELTA_ESO)); tmp |= (val >> 16) & 0xff00; - printk(KERN_DEBUG "Delta: 0x%x\n", tmp); - printk(KERN_DEBUG "ESO: 0x%x\n", val & 0x00ffffff); + dev_dbg(trident->card->dev, "Delta: 0x%x\n", tmp); + dev_dbg(trident->card->dev, "ESO: 0x%x\n", val & 0x00ffffff); val = inl(TRID_REG(trident, CH_NX_ALPHA_FMS_FMC_RVOL_CVOL)); - printk(KERN_DEBUG "Alpha: 0x%x\n", val >> 20); - printk(KERN_DEBUG "FMS: 0x%x\n", (val >> 16) & 0x0f); + dev_dbg(trident->card->dev, "Alpha: 0x%x\n", val >> 20); + dev_dbg(trident->card->dev, "FMS: 0x%x\n", (val >> 16) & 0x0f); } - printk(KERN_DEBUG "FMC: 0x%x\n", (val >> 14) & 3); - printk(KERN_DEBUG "RVol: 0x%x\n", (val >> 7) & 0x7f); - printk(KERN_DEBUG "CVol: 0x%x\n", val & 0x7f); + dev_dbg(trident->card->dev, "FMC: 0x%x\n", (val >> 14) & 3); + dev_dbg(trident->card->dev, "RVol: 0x%x\n", (val >> 7) & 0x7f); + dev_dbg(trident->card->dev, "CVol: 0x%x\n", val & 0x7f); } #endif @@ -156,7 +156,8 @@ static unsigned short snd_trident_codec_read(struct snd_ac97 *ac97, unsigned sho } if (count == 0 && !trident->ac97_detect) { - snd_printk(KERN_ERR "ac97 codec read TIMEOUT [0x%x/0x%x]!!!\n", + dev_err(trident->card->dev, + "ac97 codec read TIMEOUT [0x%x/0x%x]!!!\n", reg, data); data = 0; } @@ -497,16 +498,16 @@ void snd_trident_write_voice_regs(struct snd_trident * trident, outl(regs[4], TRID_REG(trident, CH_START + 16)); #if 0 - printk(KERN_DEBUG "written %i channel:\n", voice->number); - printk(KERN_DEBUG " regs[0] = 0x%x/0x%x\n", + dev_dbg(trident->card->dev, "written %i channel:\n", voice->number); + dev_dbg(trident->card->dev, " regs[0] = 0x%x/0x%x\n", regs[0], inl(TRID_REG(trident, CH_START + 0))); - printk(KERN_DEBUG " regs[1] = 0x%x/0x%x\n", + dev_dbg(trident->card->dev, " regs[1] = 0x%x/0x%x\n", regs[1], inl(TRID_REG(trident, CH_START + 4))); - printk(KERN_DEBUG " regs[2] = 0x%x/0x%x\n", + dev_dbg(trident->card->dev, " regs[2] = 0x%x/0x%x\n", regs[2], inl(TRID_REG(trident, CH_START + 8))); - printk(KERN_DEBUG " regs[3] = 0x%x/0x%x\n", + dev_dbg(trident->card->dev, " regs[3] = 0x%x/0x%x\n", regs[3], inl(TRID_REG(trident, CH_START + 12))); - printk(KERN_DEBUG " regs[4] = 0x%x/0x%x\n", + dev_dbg(trident->card->dev, " regs[4] = 0x%x/0x%x\n", regs[4], inl(TRID_REG(trident, CH_START + 16))); #endif } @@ -589,7 +590,7 @@ static void snd_trident_write_vol_reg(struct snd_trident * trident, outb(voice->Vol >> 2, TRID_REG(trident, CH_GVSEL_PAN_VOL_CTRL_EC + 2)); break; case TRIDENT_DEVICE_ID_SI7018: - /* printk(KERN_DEBUG "voice->Vol = 0x%x\n", voice->Vol); */ + /* dev_dbg(trident->card->dev, "voice->Vol = 0x%x\n", voice->Vol); */ outw((voice->CTRL << 12) | voice->Vol, TRID_REG(trident, CH_GVSEL_PAN_VOL_CTRL_EC)); break; @@ -3013,13 +3014,15 @@ static int snd_trident_mixer(struct snd_trident *trident, int pcm_spdif_device) _ac97.num = 1; err = snd_ac97_mixer(trident->ac97_bus, &_ac97, &trident->ac97_sec); if (err < 0) - snd_printk(KERN_ERR "SI7018: the secondary codec - invalid access\n"); + dev_err(trident->card->dev, + "SI7018: the secondary codec - invalid access\n"); #if 0 // only for my testing purpose --jk { struct snd_ac97 *mc97; err = snd_ac97_modem(trident->card, &_ac97, &mc97); if (err < 0) - snd_printk(KERN_ERR "snd_ac97_modem returned error %i\n", err); + dev_err(trident->card->dev, + "snd_ac97_modem returned error %i\n", err); } #endif } @@ -3197,7 +3200,8 @@ int snd_trident_create_gameport(struct snd_trident *chip) chip->gameport = gp = gameport_allocate_port(); if (!gp) { - printk(KERN_ERR "trident: cannot allocate memory for gameport\n"); + dev_err(chip->card->dev, + "cannot allocate memory for gameport\n"); return -ENOMEM; } @@ -3270,7 +3274,8 @@ static int snd_trident_sis_reset(struct snd_trident *trident) goto __si7018_ok; do_delay(trident); } while (time_after_eq(end_time, jiffies)); - snd_printk(KERN_ERR "AC'97 codec ready error [0x%x]\n", inl(TRID_REG(trident, SI_SERIAL_INTF_CTRL))); + dev_err(trident->card->dev, "AC'97 codec ready error [0x%x]\n", + inl(TRID_REG(trident, SI_SERIAL_INTF_CTRL))); if (r-- > 0) { end_time = jiffies + HZ; do { @@ -3367,7 +3372,7 @@ static int snd_trident_tlb_alloc(struct snd_trident *trident) if (snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(trident->pci), 2 * SNDRV_TRIDENT_MAX_PAGES * 4, &trident->tlb.buffer) < 0) { - snd_printk(KERN_ERR "trident: unable to allocate TLB buffer\n"); + dev_err(trident->card->dev, "unable to allocate TLB buffer\n"); return -ENOMEM; } trident->tlb.entries = (unsigned int*)ALIGN((unsigned long)trident->tlb.buffer.area, SNDRV_TRIDENT_MAX_PAGES * 4); @@ -3375,13 +3380,14 @@ static int snd_trident_tlb_alloc(struct snd_trident *trident) /* allocate shadow TLB page table (virtual addresses) */ trident->tlb.shadow_entries = vmalloc(SNDRV_TRIDENT_MAX_PAGES*sizeof(unsigned long)); if (trident->tlb.shadow_entries == NULL) { - snd_printk(KERN_ERR "trident: unable to allocate shadow TLB entries\n"); + dev_err(trident->card->dev, + "unable to allocate shadow TLB entries\n"); return -ENOMEM; } /* allocate and setup silent page and initialise TLB entries */ if (snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(trident->pci), SNDRV_TRIDENT_PAGE_SIZE, &trident->tlb.silent_page) < 0) { - snd_printk(KERN_ERR "trident: unable to allocate silent page\n"); + dev_err(trident->card->dev, "unable to allocate silent page\n"); return -ENOMEM; } memset(trident->tlb.silent_page.area, 0, SNDRV_TRIDENT_PAGE_SIZE); @@ -3439,7 +3445,7 @@ static int snd_trident_4d_dx_init(struct snd_trident *trident) goto __dx_ok; do_delay(trident); } while (time_after_eq(end_time, jiffies)); - snd_printk(KERN_ERR "AC'97 codec ready error\n"); + dev_err(trident->card->dev, "AC'97 codec ready error\n"); return -EIO; __dx_ok: @@ -3477,7 +3483,8 @@ static int snd_trident_4d_nx_init(struct snd_trident *trident) goto __nx_ok; do_delay(trident); } while (time_after_eq(end_time, jiffies)); - snd_printk(KERN_ERR "AC'97 codec ready error [0x%x]\n", inl(TRID_REG(trident, NX_ACR0_AC97_COM_STAT))); + dev_err(trident->card->dev, "AC'97 codec ready error [0x%x]\n", + inl(TRID_REG(trident, NX_ACR0_AC97_COM_STAT))); return -EIO; __nx_ok: @@ -3562,7 +3569,8 @@ int snd_trident_create(struct snd_card *card, /* check, if we can restrict PCI DMA transfers to 30 bits */ if (pci_set_dma_mask(pci, DMA_BIT_MASK(30)) < 0 || pci_set_consistent_dma_mask(pci, DMA_BIT_MASK(30)) < 0) { - snd_printk(KERN_ERR "architecture does not support 30bit PCI busmaster DMA\n"); + dev_err(card->dev, + "architecture does not support 30bit PCI busmaster DMA\n"); pci_disable_device(pci); return -ENXIO; } @@ -3600,7 +3608,7 @@ int snd_trident_create(struct snd_card *card, if (request_irq(pci->irq, snd_trident_interrupt, IRQF_SHARED, KBUILD_MODNAME, trident)) { - snd_printk(KERN_ERR "unable to grab IRQ %d\n", pci->irq); + dev_err(card->dev, "unable to grab IRQ %d\n", pci->irq); snd_trident_free(trident); return -EBUSY; } @@ -3664,7 +3672,6 @@ int snd_trident_create(struct snd_card *card, snd_trident_enable_eso(trident); snd_trident_proc_init(trident); - snd_card_set_dev(card, &pci->dev); *rtrident = trident; return 0; } @@ -3950,8 +3957,7 @@ static int snd_trident_resume(struct device *dev) pci_set_power_state(pci, PCI_D0); pci_restore_state(pci); if (pci_enable_device(pci) < 0) { - printk(KERN_ERR "trident: pci_enable_device failed, " - "disabling device\n"); + dev_err(dev, "pci_enable_device failed, disabling device\n"); snd_card_disconnect(card); return -EIO; } diff --git a/sound/pci/via82xx.c b/sound/pci/via82xx.c index 5ae6f042c58..95b98f537b6 100644 --- a/sound/pci/via82xx.c +++ b/sound/pci/via82xx.c @@ -459,7 +459,7 @@ static int build_via_table(struct viadev *dev, struct snd_pcm_substream *substre unsigned int addr; if (idx >= VIA_TABLE_SIZE) { - snd_printk(KERN_ERR "via82xx: too much table size!\n"); + dev_err(&pci->dev, "too much table size!\n"); return -EINVAL; } addr = snd_pcm_sgbuf_get_addr(substream, ofs); @@ -474,8 +474,9 @@ static int build_via_table(struct viadev *dev, struct snd_pcm_substream *substre } else flag = 0; /* period continues to the next */ /* - printk(KERN_DEBUG "via: tbl %d: at %d size %d " - "(rest %d)\n", idx, ofs, r, rest); + dev_dbg(&pci->dev, + "tbl %d: at %d size %d (rest %d)\n", + idx, ofs, r, rest); */ ((u32 *)dev->table.area)[(idx<<1) + 1] = cpu_to_le32(r | flag); dev->idx_table[idx].offset = ofs; @@ -528,7 +529,7 @@ static int snd_via82xx_codec_ready(struct via82xx *chip, int secondary) if (!((val = snd_via82xx_codec_xread(chip)) & VIA_REG_AC97_BUSY)) return val & 0xffff; } - snd_printk(KERN_ERR "codec_ready: codec %i is not ready [0x%x]\n", + dev_err(chip->card->dev, "codec_ready: codec %i is not ready [0x%x]\n", secondary, snd_via82xx_codec_xread(chip)); return -EIO; } @@ -587,7 +588,8 @@ static unsigned short snd_via82xx_codec_read(struct snd_ac97 *ac97, unsigned sho xval |= (reg & 0x7f) << VIA_REG_AC97_CMD_SHIFT; while (1) { if (again++ > 3) { - snd_printk(KERN_ERR "codec_read: codec %i is not valid [0x%x]\n", + dev_err(chip->card->dev, + "codec_read: codec %i is not valid [0x%x]\n", ac97->num, snd_via82xx_codec_xread(chip)); return 0xffff; } @@ -777,7 +779,9 @@ static int snd_via82xx_pcm_trigger(struct snd_pcm_substream *substream, int cmd) ((pos) < viadev->lastpos && ((pos) >= viadev->bufsize2 ||\ viadev->lastpos < viadev->bufsize2)) -static inline unsigned int calc_linear_pos(struct viadev *viadev, unsigned int idx, +static inline unsigned int calc_linear_pos(struct via82xx *chip, + struct viadev *viadev, + unsigned int idx, unsigned int count) { unsigned int size, base, res; @@ -790,7 +794,8 @@ static inline unsigned int calc_linear_pos(struct viadev *viadev, unsigned int i /* check the validity of the calculated position */ if (size < count) { - snd_printd(KERN_ERR "invalid via82xx_cur_ptr (size = %d, count = %d)\n", + dev_dbg(chip->card->dev, + "invalid via82xx_cur_ptr (size = %d, count = %d)\n", (int)size, (int)count); res = viadev->lastpos; } else { @@ -807,9 +812,9 @@ static inline unsigned int calc_linear_pos(struct viadev *viadev, unsigned int i } if (check_invalid_pos(viadev, res)) { #ifdef POINTER_DEBUG - printk(KERN_DEBUG "fail: idx = %i/%i, lastpos = 0x%x, " - "bufsize2 = 0x%x, offsize = 0x%x, size = 0x%x, " - "count = 0x%x\n", idx, viadev->tbl_entries, + dev_dbg(chip->card->dev, + "fail: idx = %i/%i, lastpos = 0x%x, bufsize2 = 0x%x, offsize = 0x%x, size = 0x%x, count = 0x%x\n", + idx, viadev->tbl_entries, viadev->lastpos, viadev->bufsize2, viadev->idx_table[idx].offset, viadev->idx_table[idx].size, count); @@ -817,8 +822,8 @@ static inline unsigned int calc_linear_pos(struct viadev *viadev, unsigned int i /* count register returns full size when end of buffer is reached */ res = base + size; if (check_invalid_pos(viadev, res)) { - snd_printd(KERN_ERR "invalid via82xx_cur_ptr (2), " - "using last valid pointer\n"); + dev_dbg(chip->card->dev, + "invalid via82xx_cur_ptr (2), using last valid pointer\n"); res = viadev->lastpos; } } @@ -850,7 +855,7 @@ static snd_pcm_uframes_t snd_via686_pcm_pointer(struct snd_pcm_substream *substr idx = 0; else /* CURR_PTR holds the address + 8 */ idx = ((ptr - (unsigned int)viadev->table.addr) / 8 - 1) % viadev->tbl_entries; - res = calc_linear_pos(viadev, idx, count); + res = calc_linear_pos(chip, viadev, idx, count); viadev->lastpos = res; /* remember the last position */ spin_unlock(&chip->reg_lock); @@ -889,13 +894,14 @@ static snd_pcm_uframes_t snd_via8233_pcm_pointer(struct snd_pcm_substream *subst idx = count >> 24; if (idx >= viadev->tbl_entries) { #ifdef POINTER_DEBUG - printk(KERN_DEBUG "fail: invalid idx = %i/%i\n", idx, + dev_dbg(chip->card->dev, + "fail: invalid idx = %i/%i\n", idx, viadev->tbl_entries); #endif res = viadev->lastpos; } else { count &= 0xffffff; - res = calc_linear_pos(viadev, idx, count); + res = calc_linear_pos(chip, viadev, idx, count); } } else { res = viadev->hwptr_done; @@ -1940,14 +1946,15 @@ static int snd_via686_create_gameport(struct via82xx *chip, unsigned char *legac r = request_region(JOYSTICK_ADDR, 8, "VIA686 gameport"); if (!r) { - printk(KERN_WARNING "via82xx: cannot reserve joystick port %#x\n", + dev_warn(chip->card->dev, "cannot reserve joystick port %#x\n", JOYSTICK_ADDR); return -EBUSY; } chip->gameport = gp = gameport_allocate_port(); if (!gp) { - printk(KERN_ERR "via82xx: cannot allocate memory for gameport\n"); + dev_err(chip->card->dev, + "cannot allocate memory for gameport\n"); release_and_free_resource(r); return -ENOMEM; } @@ -2016,7 +2023,8 @@ static int snd_via8233_init_misc(struct via82xx *chip) strcpy(sid.name, "PCM Playback Volume"); sid.iface = SNDRV_CTL_ELEM_IFACE_MIXER; if (! snd_ctl_find_id(chip->card, &sid)) { - snd_printd(KERN_INFO "Using DXS as PCM Playback\n"); + dev_info(chip->card->dev, + "Using DXS as PCM Playback\n"); err = snd_ctl_add(chip->card, snd_ctl_new1(&snd_via8233_pcmdxs_volume_control, chip)); if (err < 0) return err; @@ -2102,8 +2110,9 @@ static int snd_via686_init_misc(struct via82xx *chip) mpu_port, MPU401_INFO_INTEGRATED | MPU401_INFO_IRQ_HOOK, -1, &chip->rmidi) < 0) { - printk(KERN_WARNING "unable to initialize MPU-401" - " at 0x%lx, skipping\n", mpu_port); + dev_warn(chip->card->dev, + "unable to initialize MPU-401 at 0x%lx, skipping\n", + mpu_port); legacy &= ~VIA_FUNC_ENABLE_MIDI; } else { legacy &= ~VIA_FUNC_MIDI_IRQMASK; /* enable MIDI interrupt */ @@ -2203,7 +2212,8 @@ static int snd_via82xx_chip_init(struct via82xx *chip) } while (time_before(jiffies, end_time)); if ((val = snd_via82xx_codec_xread(chip)) & VIA_REG_AC97_BUSY) - snd_printk(KERN_ERR "AC'97 codec is not ready [0x%x]\n", val); + dev_err(chip->card->dev, + "AC'97 codec is not ready [0x%x]\n", val); #if 0 /* FIXME: we don't support the second codec yet so skip the detection now.. */ snd_via82xx_codec_xwrite(chip, VIA_REG_AC97_READ | @@ -2303,8 +2313,7 @@ static int snd_via82xx_resume(struct device *dev) pci_set_power_state(pci, PCI_D0); pci_restore_state(pci); if (pci_enable_device(pci) < 0) { - printk(KERN_ERR "via82xx: pci_enable_device failed, " - "disabling device\n"); + dev_err(dev, "pci_enable_device failed, disabling device\n"); snd_card_disconnect(card); return -EIO; } @@ -2417,7 +2426,7 @@ static int snd_via82xx_create(struct snd_card *card, snd_via8233_interrupt : snd_via686_interrupt, IRQF_SHARED, KBUILD_MODNAME, chip)) { - snd_printk(KERN_ERR "unable to grab IRQ %d\n", pci->irq); + dev_err(card->dev, "unable to grab IRQ %d\n", pci->irq); snd_via82xx_free(chip); return -EBUSY; } @@ -2441,8 +2450,6 @@ static int snd_via82xx_create(struct snd_card *card, * We call pci_set_master here because it does not hurt. */ pci_set_master(pci); - snd_card_set_dev(card, &pci->dev); - *r_via = chip; return 0; } @@ -2516,7 +2523,7 @@ static int check_dxs_list(struct pci_dev *pci, int revision) w = snd_pci_quirk_lookup(pci, dxs_whitelist); if (w) { - snd_printdd(KERN_INFO "via82xx: DXS white list for %s found\n", + dev_dbg(&pci->dev, "DXS white list for %s found\n", snd_pci_quirk_name(w)); return w->value; } @@ -2528,10 +2535,10 @@ static int check_dxs_list(struct pci_dev *pci, int revision) /* * not detected, try 48k rate only to be sure. */ - printk(KERN_INFO "via82xx: Assuming DXS channels with 48k fixed sample rate.\n"); - printk(KERN_INFO " Please try dxs_support=5 option\n"); - printk(KERN_INFO " and report if it works on your machine.\n"); - printk(KERN_INFO " For more details, read ALSA-Configuration.txt.\n"); + dev_info(&pci->dev, "Assuming DXS channels with 48k fixed sample rate.\n"); + dev_info(&pci->dev, " Please try dxs_support=5 option\n"); + dev_info(&pci->dev, " and report if it works on your machine.\n"); + dev_info(&pci->dev, " For more details, read ALSA-Configuration.txt.\n"); return VIA_DXS_48K; }; @@ -2544,7 +2551,7 @@ static int snd_via82xx_probe(struct pci_dev *pci, unsigned int i; int err; - err = snd_card_create(index, id, THIS_MODULE, 0, &card); + err = snd_card_new(&pci->dev, index, id, THIS_MODULE, 0, &card); if (err < 0) return err; @@ -2584,7 +2591,7 @@ static int snd_via82xx_probe(struct pci_dev *pci, strcpy(card->driver, "VIA8233"); break; default: - snd_printk(KERN_ERR "invalid card type %d\n", card_type); + dev_err(card->dev, "invalid card type %d\n", card_type); err = -EINVAL; goto __error; } diff --git a/sound/pci/via82xx_modem.c b/sound/pci/via82xx_modem.c index ca190283cbd..46a0526b1d7 100644 --- a/sound/pci/via82xx_modem.c +++ b/sound/pci/via82xx_modem.c @@ -312,7 +312,7 @@ static int build_via_table(struct viadev *dev, struct snd_pcm_substream *substre unsigned int addr; if (idx >= VIA_TABLE_SIZE) { - snd_printk(KERN_ERR "via82xx: too much table size!\n"); + dev_err(&pci->dev, "too much table size!\n"); return -EINVAL; } addr = snd_pcm_sgbuf_get_addr(substream, ofs); @@ -329,8 +329,9 @@ static int build_via_table(struct viadev *dev, struct snd_pcm_substream *substre } else flag = 0; /* period continues to the next */ /* - printk(KERN_DEBUG "via: tbl %d: at %d size %d " - "(rest %d)\n", idx, ofs, r, rest); + dev_dbg(&pci->dev, + "tbl %d: at %d size %d (rest %d)\n", + idx, ofs, r, rest); */ ((u32 *)dev->table.area)[(idx<<1) + 1] = cpu_to_le32(r | flag); dev->idx_table[idx].offset = ofs; @@ -382,7 +383,7 @@ static int snd_via82xx_codec_ready(struct via82xx_modem *chip, int secondary) if (!((val = snd_via82xx_codec_xread(chip)) & VIA_REG_AC97_BUSY)) return val & 0xffff; } - snd_printk(KERN_ERR "codec_ready: codec %i is not ready [0x%x]\n", + dev_err(chip->card->dev, "codec_ready: codec %i is not ready [0x%x]\n", secondary, snd_via82xx_codec_xread(chip)); return -EIO; } @@ -443,7 +444,8 @@ static unsigned short snd_via82xx_codec_read(struct snd_ac97 *ac97, unsigned sho xval |= (reg & 0x7f) << VIA_REG_AC97_CMD_SHIFT; while (1) { if (again++ > 3) { - snd_printk(KERN_ERR "codec_read: codec %i is not valid [0x%x]\n", + dev_err(chip->card->dev, + "codec_read: codec %i is not valid [0x%x]\n", ac97->num, snd_via82xx_codec_xread(chip)); return 0xffff; } @@ -560,7 +562,9 @@ static int snd_via82xx_pcm_trigger(struct snd_pcm_substream *substream, int cmd) ((pos) < viadev->lastpos && ((pos) >= viadev->bufsize2 ||\ viadev->lastpos < viadev->bufsize2)) -static inline unsigned int calc_linear_pos(struct viadev *viadev, unsigned int idx, +static inline unsigned int calc_linear_pos(struct via82xx_modem *chip, + struct viadev *viadev, + unsigned int idx, unsigned int count) { unsigned int size, res; @@ -570,20 +574,21 @@ static inline unsigned int calc_linear_pos(struct viadev *viadev, unsigned int i /* check the validity of the calculated position */ if (size < count) { - snd_printd(KERN_ERR "invalid via82xx_cur_ptr (size = %d, count = %d)\n", + dev_err(chip->card->dev, + "invalid via82xx_cur_ptr (size = %d, count = %d)\n", (int)size, (int)count); res = viadev->lastpos; } else if (check_invalid_pos(viadev, res)) { #ifdef POINTER_DEBUG - printk(KERN_DEBUG "fail: idx = %i/%i, lastpos = 0x%x, " - "bufsize2 = 0x%x, offsize = 0x%x, size = 0x%x, " - "count = 0x%x\n", idx, viadev->tbl_entries, viadev->lastpos, + dev_dbg(chip->card->dev, + "fail: idx = %i/%i, lastpos = 0x%x, bufsize2 = 0x%x, offsize = 0x%x, size = 0x%x, count = 0x%x\n", + idx, viadev->tbl_entries, viadev->lastpos, viadev->bufsize2, viadev->idx_table[idx].offset, viadev->idx_table[idx].size, count); #endif if (count && size < count) { - snd_printd(KERN_ERR "invalid via82xx_cur_ptr, " - "using last valid pointer\n"); + dev_dbg(chip->card->dev, + "invalid via82xx_cur_ptr, using last valid pointer\n"); res = viadev->lastpos; } else { if (! count) @@ -595,8 +600,8 @@ static inline unsigned int calc_linear_pos(struct viadev *viadev, unsigned int i */ res = viadev->idx_table[idx].offset + size; if (check_invalid_pos(viadev, res)) { - snd_printd(KERN_ERR "invalid via82xx_cur_ptr (2), " - "using last valid pointer\n"); + dev_dbg(chip->card->dev, + "invalid via82xx_cur_ptr (2), using last valid pointer\n"); res = viadev->lastpos; } } @@ -632,7 +637,7 @@ static snd_pcm_uframes_t snd_via686_pcm_pointer(struct snd_pcm_substream *substr else /* CURR_PTR holds the address + 8 */ idx = ((ptr - (unsigned int)viadev->table.addr) / 8 - 1) % viadev->tbl_entries; - res = calc_linear_pos(viadev, idx, count); + res = calc_linear_pos(chip, viadev, idx, count); spin_unlock(&chip->reg_lock); return bytes_to_frames(substream->runtime, res); @@ -991,7 +996,8 @@ static int snd_via82xx_chip_init(struct via82xx_modem *chip) } while (time_before(jiffies, end_time)); if ((val = snd_via82xx_codec_xread(chip)) & VIA_REG_AC97_BUSY) - snd_printk(KERN_ERR "AC'97 codec is not ready [0x%x]\n", val); + dev_err(chip->card->dev, + "AC'97 codec is not ready [0x%x]\n", val); snd_via82xx_codec_xwrite(chip, VIA_REG_AC97_READ | VIA_REG_AC97_SECONDARY_VALID | @@ -1054,8 +1060,7 @@ static int snd_via82xx_resume(struct device *dev) pci_set_power_state(pci, PCI_D0); pci_restore_state(pci); if (pci_enable_device(pci) < 0) { - printk(KERN_ERR "via82xx-modem: pci_enable_device failed, " - "disabling device\n"); + dev_err(dev, "pci_enable_device failed, disabling device\n"); snd_card_disconnect(card); return -EIO; } @@ -1137,7 +1142,7 @@ static int snd_via82xx_create(struct snd_card *card, chip->port = pci_resource_start(pci, 0); if (request_irq(pci->irq, snd_via82xx_interrupt, IRQF_SHARED, KBUILD_MODNAME, chip)) { - snd_printk(KERN_ERR "unable to grab IRQ %d\n", pci->irq); + dev_err(card->dev, "unable to grab IRQ %d\n", pci->irq); snd_via82xx_free(chip); return -EBUSY; } @@ -1161,8 +1166,6 @@ static int snd_via82xx_create(struct snd_card *card, * We call pci_set_master here because it does not hurt. */ pci_set_master(pci); - snd_card_set_dev(card, &pci->dev); - *r_via = chip; return 0; } @@ -1177,7 +1180,7 @@ static int snd_via82xx_probe(struct pci_dev *pci, unsigned int i; int err; - err = snd_card_create(index, id, THIS_MODULE, 0, &card); + err = snd_card_new(&pci->dev, index, id, THIS_MODULE, 0, &card); if (err < 0) return err; @@ -1188,7 +1191,7 @@ static int snd_via82xx_probe(struct pci_dev *pci, sprintf(card->shortname, "VIA 82XX modem"); break; default: - snd_printk(KERN_ERR "invalid card type %d\n", card_type); + dev_err(card->dev, "invalid card type %d\n", card_type); err = -EINVAL; goto __error; } diff --git a/sound/pci/vx222/vx222.c b/sound/pci/vx222/vx222.c index ab8a9b1bfb8..ff9074d2260 100644 --- a/sound/pci/vx222/vx222.c +++ b/sound/pci/vx222/vx222.c @@ -170,7 +170,7 @@ static int snd_vx222_create(struct snd_card *card, struct pci_dev *pci, if (request_irq(pci->irq, snd_vx_irq_handler, IRQF_SHARED, KBUILD_MODNAME, chip)) { - snd_printk(KERN_ERR "unable to grab IRQ %d\n", pci->irq); + dev_err(card->dev, "unable to grab IRQ %d\n", pci->irq); snd_vx222_free(chip); return -EBUSY; } @@ -181,8 +181,6 @@ static int snd_vx222_create(struct snd_card *card, struct pci_dev *pci, return err; } - snd_card_set_dev(card, &pci->dev); - *rchip = vx; return 0; } @@ -204,7 +202,8 @@ static int snd_vx222_probe(struct pci_dev *pci, return -ENOENT; } - err = snd_card_create(index[dev], id[dev], THIS_MODULE, 0, &card); + err = snd_card_new(&pci->dev, index[dev], id[dev], THIS_MODULE, + 0, &card); if (err < 0) return err; @@ -229,7 +228,7 @@ static int snd_vx222_probe(struct pci_dev *pci, sprintf(card->longname, "%s at 0x%lx & 0x%lx, irq %i", card->shortname, vx->port[0], vx->port[1], vx->core.irq); - snd_printdd("%s at 0x%lx & 0x%lx, irq %i\n", + dev_dbg(card->dev, "%s at 0x%lx & 0x%lx, irq %i\n", card->shortname, vx->port[0], vx->port[1], vx->core.irq); #ifdef SND_VX_FW_LOADER @@ -280,8 +279,7 @@ static int snd_vx222_resume(struct device *dev) pci_set_power_state(pci, PCI_D0); pci_restore_state(pci); if (pci_enable_device(pci) < 0) { - printk(KERN_ERR "vx222: pci_enable_device failed, " - "disabling device\n"); + dev_err(dev, "pci_enable_device failed, disabling device\n"); snd_card_disconnect(card); return -EIO; } diff --git a/sound/pci/vx222/vx222_ops.c b/sound/pci/vx222/vx222_ops.c index a69e774d0b1..2d1570273e9 100644 --- a/sound/pci/vx222/vx222_ops.c +++ b/sound/pci/vx222/vx222_ops.c @@ -108,7 +108,7 @@ static void vx2_outb(struct vx_core *chip, int offset, unsigned char val) { outb(val, vx2_reg_addr(chip, offset)); /* - printk(KERN_DEBUG "outb: %x -> %x\n", val, vx2_reg_addr(chip, offset)); + dev_dbg(chip->card->dev, "outb: %x -> %x\n", val, vx2_reg_addr(chip, offset)); */ } @@ -129,7 +129,7 @@ static unsigned int vx2_inl(struct vx_core *chip, int offset) static void vx2_outl(struct vx_core *chip, int offset, unsigned int val) { /* - printk(KERN_DEBUG "outl: %x -> %x\n", val, vx2_reg_addr(chip, offset)); + dev_dbg(chip->card->dev, "outl: %x -> %x\n", val, vx2_reg_addr(chip, offset)); */ outl(val, vx2_reg_addr(chip, offset)); } @@ -173,7 +173,7 @@ static int vx2_test_xilinx(struct vx_core *_chip) struct snd_vx222 *chip = (struct snd_vx222 *)_chip; unsigned int data; - snd_printdd("testing xilinx...\n"); + dev_dbg(_chip->card->dev, "testing xilinx...\n"); /* This test uses several write/read sequences on TEST0 and TEST1 bits * to figure out whever or not the xilinx was correctly loaded */ @@ -183,7 +183,7 @@ static int vx2_test_xilinx(struct vx_core *_chip) vx_inl(chip, ISR); data = vx_inl(chip, STATUS); if ((data & VX_STATUS_VAL_TEST0_MASK) == VX_STATUS_VAL_TEST0_MASK) { - snd_printdd("bad!\n"); + dev_dbg(_chip->card->dev, "bad!\n"); return -ENODEV; } @@ -192,7 +192,7 @@ static int vx2_test_xilinx(struct vx_core *_chip) vx_inl(chip, ISR); data = vx_inl(chip, STATUS); if (! (data & VX_STATUS_VAL_TEST0_MASK)) { - snd_printdd("bad! #2\n"); + dev_dbg(_chip->card->dev, "bad! #2\n"); return -ENODEV; } @@ -203,7 +203,7 @@ static int vx2_test_xilinx(struct vx_core *_chip) vx_inl(chip, ISR); data = vx_inl(chip, STATUS); if ((data & VX_STATUS_VAL_TEST1_MASK) == VX_STATUS_VAL_TEST1_MASK) { - snd_printdd("bad! #3\n"); + dev_dbg(_chip->card->dev, "bad! #3\n"); return -ENODEV; } @@ -212,11 +212,11 @@ static int vx2_test_xilinx(struct vx_core *_chip) vx_inl(chip, ISR); data = vx_inl(chip, STATUS); if (! (data & VX_STATUS_VAL_TEST1_MASK)) { - snd_printdd("bad! #4\n"); + dev_dbg(_chip->card->dev, "bad! #4\n"); return -ENODEV; } } - snd_printdd("ok, xilinx fine.\n"); + dev_dbg(_chip->card->dev, "ok, xilinx fine.\n"); return 0; } @@ -397,7 +397,8 @@ static int vx2_load_xilinx_binary(struct vx_core *chip, const struct firmware *x i = vx_inl(chip, GPIOC); if (i & 0x0100) return 0; - snd_printk(KERN_ERR "vx222: xilinx test failed after load, GPIOC=0x%x\n", i); + dev_err(chip->card->dev, + "xilinx test failed after load, GPIOC=0x%x\n", i); return -EINVAL; } diff --git a/sound/pci/ymfpci/ymfpci.c b/sound/pci/ymfpci/ymfpci.c index e8932b2e4a5..82eed164b27 100644 --- a/sound/pci/ymfpci/ymfpci.c +++ b/sound/pci/ymfpci/ymfpci.c @@ -106,7 +106,8 @@ static int snd_ymfpci_create_gameport(struct snd_ymfpci *chip, int dev, break; } if (!r) { - printk(KERN_ERR "ymfpci: no gameport ports available\n"); + dev_err(chip->card->dev, + "no gameport ports available\n"); return -EBUSY; } } @@ -116,19 +117,22 @@ static int snd_ymfpci_create_gameport(struct snd_ymfpci *chip, int dev, case 0x204: legacy_ctrl2 |= 2 << 6; break; case 0x205: legacy_ctrl2 |= 3 << 6; break; default: - printk(KERN_ERR "ymfpci: invalid joystick port %#x", io_port); + dev_err(chip->card->dev, + "invalid joystick port %#x", io_port); return -EINVAL; } } if (!r && !(r = request_region(io_port, 1, "YMFPCI gameport"))) { - printk(KERN_ERR "ymfpci: joystick port %#x is in use.\n", io_port); + dev_err(chip->card->dev, + "joystick port %#x is in use.\n", io_port); return -EBUSY; } chip->gameport = gp = gameport_allocate_port(); if (!gp) { - printk(KERN_ERR "ymfpci: cannot allocate memory for gameport\n"); + dev_err(chip->card->dev, + "cannot allocate memory for gameport\n"); release_and_free_resource(r); return -ENOMEM; } @@ -187,7 +191,8 @@ static int snd_card_ymfpci_probe(struct pci_dev *pci, return -ENOENT; } - err = snd_card_create(index[dev], id[dev], THIS_MODULE, 0, &card); + err = snd_card_new(&pci->dev, index[dev], id[dev], THIS_MODULE, + 0, &card); if (err < 0) return err; @@ -313,7 +318,9 @@ static int snd_card_ymfpci_probe(struct pci_dev *pci, MPU401_INFO_INTEGRATED | MPU401_INFO_IRQ_HOOK, -1, &chip->rawmidi)) < 0) { - printk(KERN_WARNING "ymfpci: cannot initialize MPU401 at 0x%lx, skipping...\n", mpu_port[dev]); + dev_warn(card->dev, + "cannot initialize MPU401 at 0x%lx, skipping...\n", + mpu_port[dev]); legacy_ctrl &= ~YMFPCI_LEGACY_MIEN; /* disable MPU401 irq */ pci_write_config_word(pci, PCIR_DSXG_LEGACY, legacy_ctrl); } @@ -323,12 +330,14 @@ static int snd_card_ymfpci_probe(struct pci_dev *pci, fm_port[dev], fm_port[dev] + 2, OPL3_HW_OPL3, 1, &opl3)) < 0) { - printk(KERN_WARNING "ymfpci: cannot initialize FM OPL3 at 0x%lx, skipping...\n", fm_port[dev]); + dev_warn(card->dev, + "cannot initialize FM OPL3 at 0x%lx, skipping...\n", + fm_port[dev]); legacy_ctrl &= ~YMFPCI_LEGACY_FMEN; pci_write_config_word(pci, PCIR_DSXG_LEGACY, legacy_ctrl); } else if ((err = snd_opl3_hwdep_new(opl3, 0, 1, NULL)) < 0) { snd_card_free(card); - snd_printk(KERN_ERR "cannot create opl3 hwdep\n"); + dev_err(card->dev, "cannot create opl3 hwdep\n"); return err; } } diff --git a/sound/pci/ymfpci/ymfpci_main.c b/sound/pci/ymfpci/ymfpci_main.c index d591c154fc5..81c916a5eb9 100644 --- a/sound/pci/ymfpci/ymfpci_main.c +++ b/sound/pci/ymfpci/ymfpci_main.c @@ -86,7 +86,9 @@ static int snd_ymfpci_codec_ready(struct snd_ymfpci *chip, int secondary) return 0; schedule_timeout_uninterruptible(1); } while (time_before(jiffies, end_time)); - snd_printk(KERN_ERR "codec_ready: codec %i is not ready [0x%x]\n", secondary, snd_ymfpci_readw(chip, reg)); + dev_err(chip->card->dev, + "codec_ready: codec %i is not ready [0x%x]\n", + secondary, snd_ymfpci_readw(chip, reg)); return -EBUSY; } @@ -319,7 +321,7 @@ static void snd_ymfpci_pcm_interrupt(struct snd_ymfpci *chip, struct snd_ymfpci_ ypcm->last_pos = pos; if (ypcm->period_pos >= ypcm->period_size) { /* - printk(KERN_DEBUG + dev_dbg(chip->card->dev, "done - active_bank = 0x%x, start = 0x%x\n", chip->active_bank, voice->bank[chip->active_bank].start); @@ -372,7 +374,7 @@ static void snd_ymfpci_pcm_capture_interrupt(struct snd_pcm_substream *substream if (ypcm->period_pos >= ypcm->period_size) { ypcm->period_pos %= ypcm->period_size; /* - printk(KERN_DEBUG + dev_dbg(chip->card->dev, "done - active_bank = 0x%x, start = 0x%x\n", chip->active_bank, voice->bank[chip->active_bank].start); @@ -2067,7 +2069,8 @@ static int snd_ymfpci_request_firmware(struct snd_ymfpci *chip) &chip->pci->dev); if (err >= 0) { if (chip->dsp_microcode->size != YDSXG_DSPLENGTH) { - snd_printk(KERN_ERR "DSP microcode has wrong size\n"); + dev_err(chip->card->dev, + "DSP microcode has wrong size\n"); err = -EINVAL; } } @@ -2082,8 +2085,8 @@ static int snd_ymfpci_request_firmware(struct snd_ymfpci *chip) &chip->pci->dev); if (err >= 0) { if (chip->controller_microcode->size != YDSXG_CTRLLENGTH) { - snd_printk(KERN_ERR "controller microcode" - " has wrong size\n"); + dev_err(chip->card->dev, + "controller microcode has wrong size\n"); err = -EINVAL; } } @@ -2360,8 +2363,7 @@ static int snd_ymfpci_resume(struct device *dev) pci_set_power_state(pci, PCI_D0); pci_restore_state(pci); if (pci_enable_device(pci) < 0) { - printk(KERN_ERR "ymfpci: pci_enable_device failed, " - "disabling device\n"); + dev_err(dev, "pci_enable_device failed, disabling device\n"); snd_card_disconnect(card); return -EIO; } @@ -2433,13 +2435,15 @@ int snd_ymfpci_create(struct snd_card *card, chip->src441_used = -1; if ((chip->res_reg_area = request_mem_region(chip->reg_area_phys, 0x8000, "YMFPCI")) == NULL) { - snd_printk(KERN_ERR "unable to grab memory region 0x%lx-0x%lx\n", chip->reg_area_phys, chip->reg_area_phys + 0x8000 - 1); + dev_err(chip->card->dev, + "unable to grab memory region 0x%lx-0x%lx\n", + chip->reg_area_phys, chip->reg_area_phys + 0x8000 - 1); snd_ymfpci_free(chip); return -EBUSY; } if (request_irq(pci->irq, snd_ymfpci_interrupt, IRQF_SHARED, KBUILD_MODNAME, chip)) { - snd_printk(KERN_ERR "unable to grab IRQ %d\n", pci->irq); + dev_err(chip->card->dev, "unable to grab IRQ %d\n", pci->irq); snd_ymfpci_free(chip); return -EBUSY; } @@ -2453,7 +2457,7 @@ int snd_ymfpci_create(struct snd_card *card, err = snd_ymfpci_request_firmware(chip); if (err < 0) { - snd_printk(KERN_ERR "firmware request failed: %d\n", err); + dev_err(chip->card->dev, "firmware request failed: %d\n", err); snd_ymfpci_free(chip); return err; } @@ -2487,8 +2491,6 @@ int snd_ymfpci_create(struct snd_card *card, snd_ymfpci_proc_init(card, chip); - snd_card_set_dev(card, &pci->dev); - *rchip = chip; return 0; } diff --git a/sound/pcmcia/pdaudiocf/pdaudiocf.c b/sound/pcmcia/pdaudiocf/pdaudiocf.c index 8f489de5c4c..56bda124cd4 100644 --- a/sound/pcmcia/pdaudiocf/pdaudiocf.c +++ b/sound/pcmcia/pdaudiocf/pdaudiocf.c @@ -112,7 +112,8 @@ static int snd_pdacf_probe(struct pcmcia_device *link) return -ENODEV; /* disabled explicitly */ /* ok, create a card instance */ - err = snd_card_create(index[i], id[i], THIS_MODULE, 0, &card); + err = snd_card_new(&link->dev, index[i], id[i], THIS_MODULE, + 0, &card); if (err < 0) { snd_printk(KERN_ERR "pdacf: cannot create a card instance\n"); return err; @@ -131,8 +132,6 @@ static int snd_pdacf_probe(struct pcmcia_device *link) return err; } - snd_card_set_dev(card, &link->dev); - pdacf->index = i; card_list[i] = card; diff --git a/sound/pcmcia/vx/vxpocket.c b/sound/pcmcia/vx/vxpocket.c index d4db7ecaa6b..786e7e139c9 100644 --- a/sound/pcmcia/vx/vxpocket.c +++ b/sound/pcmcia/vx/vxpocket.c @@ -238,7 +238,6 @@ static int vxpocket_config(struct pcmcia_device *link) goto failed; chip->dev = &link->dev; - snd_card_set_dev(chip->card, chip->dev); if (snd_vxpocket_assign_resources(chip, link->resource[0]->start, link->irq) < 0) @@ -307,7 +306,8 @@ static int vxpocket_probe(struct pcmcia_device *p_dev) return -ENODEV; /* disabled explicitly */ /* ok, create a card instance */ - err = snd_card_create(index[i], id[i], THIS_MODULE, 0, &card); + err = snd_card_new(&p_dev->dev, index[i], id[i], THIS_MODULE, + 0, &card); if (err < 0) { snd_printk(KERN_ERR "vxpocket: cannot create a card instance\n"); return err; diff --git a/sound/ppc/powermac.c b/sound/ppc/powermac.c index 8abb521b481..350a7c8f86d 100644 --- a/sound/ppc/powermac.c +++ b/sound/ppc/powermac.c @@ -58,7 +58,7 @@ static int snd_pmac_probe(struct platform_device *devptr) char *name_ext; int err; - err = snd_card_create(index, id, THIS_MODULE, 0, &card); + err = snd_card_new(&devptr->dev, index, id, THIS_MODULE, 0, &card); if (err < 0) return err; @@ -122,8 +122,6 @@ static int snd_pmac_probe(struct platform_device *devptr) if (enable_beep) snd_pmac_attach_beep(chip); - snd_card_set_dev(card, &devptr->dev); - if ((err = snd_card_register(card)) < 0) goto __error; diff --git a/sound/ppc/snd_ps3.c b/sound/ppc/snd_ps3.c index ebb76f2d90d..58f292a87f9 100644 --- a/sound/ppc/snd_ps3.c +++ b/sound/ppc/snd_ps3.c @@ -984,7 +984,8 @@ static int snd_ps3_driver_probe(struct ps3_system_bus_device *dev) } /* create card instance */ - ret = snd_card_create(index, id, THIS_MODULE, 0, &the_card.card); + ret = snd_card_new(&dev->core, index, id, THIS_MODULE, + 0, &the_card.card); if (ret < 0) goto clean_irq; @@ -1052,7 +1053,6 @@ static int snd_ps3_driver_probe(struct ps3_system_bus_device *dev) snd_ps3_init_avsetting(&the_card); /* register the card */ - snd_card_set_dev(the_card.card, &dev->core); ret = snd_card_register(the_card.card); if (ret < 0) goto clean_dma_map; diff --git a/sound/sh/aica.c b/sound/sh/aica.c index 78a369785a9..47849eaf266 100644 --- a/sound/sh/aica.c +++ b/sound/sh/aica.c @@ -608,8 +608,8 @@ static int snd_aica_probe(struct platform_device *devptr) dreamcastcard = kmalloc(sizeof(struct snd_card_aica), GFP_KERNEL); if (unlikely(!dreamcastcard)) return -ENOMEM; - err = snd_card_create(index, SND_AICA_DRIVER, THIS_MODULE, 0, - &dreamcastcard->card); + err = snd_card_new(&devptr->dev, index, SND_AICA_DRIVER, + THIS_MODULE, 0, &dreamcastcard->card); if (unlikely(err < 0)) { kfree(dreamcastcard); return err; @@ -624,7 +624,6 @@ static int snd_aica_probe(struct platform_device *devptr) err = snd_aicapcmchip(dreamcastcard, 0); if (unlikely(err < 0)) goto freedreamcast; - snd_card_set_dev(dreamcastcard->card, &devptr->dev); dreamcastcard->timer.data = 0; dreamcastcard->channel = NULL; /* Add basic controls */ diff --git a/sound/sh/sh_dac_audio.c b/sound/sh/sh_dac_audio.c index 7c9422c4fc0..d1fb74dabbd 100644 --- a/sound/sh/sh_dac_audio.c +++ b/sound/sh/sh_dac_audio.c @@ -396,7 +396,7 @@ static int snd_sh_dac_probe(struct platform_device *devptr) struct snd_card *card; int err; - err = snd_card_create(index, id, THIS_MODULE, 0, &card); + err = snd_card_new(&devptr->dev, index, id, THIS_MODULE, 0, &card); if (err < 0) { snd_printk(KERN_ERR "cannot allocate the card\n"); return err; diff --git a/sound/soc/Kconfig b/sound/soc/Kconfig index d62ce483a44..0060b31cc3f 100644 --- a/sound/soc/Kconfig +++ b/sound/soc/Kconfig @@ -50,6 +50,7 @@ source "sound/soc/pxa/Kconfig" source "sound/soc/samsung/Kconfig" source "sound/soc/s6000/Kconfig" source "sound/soc/sh/Kconfig" +source "sound/soc/sirf/Kconfig" source "sound/soc/spear/Kconfig" source "sound/soc/tegra/Kconfig" source "sound/soc/txx9/Kconfig" diff --git a/sound/soc/Makefile b/sound/soc/Makefile index 62a1822e77b..5f1df02984f 100644 --- a/sound/soc/Makefile +++ b/sound/soc/Makefile @@ -27,6 +27,7 @@ obj-$(CONFIG_SND_SOC) += pxa/ obj-$(CONFIG_SND_SOC) += samsung/ obj-$(CONFIG_SND_SOC) += s6000/ obj-$(CONFIG_SND_SOC) += sh/ +obj-$(CONFIG_SND_SOC) += sirf/ obj-$(CONFIG_SND_SOC) += spear/ obj-$(CONFIG_SND_SOC) += tegra/ obj-$(CONFIG_SND_SOC) += txx9/ diff --git a/sound/soc/atmel/Kconfig b/sound/soc/atmel/Kconfig index e634eb78ed0..4789619a52d 100644 --- a/sound/soc/atmel/Kconfig +++ b/sound/soc/atmel/Kconfig @@ -58,6 +58,6 @@ config SND_AT91_SOC_AFEB9260 depends on ARCH_AT91 && ATMEL_SSC && ARCH_AT91 && MACH_AFEB9260 && SND_ATMEL_SOC select SND_ATMEL_SOC_PDC select SND_ATMEL_SOC_SSC - select SND_SOC_TLV320AIC23 + select SND_SOC_TLV320AIC23_I2C help Say Y here to support sound on AFEB9260 board. diff --git a/sound/soc/atmel/atmel_ssc_dai.c b/sound/soc/atmel/atmel_ssc_dai.c index 1ead3c977a5..de433cfd044 100644 --- a/sound/soc/atmel/atmel_ssc_dai.c +++ b/sound/soc/atmel/atmel_ssc_dai.c @@ -341,6 +341,7 @@ static int atmel_ssc_hw_params(struct snd_pcm_substream *substream, { int id = dai->id; struct atmel_ssc_info *ssc_p = &ssc_info[id]; + struct ssc_device *ssc = ssc_p->ssc; struct atmel_pcm_dma_params *dma_params; int dir, channels, bits; u32 tfmr, rfmr, tcmr, rcmr; @@ -466,7 +467,8 @@ static int atmel_ssc_hw_params(struct snd_pcm_substream *substream, | SSC_BF(RCMR_START, start_event) | SSC_BF(RCMR_CKI, SSC_CKI_RISING) | SSC_BF(RCMR_CKO, SSC_CKO_NONE) - | SSC_BF(RCMR_CKS, SSC_CKS_CLOCK); + | SSC_BF(RCMR_CKS, ssc->clk_from_rk_pin ? + SSC_CKS_PIN : SSC_CKS_CLOCK); rfmr = SSC_BF(RFMR_FSEDGE, SSC_FSEDGE_POSITIVE) | SSC_BF(RFMR_FSOS, SSC_FSOS_NONE) @@ -481,7 +483,8 @@ static int atmel_ssc_hw_params(struct snd_pcm_substream *substream, | SSC_BF(TCMR_START, start_event) | SSC_BF(TCMR_CKI, SSC_CKI_FALLING) | SSC_BF(TCMR_CKO, SSC_CKO_NONE) - | SSC_BF(TCMR_CKS, SSC_CKS_PIN); + | SSC_BF(TCMR_CKS, ssc->clk_from_rk_pin ? + SSC_CKS_CLOCK : SSC_CKS_PIN); tfmr = SSC_BF(TFMR_FSEDGE, SSC_FSEDGE_POSITIVE) | SSC_BF(TFMR_FSDEN, 0) @@ -550,7 +553,8 @@ static int atmel_ssc_hw_params(struct snd_pcm_substream *substream, | SSC_BF(RCMR_START, SSC_START_RISING_RF) | SSC_BF(RCMR_CKI, SSC_CKI_RISING) | SSC_BF(RCMR_CKO, SSC_CKO_NONE) - | SSC_BF(RCMR_CKS, SSC_CKS_PIN); + | SSC_BF(RCMR_CKS, ssc->clk_from_rk_pin ? + SSC_CKS_PIN : SSC_CKS_CLOCK); rfmr = SSC_BF(RFMR_FSEDGE, SSC_FSEDGE_POSITIVE) | SSC_BF(RFMR_FSOS, SSC_FSOS_NONE) @@ -565,7 +569,8 @@ static int atmel_ssc_hw_params(struct snd_pcm_substream *substream, | SSC_BF(TCMR_START, SSC_START_RISING_RF) | SSC_BF(TCMR_CKI, SSC_CKI_FALLING) | SSC_BF(TCMR_CKO, SSC_CKO_NONE) - | SSC_BF(TCMR_CKS, SSC_CKS_PIN); + | SSC_BF(RCMR_CKS, ssc->clk_from_rk_pin ? + SSC_CKS_CLOCK : SSC_CKS_PIN); tfmr = SSC_BF(TFMR_FSEDGE, SSC_FSEDGE_POSITIVE) | SSC_BF(TFMR_FSDEN, 0) diff --git a/sound/soc/atmel/sam9g20_wm8731.c b/sound/soc/atmel/sam9g20_wm8731.c index f15bff1548f..174bd546c08 100644 --- a/sound/soc/atmel/sam9g20_wm8731.c +++ b/sound/soc/atmel/sam9g20_wm8731.c @@ -155,25 +155,14 @@ static int at91sam9g20ek_wm8731_init(struct snd_soc_pcm_runtime *rtd) return ret; } - /* Add specific widgets */ - snd_soc_dapm_new_controls(dapm, at91sam9g20ek_dapm_widgets, - ARRAY_SIZE(at91sam9g20ek_dapm_widgets)); - /* Set up specific audio path interconnects */ - snd_soc_dapm_add_routes(dapm, intercon, ARRAY_SIZE(intercon)); - /* not connected */ snd_soc_dapm_nc_pin(dapm, "RLINEIN"); snd_soc_dapm_nc_pin(dapm, "LLINEIN"); -#ifdef ENABLE_MIC_INPUT - snd_soc_dapm_enable_pin(dapm, "Int Mic"); -#else - snd_soc_dapm_nc_pin(dapm, "Int Mic"); +#ifndef ENABLE_MIC_INPUT + snd_soc_dapm_nc_pin(&rtd->card->dapm, "Int Mic"); #endif - /* always connected */ - snd_soc_dapm_enable_pin(dapm, "Ext Spk"); - return 0; } @@ -194,6 +183,11 @@ static struct snd_soc_card snd_soc_at91sam9g20ek = { .dai_link = &at91sam9g20ek_dai, .num_links = 1, .set_bias_level = at91sam9g20ek_set_bias_level, + + .dapm_widgets = at91sam9g20ek_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(at91sam9g20ek_dapm_widgets), + .dapm_routes = intercon, + .num_dapm_routes = ARRAY_SIZE(intercon), }; static int at91sam9g20ek_audio_probe(struct platform_device *pdev) diff --git a/sound/soc/blackfin/Kconfig b/sound/soc/blackfin/Kconfig index 4544d8eb145..6347d591013 100644 --- a/sound/soc/blackfin/Kconfig +++ b/sound/soc/blackfin/Kconfig @@ -14,7 +14,8 @@ config SND_BF5XX_SOC_SSM2602 depends on SND_BF5XX_I2S && SND_SOC_I2C_AND_SPI select SND_BF5XX_SOC_I2S if !BF60x select SND_BF6XX_SOC_I2S if BF60x - select SND_SOC_SSM2602 + select SND_SOC_SSM2602_SPI if SPI_MASTER + select SND_SOC_SSM2602_I2C if I2C help Say Y if you want to add support for the Analog Devices SSM2602 Audio Codec Add-On Card. @@ -46,7 +47,8 @@ config SND_SOC_BFIN_EVAL_ADAV80X tristate "Support for the EVAL-ADAV80X boards on Blackfin eval boards" depends on SND_BF5XX_I2S && SND_SOC_I2C_AND_SPI select SND_BF5XX_SOC_I2S - select SND_SOC_ADAV80X + select SND_SOC_ADAV801 if SPI_MASTER + select SND_SOC_ADAV803 if I2C help Say Y if you want to add support for the Analog Devices EVAL-ADAV801 or EVAL-ADAV803 board connected to one of the Blackfin evaluation boards @@ -67,7 +69,8 @@ config SND_BF5XX_SOC_AD193X tristate "SoC AD193X Audio support for Blackfin" depends on SND_BF5XX_I2S && SND_SOC_I2C_AND_SPI select SND_BF5XX_SOC_I2S - select SND_SOC_AD193X + select SND_SOC_AD193X_I2C if I2C + select SND_SOC_AD193X_SPI if SPI_MASTER help Say Y if you want to add support for AD193X codec on Blackfin. This driver supports AD1936, AD1937, AD1938 and AD1939. diff --git a/sound/soc/cirrus/Kconfig b/sound/soc/cirrus/Kconfig index 06f938deda1..5477c547592 100644 --- a/sound/soc/cirrus/Kconfig +++ b/sound/soc/cirrus/Kconfig @@ -1,6 +1,6 @@ config SND_EP93XX_SOC tristate "SoC Audio support for the Cirrus Logic EP93xx series" - depends on (ARCH_EP93XX || COMPILE_TEST) && SND_SOC + depends on ARCH_EP93XX || COMPILE_TEST select SND_SOC_GENERIC_DMAENGINE_PCM help Say Y or M if you want to add support for codecs attached to @@ -18,7 +18,7 @@ config SND_EP93XX_SOC_SNAPPERCL15 tristate "SoC Audio support for Bluewater Systems Snapper CL15 module" depends on SND_EP93XX_SOC && MACH_SNAPPER_CL15 select SND_EP93XX_SOC_I2S - select SND_SOC_TLV320AIC23 + select SND_SOC_TLV320AIC23_I2C help Say Y or M here if you want to add support for I2S audio on the Bluewater Systems Snapper CL15 module. diff --git a/sound/soc/cirrus/snappercl15.c b/sound/soc/cirrus/snappercl15.c index 29238a7476d..5b68b106cfc 100644 --- a/sound/soc/cirrus/snappercl15.c +++ b/sound/soc/cirrus/snappercl15.c @@ -65,18 +65,6 @@ static const struct snd_soc_dapm_route audio_map[] = { {"MICIN", NULL, "Mic Jack"}, }; -static int snappercl15_tlv320aic23_init(struct snd_soc_pcm_runtime *rtd) -{ - struct snd_soc_codec *codec = rtd->codec; - struct snd_soc_dapm_context *dapm = &codec->dapm; - - snd_soc_dapm_new_controls(dapm, tlv320aic23_dapm_widgets, - ARRAY_SIZE(tlv320aic23_dapm_widgets)); - - snd_soc_dapm_add_routes(dapm, audio_map, ARRAY_SIZE(audio_map)); - return 0; -} - static struct snd_soc_dai_link snappercl15_dai = { .name = "tlv320aic23", .stream_name = "AIC23", @@ -84,7 +72,6 @@ static struct snd_soc_dai_link snappercl15_dai = { .codec_dai_name = "tlv320aic23-hifi", .codec_name = "tlv320aic23-codec.0-001a", .platform_name = "ep93xx-i2s", - .init = snappercl15_tlv320aic23_init, .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_IF | SND_SOC_DAIFMT_CBS_CFS, .ops = &snappercl15_ops, @@ -95,6 +82,11 @@ static struct snd_soc_card snd_soc_snappercl15 = { .owner = THIS_MODULE, .dai_link = &snappercl15_dai, .num_links = 1, + + .dapm_widgets = tlv320aic23_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(tlv320aic23_dapm_widgets), + .dapm_routes = audio_map, + .num_dapm_routes = ARRAY_SIZE(audio_map), }; static int snappercl15_probe(struct platform_device *pdev) diff --git a/sound/soc/codecs/88pm860x-codec.c b/sound/soc/codecs/88pm860x-codec.c index 647a72cda00..b07e17160f9 100644 --- a/sound/soc/codecs/88pm860x-codec.c +++ b/sound/soc/codecs/88pm860x-codec.c @@ -448,38 +448,38 @@ static const char *pm860x_opamp_texts[] = {"-50%", "-25%", "0%", "75%"}; static const char *pm860x_pa_texts[] = {"-33%", "0%", "33%", "66%"}; -static const struct soc_enum pm860x_hs1_opamp_enum = - SOC_ENUM_SINGLE(PM860X_HS1_CTRL, 5, 4, pm860x_opamp_texts); +static SOC_ENUM_SINGLE_DECL(pm860x_hs1_opamp_enum, + PM860X_HS1_CTRL, 5, pm860x_opamp_texts); -static const struct soc_enum pm860x_hs2_opamp_enum = - SOC_ENUM_SINGLE(PM860X_HS2_CTRL, 5, 4, pm860x_opamp_texts); +static SOC_ENUM_SINGLE_DECL(pm860x_hs2_opamp_enum, + PM860X_HS2_CTRL, 5, pm860x_opamp_texts); -static const struct soc_enum pm860x_hs1_pa_enum = - SOC_ENUM_SINGLE(PM860X_HS1_CTRL, 3, 4, pm860x_pa_texts); +static SOC_ENUM_SINGLE_DECL(pm860x_hs1_pa_enum, + PM860X_HS1_CTRL, 3, pm860x_pa_texts); -static const struct soc_enum pm860x_hs2_pa_enum = - SOC_ENUM_SINGLE(PM860X_HS2_CTRL, 3, 4, pm860x_pa_texts); +static SOC_ENUM_SINGLE_DECL(pm860x_hs2_pa_enum, + PM860X_HS2_CTRL, 3, pm860x_pa_texts); -static const struct soc_enum pm860x_lo1_opamp_enum = - SOC_ENUM_SINGLE(PM860X_LO1_CTRL, 5, 4, pm860x_opamp_texts); +static SOC_ENUM_SINGLE_DECL(pm860x_lo1_opamp_enum, + PM860X_LO1_CTRL, 5, pm860x_opamp_texts); -static const struct soc_enum pm860x_lo2_opamp_enum = - SOC_ENUM_SINGLE(PM860X_LO2_CTRL, 5, 4, pm860x_opamp_texts); +static SOC_ENUM_SINGLE_DECL(pm860x_lo2_opamp_enum, + PM860X_LO2_CTRL, 5, pm860x_opamp_texts); -static const struct soc_enum pm860x_lo1_pa_enum = - SOC_ENUM_SINGLE(PM860X_LO1_CTRL, 3, 4, pm860x_pa_texts); +static SOC_ENUM_SINGLE_DECL(pm860x_lo1_pa_enum, + PM860X_LO1_CTRL, 3, pm860x_pa_texts); -static const struct soc_enum pm860x_lo2_pa_enum = - SOC_ENUM_SINGLE(PM860X_LO2_CTRL, 3, 4, pm860x_pa_texts); +static SOC_ENUM_SINGLE_DECL(pm860x_lo2_pa_enum, + PM860X_LO2_CTRL, 3, pm860x_pa_texts); -static const struct soc_enum pm860x_spk_pa_enum = - SOC_ENUM_SINGLE(PM860X_EAR_CTRL_1, 5, 4, pm860x_pa_texts); +static SOC_ENUM_SINGLE_DECL(pm860x_spk_pa_enum, + PM860X_EAR_CTRL_1, 5, pm860x_pa_texts); -static const struct soc_enum pm860x_ear_pa_enum = - SOC_ENUM_SINGLE(PM860X_EAR_CTRL_2, 0, 4, pm860x_pa_texts); +static SOC_ENUM_SINGLE_DECL(pm860x_ear_pa_enum, + PM860X_EAR_CTRL_2, 0, pm860x_pa_texts); -static const struct soc_enum pm860x_spk_ear_opamp_enum = - SOC_ENUM_SINGLE(PM860X_EAR_CTRL_1, 3, 4, pm860x_opamp_texts); +static SOC_ENUM_SINGLE_DECL(pm860x_spk_ear_opamp_enum, + PM860X_EAR_CTRL_1, 3, pm860x_opamp_texts); static const struct snd_kcontrol_new pm860x_snd_controls[] = { SOC_DOUBLE_R_TLV("ADC Capture Volume", PM860X_ADC_ANA_2, @@ -561,8 +561,8 @@ static const char *aif1_text[] = { "PCM L", "PCM R", }; -static const struct soc_enum aif1_enum = - SOC_ENUM_SINGLE(PM860X_PCM_IFACE_3, 6, 2, aif1_text); +static SOC_ENUM_SINGLE_DECL(aif1_enum, + PM860X_PCM_IFACE_3, 6, aif1_text); static const struct snd_kcontrol_new aif1_mux = SOC_DAPM_ENUM("PCM Mux", aif1_enum); @@ -572,8 +572,8 @@ static const char *i2s_din_text[] = { "DIN", "DIN1", }; -static const struct soc_enum i2s_din_enum = - SOC_ENUM_SINGLE(PM860X_I2S_IFACE_3, 1, 2, i2s_din_text); +static SOC_ENUM_SINGLE_DECL(i2s_din_enum, + PM860X_I2S_IFACE_3, 1, i2s_din_text); static const struct snd_kcontrol_new i2s_din_mux = SOC_DAPM_ENUM("I2S DIN Mux", i2s_din_enum); @@ -583,8 +583,8 @@ static const char *i2s_mic_text[] = { "Ex PA", "ADC", }; -static const struct soc_enum i2s_mic_enum = - SOC_ENUM_SINGLE(PM860X_I2S_IFACE_3, 4, 2, i2s_mic_text); +static SOC_ENUM_SINGLE_DECL(i2s_mic_enum, + PM860X_I2S_IFACE_3, 4, i2s_mic_text); static const struct snd_kcontrol_new i2s_mic_mux = SOC_DAPM_ENUM("I2S Mic Mux", i2s_mic_enum); @@ -594,8 +594,8 @@ static const char *adcl_text[] = { "ADCR", "ADCL", }; -static const struct soc_enum adcl_enum = - SOC_ENUM_SINGLE(PM860X_PCM_IFACE_3, 4, 2, adcl_text); +static SOC_ENUM_SINGLE_DECL(adcl_enum, + PM860X_PCM_IFACE_3, 4, adcl_text); static const struct snd_kcontrol_new adcl_mux = SOC_DAPM_ENUM("ADC Left Mux", adcl_enum); @@ -605,8 +605,8 @@ static const char *adcr_text[] = { "ADCL", "ADCR", }; -static const struct soc_enum adcr_enum = - SOC_ENUM_SINGLE(PM860X_PCM_IFACE_3, 2, 2, adcr_text); +static SOC_ENUM_SINGLE_DECL(adcr_enum, + PM860X_PCM_IFACE_3, 2, adcr_text); static const struct snd_kcontrol_new adcr_mux = SOC_DAPM_ENUM("ADC Right Mux", adcr_enum); @@ -616,8 +616,8 @@ static const char *adcr_ec_text[] = { "ADCR", "EC", }; -static const struct soc_enum adcr_ec_enum = - SOC_ENUM_SINGLE(PM860X_ADC_EN_2, 3, 2, adcr_ec_text); +static SOC_ENUM_SINGLE_DECL(adcr_ec_enum, + PM860X_ADC_EN_2, 3, adcr_ec_text); static const struct snd_kcontrol_new adcr_ec_mux = SOC_DAPM_ENUM("ADCR EC Mux", adcr_ec_enum); @@ -627,8 +627,8 @@ static const char *ec_text[] = { "Left", "Right", "Left + Right", }; -static const struct soc_enum ec_enum = - SOC_ENUM_SINGLE(PM860X_EC_PATH, 1, 3, ec_text); +static SOC_ENUM_SINGLE_DECL(ec_enum, + PM860X_EC_PATH, 1, ec_text); static const struct snd_kcontrol_new ec_mux = SOC_DAPM_ENUM("EC Mux", ec_enum); @@ -638,36 +638,36 @@ static const char *dac_text[] = { }; /* DAC Headset 1 Mux / Mux10 */ -static const struct soc_enum dac_hs1_enum = - SOC_ENUM_SINGLE(PM860X_ANA_INPUT_SEL_1, 0, 4, dac_text); +static SOC_ENUM_SINGLE_DECL(dac_hs1_enum, + PM860X_ANA_INPUT_SEL_1, 0, dac_text); static const struct snd_kcontrol_new dac_hs1_mux = SOC_DAPM_ENUM("DAC HS1 Mux", dac_hs1_enum); /* DAC Headset 2 Mux / Mux11 */ -static const struct soc_enum dac_hs2_enum = - SOC_ENUM_SINGLE(PM860X_ANA_INPUT_SEL_1, 2, 4, dac_text); +static SOC_ENUM_SINGLE_DECL(dac_hs2_enum, + PM860X_ANA_INPUT_SEL_1, 2, dac_text); static const struct snd_kcontrol_new dac_hs2_mux = SOC_DAPM_ENUM("DAC HS2 Mux", dac_hs2_enum); /* DAC Lineout 1 Mux / Mux12 */ -static const struct soc_enum dac_lo1_enum = - SOC_ENUM_SINGLE(PM860X_ANA_INPUT_SEL_1, 4, 4, dac_text); +static SOC_ENUM_SINGLE_DECL(dac_lo1_enum, + PM860X_ANA_INPUT_SEL_1, 4, dac_text); static const struct snd_kcontrol_new dac_lo1_mux = SOC_DAPM_ENUM("DAC LO1 Mux", dac_lo1_enum); /* DAC Lineout 2 Mux / Mux13 */ -static const struct soc_enum dac_lo2_enum = - SOC_ENUM_SINGLE(PM860X_ANA_INPUT_SEL_1, 6, 4, dac_text); +static SOC_ENUM_SINGLE_DECL(dac_lo2_enum, + PM860X_ANA_INPUT_SEL_1, 6, dac_text); static const struct snd_kcontrol_new dac_lo2_mux = SOC_DAPM_ENUM("DAC LO2 Mux", dac_lo2_enum); /* DAC Spearker Earphone Mux / Mux14 */ -static const struct soc_enum dac_spk_ear_enum = - SOC_ENUM_SINGLE(PM860X_ANA_INPUT_SEL_2, 0, 4, dac_text); +static SOC_ENUM_SINGLE_DECL(dac_spk_ear_enum, + PM860X_ANA_INPUT_SEL_2, 0, dac_text); static const struct snd_kcontrol_new dac_spk_ear_mux = SOC_DAPM_ENUM("DAC SP Mux", dac_spk_ear_enum); @@ -677,29 +677,29 @@ static const char *in_text[] = { "Digital", "Analog", }; -static const struct soc_enum hs1_enum = - SOC_ENUM_SINGLE(PM860X_ANA_TO_ANA, 0, 2, in_text); +static SOC_ENUM_SINGLE_DECL(hs1_enum, + PM860X_ANA_TO_ANA, 0, in_text); static const struct snd_kcontrol_new hs1_mux = SOC_DAPM_ENUM("Headset1 Mux", hs1_enum); /* Headset 2 Mux / Mux16 */ -static const struct soc_enum hs2_enum = - SOC_ENUM_SINGLE(PM860X_ANA_TO_ANA, 1, 2, in_text); +static SOC_ENUM_SINGLE_DECL(hs2_enum, + PM860X_ANA_TO_ANA, 1, in_text); static const struct snd_kcontrol_new hs2_mux = SOC_DAPM_ENUM("Headset2 Mux", hs2_enum); /* Lineout 1 Mux / Mux17 */ -static const struct soc_enum lo1_enum = - SOC_ENUM_SINGLE(PM860X_ANA_TO_ANA, 2, 2, in_text); +static SOC_ENUM_SINGLE_DECL(lo1_enum, + PM860X_ANA_TO_ANA, 2, in_text); static const struct snd_kcontrol_new lo1_mux = SOC_DAPM_ENUM("Lineout1 Mux", lo1_enum); /* Lineout 2 Mux / Mux18 */ -static const struct soc_enum lo2_enum = - SOC_ENUM_SINGLE(PM860X_ANA_TO_ANA, 3, 2, in_text); +static SOC_ENUM_SINGLE_DECL(lo2_enum, + PM860X_ANA_TO_ANA, 3, in_text); static const struct snd_kcontrol_new lo2_mux = SOC_DAPM_ENUM("Lineout2 Mux", lo2_enum); @@ -709,8 +709,8 @@ static const char *spk_text[] = { "Earpiece", "Speaker", }; -static const struct soc_enum spk_enum = - SOC_ENUM_SINGLE(PM860X_ANA_TO_ANA, 6, 2, spk_text); +static SOC_ENUM_SINGLE_DECL(spk_enum, + PM860X_ANA_TO_ANA, 6, spk_text); static const struct snd_kcontrol_new spk_demux = SOC_DAPM_ENUM("Speaker Earpiece Demux", spk_enum); @@ -720,8 +720,8 @@ static const char *mic_text[] = { "Mic 1", "Mic 2", }; -static const struct soc_enum mic_enum = - SOC_ENUM_SINGLE(PM860X_ADC_ANA_4, 4, 2, mic_text); +static SOC_ENUM_SINGLE_DECL(mic_enum, + PM860X_ADC_ANA_4, 4, mic_text); static const struct snd_kcontrol_new mic_mux = SOC_DAPM_ENUM("MIC Mux", mic_enum); @@ -1327,8 +1327,7 @@ static int pm860x_probe(struct snd_soc_codec *codec) pm860x->codec = codec; - codec->control_data = pm860x->regmap; - ret = snd_soc_codec_set_cache_io(codec, 0, 0, SND_SOC_REGMAP); + ret = snd_soc_codec_set_cache_io(codec, pm860x->regmap); if (ret) return ret; diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig index 983d087aa92..f0e84013788 100644 --- a/sound/soc/codecs/Kconfig +++ b/sound/soc/codecs/Kconfig @@ -8,6 +8,8 @@ config SND_SOC_I2C_AND_SPI default y if I2C=y default y if SPI_MASTER=y +menu "CODEC drivers" + config SND_SOC_ALL_CODECS tristate "Build all ASoC CODEC drivers" depends on COMPILE_TEST @@ -16,15 +18,20 @@ config SND_SOC_ALL_CODECS select SND_SOC_AB8500_CODEC if ABX500_CORE select SND_SOC_AC97_CODEC if SND_SOC_AC97_BUS select SND_SOC_AD1836 if SPI_MASTER - select SND_SOC_AD193X if SND_SOC_I2C_AND_SPI + select SND_SOC_AD193X_SPI if SPI_MASTER + select SND_SOC_AD193X_I2C if I2C select SND_SOC_AD1980 if SND_SOC_AC97_BUS select SND_SOC_AD73311 select SND_SOC_ADAU1373 if I2C - select SND_SOC_ADAV80X if SND_SOC_I2C_AND_SPI + select SND_SOC_ADAV801 if SPI_MASTER + select SND_SOC_ADAV803 if I2C + select SND_SOC_ADAU1977_SPI if SPI_MASTER + select SND_SOC_ADAU1977_I2C if I2C select SND_SOC_ADAU1701 if I2C select SND_SOC_ADS117X select SND_SOC_AK4104 if SPI_MASTER select SND_SOC_AK4535 if I2C + select SND_SOC_AK4554 select SND_SOC_AK4641 if I2C select SND_SOC_AK4642 if I2C select SND_SOC_AK4671 if I2C @@ -37,6 +44,7 @@ config SND_SOC_ALL_CODECS select SND_SOC_CS42L73 if I2C select SND_SOC_CS4270 if I2C select SND_SOC_CS4271 if SND_SOC_I2C_AND_SPI + select SND_SOC_CS42XX8_I2C if I2C select SND_SOC_CX20442 if TTY select SND_SOC_DA7210 if I2C select SND_SOC_DA7213 if I2C @@ -59,20 +67,26 @@ config SND_SOC_ALL_CODECS select SND_SOC_PCM1681 if I2C select SND_SOC_PCM1792A if SPI_MASTER select SND_SOC_PCM3008 + select SND_SOC_PCM512x_I2C if I2C + select SND_SOC_PCM512x_SPI if SPI_MASTER select SND_SOC_RT5631 if I2C select SND_SOC_RT5640 if I2C select SND_SOC_SGTL5000 if I2C select SND_SOC_SI476X if MFD_SI476X_CORE + select SND_SOC_SIRF_AUDIO_CODEC select SND_SOC_SN95031 if INTEL_SCU_IPC select SND_SOC_SPDIF select SND_SOC_SSM2518 if I2C - select SND_SOC_SSM2602 if SND_SOC_I2C_AND_SPI + select SND_SOC_SSM2602_SPI if SPI_MASTER + select SND_SOC_SSM2602_I2C if I2C select SND_SOC_STA32X if I2C select SND_SOC_STA529 if I2C select SND_SOC_STAC9766 if SND_SOC_AC97_BUS select SND_SOC_TAS5086 if I2C - select SND_SOC_TLV320AIC23 if I2C + select SND_SOC_TLV320AIC23_I2C if I2C + select SND_SOC_TLV320AIC23_SPI if SPI_MASTER select SND_SOC_TLV320AIC26 if SPI_MASTER + select SND_SOC_TLV320AIC31XX if I2C select SND_SOC_TLV320AIC32X4 if I2C select SND_SOC_TLV320AIC3X if I2C select SND_SOC_TPA6130A2 if I2C @@ -182,6 +196,14 @@ config SND_SOC_AD1836 config SND_SOC_AD193X tristate +config SND_SOC_AD193X_SPI + tristate + select SND_SOC_AD193X + +config SND_SOC_AD193X_I2C + tristate + select SND_SOC_AD193X + config SND_SOC_AD1980 tristate @@ -189,41 +211,66 @@ config SND_SOC_AD73311 tristate config SND_SOC_ADAU1701 + tristate "Analog Devices ADAU1701 CODEC" + depends on I2C select SND_SOC_SIGMADSP - tristate config SND_SOC_ADAU1373 tristate +config SND_SOC_ADAU1977 + tristate + +config SND_SOC_ADAU1977_SPI + tristate + select SND_SOC_ADAU1977 + select REGMAP_SPI + +config SND_SOC_ADAU1977_I2C + tristate + select SND_SOC_ADAU1977 + select REGMAP_I2C + config SND_SOC_ADAV80X tristate +config SND_SOC_ADAV801 + tristate + select SND_SOC_ADAV80X + +config SND_SOC_ADAV803 + tristate + select SND_SOC_ADAV80X + config SND_SOC_ADS117X tristate config SND_SOC_AK4104 - tristate + tristate "AKM AK4104 CODEC" + depends on SPI_MASTER config SND_SOC_AK4535 tristate config SND_SOC_AK4554 - tristate + tristate "AKM AK4554 CODEC" config SND_SOC_AK4641 tristate config SND_SOC_AK4642 - tristate + tristate "AKM AK4642 CODEC" + depends on I2C config SND_SOC_AK4671 tristate config SND_SOC_AK5386 - tristate + tristate "AKM AK5638 CODEC" config SND_SOC_ALC5623 tristate + config SND_SOC_ALC5632 tristate @@ -234,14 +281,17 @@ config SND_SOC_CS42L51 tristate config SND_SOC_CS42L52 - tristate + tristate "Cirrus Logic CS42L52 CODEC" + depends on I2C config SND_SOC_CS42L73 - tristate + tristate "Cirrus Logic CS42L73 CODEC" + depends on I2C # Cirrus Logic CS4270 Codec config SND_SOC_CS4270 - tristate + tristate "Cirrus Logic CS4270 CODEC" + depends on I2C # Cirrus Logic CS4270 Codec VD = 3.3V Errata # Select if you are affected by the errata where the part will not function @@ -252,8 +302,18 @@ config SND_SOC_CS4270_VD33_ERRATA depends on SND_SOC_CS4270 config SND_SOC_CS4271 + tristate "Cirrus Logic CS4271 CODEC" + depends on SND_SOC_I2C_AND_SPI + +config SND_SOC_CS42XX8 tristate +config SND_SOC_CS42XX8_I2C + tristate "Cirrus Logic CS42448/CS42888 CODEC (I2C)" + depends on I2C + select SND_SOC_CS42XX8 + select REGMAP_I2C + config SND_SOC_CX20442 tristate depends on TTY @@ -283,6 +343,9 @@ config SND_SOC_BT_SCO config SND_SOC_DMIC tristate +config SND_SOC_HDMI_CODEC + tristate "HDMI stub CODEC" + config SND_SOC_ISABELLE tristate @@ -301,18 +364,32 @@ config SND_SOC_MAX98095 config SND_SOC_MAX9850 tristate -config SND_SOC_HDMI_CODEC - tristate - config SND_SOC_PCM1681 - tristate + tristate "Texas Instruments PCM1681 CODEC" + depends on I2C config SND_SOC_PCM1792A - tristate + tristate "Texas Instruments PCM1792A CODEC" + depends on SPI_MASTER config SND_SOC_PCM3008 tristate +config SND_SOC_PCM512x + tristate + +config SND_SOC_PCM512x_I2C + tristate "Texas Instruments PCM512x CODECs - I2C" + depends on I2C + select SND_SOC_PCM512x + select REGMAP_I2C + +config SND_SOC_PCM512x_SPI + tristate "Texas Instruments PCM512x CODECs - SPI" + depends on SPI_MASTER + select SND_SOC_PCM512x + select REGMAP_SPI + config SND_SOC_RT5631 tristate @@ -321,7 +398,8 @@ config SND_SOC_RT5640 #Freescale sgtl5000 codec config SND_SOC_SGTL5000 - tristate + tristate "Freescale SGTL5000 CODEC" + depends on I2C config SND_SOC_SI476X tristate @@ -330,11 +408,15 @@ config SND_SOC_SIGMADSP tristate select CRC32 +config SND_SOC_SIRF_AUDIO_CODEC + tristate "SiRF SoC internal audio codec" + select REGMAP_MMIO + config SND_SOC_SN95031 tristate config SND_SOC_SPDIF - tristate + tristate "S/PDIF CODEC" config SND_SOC_SSM2518 tristate @@ -342,6 +424,14 @@ config SND_SOC_SSM2518 config SND_SOC_SSM2602 tristate +config SND_SOC_SSM2602_SPI + select SND_SOC_SSM2602 + tristate + +config SND_SOC_SSM2602_I2C + select SND_SOC_SSM2602 + tristate + config SND_SOC_STA32X tristate @@ -352,20 +442,33 @@ config SND_SOC_STAC9766 tristate config SND_SOC_TAS5086 - tristate + tristate "Texas Instruments TAS5086 speaker amplifier" + depends on I2C config SND_SOC_TLV320AIC23 tristate +config SND_SOC_TLV320AIC23_I2C + tristate + select SND_SOC_TLV320AIC23 + +config SND_SOC_TLV320AIC23_SPI + tristate + select SND_SOC_TLV320AIC23 + config SND_SOC_TLV320AIC26 tristate depends on SPI +config SND_SOC_TLV320AIC31XX + tristate + config SND_SOC_TLV320AIC32X4 tristate config SND_SOC_TLV320AIC3X - tristate + tristate "Texas Instruments TLV320AIC3x CODECs" + depends on I2C config SND_SOC_TLV320DAC33 tristate @@ -414,55 +517,69 @@ config SND_SOC_WM8400 tristate config SND_SOC_WM8510 - tristate + tristate "Wolfson Microelectronics WM8510 CODEC" + depends on SND_SOC_I2C_AND_SPI config SND_SOC_WM8523 - tristate + tristate "Wolfson Microelectronics WM8523 DAC" + depends on I2C config SND_SOC_WM8580 - tristate + tristate "Wolfson Microelectronics WM8523 CODEC" + depends on I2C config SND_SOC_WM8711 - tristate + tristate "Wolfson Microelectronics WM8711 CODEC" + depends on SND_SOC_I2C_AND_SPI config SND_SOC_WM8727 tristate config SND_SOC_WM8728 - tristate + tristate "Wolfson Microelectronics WM8728 DAC" + depends on SND_SOC_I2C_AND_SPI config SND_SOC_WM8731 - tristate + tristate "Wolfson Microelectronics WM8731 CODEC" + depends on SND_SOC_I2C_AND_SPI config SND_SOC_WM8737 - tristate + tristate "Wolfson Microelectronics WM8737 ADC" + depends on SND_SOC_I2C_AND_SPI config SND_SOC_WM8741 - tristate + tristate "Wolfson Microelectronics WM8737 DAC" + depends on SND_SOC_I2C_AND_SPI config SND_SOC_WM8750 - tristate + tristate "Wolfson Microelectronics WM8750 CODEC" + depends on SND_SOC_I2C_AND_SPI config SND_SOC_WM8753 - tristate + tristate "Wolfson Microelectronics WM8753 CODEC" + depends on SND_SOC_I2C_AND_SPI config SND_SOC_WM8770 - tristate + tristate "Wolfson Microelectronics WM8770 CODEC" + depends on SPI_MASTER config SND_SOC_WM8776 - tristate + tristate "Wolfson Microelectronics WM8776 CODEC" + depends on SND_SOC_I2C_AND_SPI config SND_SOC_WM8782 tristate config SND_SOC_WM8804 - tristate + tristate "Wolfson Microelectronics WM8804 S/PDIF transceiver" + depends on SND_SOC_I2C_AND_SPI config SND_SOC_WM8900 tristate config SND_SOC_WM8903 - tristate + tristate "Wolfson Microelectronics WM8903 CODEC" + depends on I2C config SND_SOC_WM8904 tristate @@ -480,7 +597,8 @@ config SND_SOC_WM8961 tristate config SND_SOC_WM8962 - tristate + tristate "Wolfson Microelectronics WM8962 CODEC" + depends on I2C config SND_SOC_WM8971 tristate @@ -553,4 +671,7 @@ config SND_SOC_ML26124 tristate config SND_SOC_TPA6130A2 - tristate + tristate "Texas Instruments TPA6130A2 headphone amplifier" + depends on I2C + +endmenu diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile index bc126764a44..3c4d275d064 100644 --- a/sound/soc/codecs/Makefile +++ b/sound/soc/codecs/Makefile @@ -3,11 +3,18 @@ snd-soc-ab8500-codec-objs := ab8500-codec.o snd-soc-ac97-objs := ac97.o snd-soc-ad1836-objs := ad1836.o snd-soc-ad193x-objs := ad193x.o +snd-soc-ad193x-spi-objs := ad193x-spi.o +snd-soc-ad193x-i2c-objs := ad193x-i2c.o snd-soc-ad1980-objs := ad1980.o snd-soc-ad73311-objs := ad73311.o snd-soc-adau1701-objs := adau1701.o snd-soc-adau1373-objs := adau1373.o +snd-soc-adau1977-objs := adau1977.o +snd-soc-adau1977-spi-objs := adau1977-spi.o +snd-soc-adau1977-i2c-objs := adau1977-i2c.o snd-soc-adav80x-objs := adav80x.o +snd-soc-adav801-objs := adav801.o +snd-soc-adav803-objs := adav803.o snd-soc-ads117x-objs := ads117x.o snd-soc-ak4104-objs := ak4104.o snd-soc-ak4535-objs := ak4535.o @@ -23,6 +30,8 @@ snd-soc-cs42l52-objs := cs42l52.o snd-soc-cs42l73-objs := cs42l73.o snd-soc-cs4270-objs := cs4270.o snd-soc-cs4271-objs := cs4271.o +snd-soc-cs42xx8-objs := cs42xx8.o +snd-soc-cs42xx8-i2c-objs := cs42xx8-i2c.o snd-soc-cx20442-objs := cx20442.o snd-soc-da7210-objs := da7210.o snd-soc-da7213-objs := da7213.o @@ -46,6 +55,9 @@ snd-soc-hdmi-codec-objs := hdmi.o snd-soc-pcm1681-objs := pcm1681.o snd-soc-pcm1792a-codec-objs := pcm1792a.o snd-soc-pcm3008-objs := pcm3008.o +snd-soc-pcm512x-objs := pcm512x.o +snd-soc-pcm512x-i2c-objs := pcm512x-i2c.o +snd-soc-pcm512x-spi-objs := pcm512x-spi.o snd-soc-rt5631-objs := rt5631.o snd-soc-rt5640-objs := rt5640.o snd-soc-sgtl5000-objs := sgtl5000.o @@ -53,19 +65,25 @@ snd-soc-alc5623-objs := alc5623.o snd-soc-alc5632-objs := alc5632.o snd-soc-sigmadsp-objs := sigmadsp.o snd-soc-si476x-objs := si476x.o +snd-soc-sirf-audio-codec-objs := sirf-audio-codec.o snd-soc-sn95031-objs := sn95031.o snd-soc-spdif-tx-objs := spdif_transmitter.o snd-soc-spdif-rx-objs := spdif_receiver.o snd-soc-ssm2518-objs := ssm2518.o snd-soc-ssm2602-objs := ssm2602.o +snd-soc-ssm2602-spi-objs := ssm2602-spi.o +snd-soc-ssm2602-i2c-objs := ssm2602-i2c.o snd-soc-sta32x-objs := sta32x.o snd-soc-sta529-objs := sta529.o snd-soc-stac9766-objs := stac9766.o snd-soc-tas5086-objs := tas5086.o snd-soc-tlv320aic23-objs := tlv320aic23.o +snd-soc-tlv320aic23-i2c-objs := tlv320aic23-i2c.o +snd-soc-tlv320aic23-spi-objs := tlv320aic23-spi.o snd-soc-tlv320aic26-objs := tlv320aic26.o -snd-soc-tlv320aic3x-objs := tlv320aic3x.o +snd-soc-tlv320aic31xx-objs := tlv320aic31xx.o snd-soc-tlv320aic32x4-objs := tlv320aic32x4.o +snd-soc-tlv320aic3x-objs := tlv320aic3x.o snd-soc-tlv320dac33-objs := tlv320dac33.o snd-soc-twl4030-objs := twl4030.o snd-soc-twl6040-objs := twl6040.o @@ -134,11 +152,18 @@ obj-$(CONFIG_SND_SOC_AB8500_CODEC) += snd-soc-ab8500-codec.o obj-$(CONFIG_SND_SOC_AC97_CODEC) += snd-soc-ac97.o obj-$(CONFIG_SND_SOC_AD1836) += snd-soc-ad1836.o obj-$(CONFIG_SND_SOC_AD193X) += snd-soc-ad193x.o +obj-$(CONFIG_SND_SOC_AD193X_SPI) += snd-soc-ad193x-spi.o +obj-$(CONFIG_SND_SOC_AD193X_I2C) += snd-soc-ad193x-i2c.o obj-$(CONFIG_SND_SOC_AD1980) += snd-soc-ad1980.o obj-$(CONFIG_SND_SOC_AD73311) += snd-soc-ad73311.o obj-$(CONFIG_SND_SOC_ADAU1373) += snd-soc-adau1373.o +obj-$(CONFIG_SND_SOC_ADAU1977) += snd-soc-adau1977.o +obj-$(CONFIG_SND_SOC_ADAU1977_SPI) += snd-soc-adau1977-spi.o +obj-$(CONFIG_SND_SOC_ADAU1977_I2C) += snd-soc-adau1977-i2c.o obj-$(CONFIG_SND_SOC_ADAU1701) += snd-soc-adau1701.o obj-$(CONFIG_SND_SOC_ADAV80X) += snd-soc-adav80x.o +obj-$(CONFIG_SND_SOC_ADAV801) += snd-soc-adav801.o +obj-$(CONFIG_SND_SOC_ADAV803) += snd-soc-adav803.o obj-$(CONFIG_SND_SOC_ADS117X) += snd-soc-ads117x.o obj-$(CONFIG_SND_SOC_AK4104) += snd-soc-ak4104.o obj-$(CONFIG_SND_SOC_AK4535) += snd-soc-ak4535.o @@ -156,6 +181,8 @@ obj-$(CONFIG_SND_SOC_CS42L52) += snd-soc-cs42l52.o obj-$(CONFIG_SND_SOC_CS42L73) += snd-soc-cs42l73.o obj-$(CONFIG_SND_SOC_CS4270) += snd-soc-cs4270.o obj-$(CONFIG_SND_SOC_CS4271) += snd-soc-cs4271.o +obj-$(CONFIG_SND_SOC_CS42XX8) += snd-soc-cs42xx8.o +obj-$(CONFIG_SND_SOC_CS42XX8_I2C) += snd-soc-cs42xx8-i2c.o obj-$(CONFIG_SND_SOC_CX20442) += snd-soc-cx20442.o obj-$(CONFIG_SND_SOC_DA7210) += snd-soc-da7210.o obj-$(CONFIG_SND_SOC_DA7213) += snd-soc-da7213.o @@ -179,6 +206,9 @@ obj-$(CONFIG_SND_SOC_HDMI_CODEC) += snd-soc-hdmi-codec.o obj-$(CONFIG_SND_SOC_PCM1681) += snd-soc-pcm1681.o obj-$(CONFIG_SND_SOC_PCM1792A) += snd-soc-pcm1792a-codec.o obj-$(CONFIG_SND_SOC_PCM3008) += snd-soc-pcm3008.o +obj-$(CONFIG_SND_SOC_PCM512x) += snd-soc-pcm512x.o +obj-$(CONFIG_SND_SOC_PCM512x_I2C) += snd-soc-pcm512x-i2c.o +obj-$(CONFIG_SND_SOC_PCM512x_SPI) += snd-soc-pcm512x-spi.o obj-$(CONFIG_SND_SOC_RT5631) += snd-soc-rt5631.o obj-$(CONFIG_SND_SOC_RT5640) += snd-soc-rt5640.o obj-$(CONFIG_SND_SOC_SGTL5000) += snd-soc-sgtl5000.o @@ -188,14 +218,19 @@ obj-$(CONFIG_SND_SOC_SN95031) +=snd-soc-sn95031.o obj-$(CONFIG_SND_SOC_SPDIF) += snd-soc-spdif-rx.o snd-soc-spdif-tx.o obj-$(CONFIG_SND_SOC_SSM2518) += snd-soc-ssm2518.o obj-$(CONFIG_SND_SOC_SSM2602) += snd-soc-ssm2602.o +obj-$(CONFIG_SND_SOC_SSM2602_SPI) += snd-soc-ssm2602-spi.o +obj-$(CONFIG_SND_SOC_SSM2602_I2C) += snd-soc-ssm2602-i2c.o obj-$(CONFIG_SND_SOC_STA32X) += snd-soc-sta32x.o obj-$(CONFIG_SND_SOC_STA529) += snd-soc-sta529.o obj-$(CONFIG_SND_SOC_STAC9766) += snd-soc-stac9766.o obj-$(CONFIG_SND_SOC_TAS5086) += snd-soc-tas5086.o obj-$(CONFIG_SND_SOC_TLV320AIC23) += snd-soc-tlv320aic23.o +obj-$(CONFIG_SND_SOC_TLV320AIC23_I2C) += snd-soc-tlv320aic23-i2c.o +obj-$(CONFIG_SND_SOC_TLV320AIC23_SPI) += snd-soc-tlv320aic23-spi.o obj-$(CONFIG_SND_SOC_TLV320AIC26) += snd-soc-tlv320aic26.o -obj-$(CONFIG_SND_SOC_TLV320AIC3X) += snd-soc-tlv320aic3x.o +obj-$(CONFIG_SND_SOC_TLV320AIC31XX) += snd-soc-tlv320aic31xx.o obj-$(CONFIG_SND_SOC_TLV320AIC32X4) += snd-soc-tlv320aic32x4.o +obj-$(CONFIG_SND_SOC_TLV320AIC3X) += snd-soc-tlv320aic3x.o obj-$(CONFIG_SND_SOC_TLV320DAC33) += snd-soc-tlv320dac33.o obj-$(CONFIG_SND_SOC_TWL4030) += snd-soc-twl4030.o obj-$(CONFIG_SND_SOC_TWL6040) += snd-soc-twl6040.o diff --git a/sound/soc/codecs/ad1836.c b/sound/soc/codecs/ad1836.c index 77f45986857..685998dd086 100644 --- a/sound/soc/codecs/ad1836.c +++ b/sound/soc/codecs/ad1836.c @@ -40,8 +40,8 @@ struct ad1836_priv { */ static const char *ad1836_deemp[] = {"None", "44.1kHz", "32kHz", "48kHz"}; -static const struct soc_enum ad1836_deemp_enum = - SOC_ENUM_SINGLE(AD1836_DAC_CTRL1, 8, 4, ad1836_deemp); +static SOC_ENUM_SINGLE_DECL(ad1836_deemp_enum, + AD1836_DAC_CTRL1, 8, ad1836_deemp); #define AD1836_DAC_VOLUME(x) \ SOC_DOUBLE_R("DAC" #x " Playback Volume", AD1836_DAC_L_VOL(x), \ diff --git a/sound/soc/codecs/ad193x-i2c.c b/sound/soc/codecs/ad193x-i2c.c new file mode 100644 index 00000000000..df3a1a41582 --- /dev/null +++ b/sound/soc/codecs/ad193x-i2c.c @@ -0,0 +1,54 @@ +/* + * AD1936/AD1937 audio driver + * + * Copyright 2014 Analog Devices Inc. + * + * Licensed under the GPL-2. + */ + +#include <linux/module.h> +#include <linux/i2c.h> +#include <linux/regmap.h> + +#include <sound/soc.h> + +#include "ad193x.h" + +static const struct i2c_device_id ad193x_id[] = { + { "ad1936", 0 }, + { "ad1937", 0 }, + { } +}; +MODULE_DEVICE_TABLE(i2c, ad193x_id); + +static int ad193x_i2c_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + struct regmap_config config; + + config = ad193x_regmap_config; + config.val_bits = 8; + config.reg_bits = 8; + + return ad193x_probe(&client->dev, devm_regmap_init_i2c(client, &config)); +} + +static int ad193x_i2c_remove(struct i2c_client *client) +{ + snd_soc_unregister_codec(&client->dev); + return 0; +} + +static struct i2c_driver ad193x_i2c_driver = { + .driver = { + .name = "ad193x", + }, + .probe = ad193x_i2c_probe, + .remove = ad193x_i2c_remove, + .id_table = ad193x_id, +}; +module_i2c_driver(ad193x_i2c_driver); + +MODULE_DESCRIPTION("ASoC AD1936/AD1937 audio CODEC driver"); +MODULE_AUTHOR("Barry Song <21cnbao@gmail.com>"); +MODULE_LICENSE("GPL"); diff --git a/sound/soc/codecs/ad193x-spi.c b/sound/soc/codecs/ad193x-spi.c new file mode 100644 index 00000000000..390cef9b9dc --- /dev/null +++ b/sound/soc/codecs/ad193x-spi.c @@ -0,0 +1,48 @@ +/* + * AD1938/AD1939 audio driver + * + * Copyright 2014 Analog Devices Inc. + * + * Licensed under the GPL-2. + */ + +#include <linux/module.h> +#include <linux/spi/spi.h> +#include <linux/regmap.h> + +#include <sound/soc.h> + +#include "ad193x.h" + +static int ad193x_spi_probe(struct spi_device *spi) +{ + struct regmap_config config; + + config = ad193x_regmap_config; + config.val_bits = 8; + config.reg_bits = 16; + config.read_flag_mask = 0x09; + config.write_flag_mask = 0x08; + + return ad193x_probe(&spi->dev, devm_regmap_init_spi(spi, &config)); +} + +static int ad193x_spi_remove(struct spi_device *spi) +{ + snd_soc_unregister_codec(&spi->dev); + return 0; +} + +static struct spi_driver ad193x_spi_driver = { + .driver = { + .name = "ad193x", + .owner = THIS_MODULE, + }, + .probe = ad193x_spi_probe, + .remove = ad193x_spi_remove, +}; +module_spi_driver(ad193x_spi_driver); + +MODULE_DESCRIPTION("ASoC AD1938/AD1939 audio CODEC driver"); +MODULE_AUTHOR("Barry Song <21cnbao@gmail.com>"); +MODULE_LICENSE("GPL"); diff --git a/sound/soc/codecs/ad193x.c b/sound/soc/codecs/ad193x.c index 5a42dca535b..6844d0b2af6 100644 --- a/sound/soc/codecs/ad193x.c +++ b/sound/soc/codecs/ad193x.c @@ -6,12 +6,10 @@ * Licensed under the GPL-2 or later. */ -#include <linux/init.h> #include <linux/module.h> #include <linux/kernel.h> #include <linux/device.h> -#include <linux/i2c.h> -#include <linux/spi/spi.h> +#include <linux/regmap.h> #include <linux/slab.h> #include <sound/core.h> #include <sound/pcm.h> @@ -19,6 +17,7 @@ #include <sound/initval.h> #include <sound/soc.h> #include <sound/tlv.h> + #include "ad193x.h" /* codec private data */ @@ -32,8 +31,8 @@ struct ad193x_priv { */ static const char * const ad193x_deemp[] = {"None", "48kHz", "44.1kHz", "32kHz"}; -static const struct soc_enum ad193x_deemp_enum = - SOC_ENUM_SINGLE(AD193X_DAC_CTRL2, 1, 4, ad193x_deemp); +static SOC_ENUM_SINGLE_DECL(ad193x_deemp_enum, AD193X_DAC_CTRL2, 1, + ad193x_deemp); static const DECLARE_TLV_DB_MINMAX(adau193x_tlv, -9563, 0); @@ -320,17 +319,9 @@ static struct snd_soc_dai_driver ad193x_dai = { .ops = &ad193x_dai_ops, }; -static int ad193x_probe(struct snd_soc_codec *codec) +static int ad193x_codec_probe(struct snd_soc_codec *codec) { struct ad193x_priv *ad193x = snd_soc_codec_get_drvdata(codec); - int ret; - - codec->control_data = ad193x->regmap; - ret = snd_soc_codec_set_cache_io(codec, 0, 0, SND_SOC_REGMAP); - if (ret < 0) { - dev_err(codec->dev, "failed to set cache I/O: %d\n", ret); - return ret; - } /* default setting for ad193x */ @@ -348,11 +339,11 @@ static int ad193x_probe(struct snd_soc_codec *codec) regmap_write(ad193x->regmap, AD193X_PLL_CLK_CTRL0, 0x99); /* mclk=24.576Mhz: 0x9D; mclk=12.288Mhz: 0x99 */ regmap_write(ad193x->regmap, AD193X_PLL_CLK_CTRL1, 0x04); - return ret; + return 0; } static struct snd_soc_codec_driver soc_codec_dev_ad193x = { - .probe = ad193x_probe, + .probe = ad193x_codec_probe, .controls = ad193x_snd_controls, .num_controls = ARRAY_SIZE(ad193x_snd_controls), .dapm_widgets = ad193x_dapm_widgets, @@ -366,140 +357,31 @@ static bool adau193x_reg_volatile(struct device *dev, unsigned int reg) return false; } -#if defined(CONFIG_SPI_MASTER) - -static const struct regmap_config ad193x_spi_regmap_config = { - .val_bits = 8, - .reg_bits = 16, - .read_flag_mask = 0x09, - .write_flag_mask = 0x08, - +const struct regmap_config ad193x_regmap_config = { .max_register = AD193X_NUM_REGS - 1, .volatile_reg = adau193x_reg_volatile, }; +EXPORT_SYMBOL_GPL(ad193x_regmap_config); -static int ad193x_spi_probe(struct spi_device *spi) +int ad193x_probe(struct device *dev, struct regmap *regmap) { struct ad193x_priv *ad193x; - ad193x = devm_kzalloc(&spi->dev, sizeof(struct ad193x_priv), - GFP_KERNEL); - if (ad193x == NULL) - return -ENOMEM; - - ad193x->regmap = devm_regmap_init_spi(spi, &ad193x_spi_regmap_config); - if (IS_ERR(ad193x->regmap)) - return PTR_ERR(ad193x->regmap); - - spi_set_drvdata(spi, ad193x); - - return snd_soc_register_codec(&spi->dev, &soc_codec_dev_ad193x, - &ad193x_dai, 1); -} - -static int ad193x_spi_remove(struct spi_device *spi) -{ - snd_soc_unregister_codec(&spi->dev); - return 0; -} - -static struct spi_driver ad193x_spi_driver = { - .driver = { - .name = "ad193x", - .owner = THIS_MODULE, - }, - .probe = ad193x_spi_probe, - .remove = ad193x_spi_remove, -}; -#endif - -#if IS_ENABLED(CONFIG_I2C) - -static const struct regmap_config ad193x_i2c_regmap_config = { - .val_bits = 8, - .reg_bits = 8, - - .max_register = AD193X_NUM_REGS - 1, - .volatile_reg = adau193x_reg_volatile, -}; - -static const struct i2c_device_id ad193x_id[] = { - { "ad1936", 0 }, - { "ad1937", 0 }, - { } -}; -MODULE_DEVICE_TABLE(i2c, ad193x_id); - -static int ad193x_i2c_probe(struct i2c_client *client, - const struct i2c_device_id *id) -{ - struct ad193x_priv *ad193x; + if (IS_ERR(regmap)) + return PTR_ERR(regmap); - ad193x = devm_kzalloc(&client->dev, sizeof(struct ad193x_priv), - GFP_KERNEL); + ad193x = devm_kzalloc(dev, sizeof(*ad193x), GFP_KERNEL); if (ad193x == NULL) return -ENOMEM; - ad193x->regmap = devm_regmap_init_i2c(client, &ad193x_i2c_regmap_config); - if (IS_ERR(ad193x->regmap)) - return PTR_ERR(ad193x->regmap); - - i2c_set_clientdata(client, ad193x); - - return snd_soc_register_codec(&client->dev, &soc_codec_dev_ad193x, - &ad193x_dai, 1); -} - -static int ad193x_i2c_remove(struct i2c_client *client) -{ - snd_soc_unregister_codec(&client->dev); - return 0; -} - -static struct i2c_driver ad193x_i2c_driver = { - .driver = { - .name = "ad193x", - }, - .probe = ad193x_i2c_probe, - .remove = ad193x_i2c_remove, - .id_table = ad193x_id, -}; -#endif - -static int __init ad193x_modinit(void) -{ - int ret; - -#if IS_ENABLED(CONFIG_I2C) - ret = i2c_add_driver(&ad193x_i2c_driver); - if (ret != 0) { - printk(KERN_ERR "Failed to register AD193X I2C driver: %d\n", - ret); - } -#endif - -#if defined(CONFIG_SPI_MASTER) - ret = spi_register_driver(&ad193x_spi_driver); - if (ret != 0) { - printk(KERN_ERR "Failed to register AD193X SPI driver: %d\n", - ret); - } -#endif - return ret; -} -module_init(ad193x_modinit); + ad193x->regmap = regmap; -static void __exit ad193x_modexit(void) -{ -#if defined(CONFIG_SPI_MASTER) - spi_unregister_driver(&ad193x_spi_driver); -#endif + dev_set_drvdata(dev, ad193x); -#if IS_ENABLED(CONFIG_I2C) - i2c_del_driver(&ad193x_i2c_driver); -#endif + return snd_soc_register_codec(dev, &soc_codec_dev_ad193x, + &ad193x_dai, 1); } -module_exit(ad193x_modexit); +EXPORT_SYMBOL_GPL(ad193x_probe); MODULE_DESCRIPTION("ASoC ad193x driver"); MODULE_AUTHOR("Barry Song <21cnbao@gmail.com>"); diff --git a/sound/soc/codecs/ad193x.h b/sound/soc/codecs/ad193x.h index 47338804999..ab9a998f15b 100644 --- a/sound/soc/codecs/ad193x.h +++ b/sound/soc/codecs/ad193x.h @@ -9,6 +9,13 @@ #ifndef __AD193X_H__ #define __AD193X_H__ +#include <linux/regmap.h> + +struct device; + +extern const struct regmap_config ad193x_regmap_config; +int ad193x_probe(struct device *dev, struct regmap *regmap); + #define AD193X_PLL_CLK_CTRL0 0x00 #define AD193X_PLL_POWERDOWN 0x01 #define AD193X_PLL_INPUT_MASK 0x6 diff --git a/sound/soc/codecs/adau1373.c b/sound/soc/codecs/adau1373.c index eb836ed5271..877f5737bb6 100644 --- a/sound/soc/codecs/adau1373.c +++ b/sound/soc/codecs/adau1373.c @@ -345,15 +345,15 @@ static const char *adau1373_fdsp_sel_text[] = { "Channel 5", }; -static const SOC_ENUM_SINGLE_DECL(adau1373_drc1_channel_enum, +static SOC_ENUM_SINGLE_DECL(adau1373_drc1_channel_enum, ADAU1373_FDSP_SEL1, 4, adau1373_fdsp_sel_text); -static const SOC_ENUM_SINGLE_DECL(adau1373_drc2_channel_enum, +static SOC_ENUM_SINGLE_DECL(adau1373_drc2_channel_enum, ADAU1373_FDSP_SEL1, 0, adau1373_fdsp_sel_text); -static const SOC_ENUM_SINGLE_DECL(adau1373_drc3_channel_enum, +static SOC_ENUM_SINGLE_DECL(adau1373_drc3_channel_enum, ADAU1373_FDSP_SEL2, 0, adau1373_fdsp_sel_text); -static const SOC_ENUM_SINGLE_DECL(adau1373_hpf_channel_enum, +static SOC_ENUM_SINGLE_DECL(adau1373_hpf_channel_enum, ADAU1373_FDSP_SEL3, 0, adau1373_fdsp_sel_text); -static const SOC_ENUM_SINGLE_DECL(adau1373_bass_channel_enum, +static SOC_ENUM_SINGLE_DECL(adau1373_bass_channel_enum, ADAU1373_FDSP_SEL4, 4, adau1373_fdsp_sel_text); static const char *adau1373_hpf_cutoff_text[] = { @@ -362,7 +362,7 @@ static const char *adau1373_hpf_cutoff_text[] = { "800Hz", }; -static const SOC_ENUM_SINGLE_DECL(adau1373_hpf_cutoff_enum, +static SOC_ENUM_SINGLE_DECL(adau1373_hpf_cutoff_enum, ADAU1373_HPF_CTRL, 3, adau1373_hpf_cutoff_text); static const char *adau1373_bass_lpf_cutoff_text[] = { @@ -388,14 +388,14 @@ static const unsigned int adau1373_bass_tlv[] = { 5, 7, TLV_DB_SCALE_ITEM(1400, 150, 0), }; -static const SOC_ENUM_SINGLE_DECL(adau1373_bass_lpf_cutoff_enum, +static SOC_ENUM_SINGLE_DECL(adau1373_bass_lpf_cutoff_enum, ADAU1373_BASS1, 5, adau1373_bass_lpf_cutoff_text); -static const SOC_VALUE_ENUM_SINGLE_DECL(adau1373_bass_clip_level_enum, +static SOC_VALUE_ENUM_SINGLE_DECL(adau1373_bass_clip_level_enum, ADAU1373_BASS1, 2, 7, adau1373_bass_clip_level_text, adau1373_bass_clip_level_values); -static const SOC_ENUM_SINGLE_DECL(adau1373_bass_hpf_cutoff_enum, +static SOC_ENUM_SINGLE_DECL(adau1373_bass_hpf_cutoff_enum, ADAU1373_BASS1, 0, adau1373_bass_hpf_cutoff_text); static const char *adau1373_3d_level_text[] = { @@ -409,9 +409,9 @@ static const char *adau1373_3d_cutoff_text[] = { "0.16875 fs", "0.27083 fs" }; -static const SOC_ENUM_SINGLE_DECL(adau1373_3d_level_enum, +static SOC_ENUM_SINGLE_DECL(adau1373_3d_level_enum, ADAU1373_3D_CTRL1, 4, adau1373_3d_level_text); -static const SOC_ENUM_SINGLE_DECL(adau1373_3d_cutoff_enum, +static SOC_ENUM_SINGLE_DECL(adau1373_3d_cutoff_enum, ADAU1373_3D_CTRL1, 0, adau1373_3d_cutoff_text); static const unsigned int adau1373_3d_tlv[] = { @@ -427,11 +427,11 @@ static const char *adau1373_lr_mux_text[] = { "Stereo", }; -static const SOC_ENUM_SINGLE_DECL(adau1373_lineout1_lr_mux_enum, +static SOC_ENUM_SINGLE_DECL(adau1373_lineout1_lr_mux_enum, ADAU1373_OUTPUT_CTRL, 4, adau1373_lr_mux_text); -static const SOC_ENUM_SINGLE_DECL(adau1373_lineout2_lr_mux_enum, +static SOC_ENUM_SINGLE_DECL(adau1373_lineout2_lr_mux_enum, ADAU1373_OUTPUT_CTRL, 6, adau1373_lr_mux_text); -static const SOC_ENUM_SINGLE_DECL(adau1373_speaker_lr_mux_enum, +static SOC_ENUM_SINGLE_DECL(adau1373_speaker_lr_mux_enum, ADAU1373_LS_CTRL, 4, adau1373_lr_mux_text); static const struct snd_kcontrol_new adau1373_controls[] = { @@ -576,8 +576,8 @@ static const char *adau1373_decimator_text[] = { "DMIC1", }; -static const struct soc_enum adau1373_decimator_enum = - SOC_ENUM_SINGLE(0, 0, 2, adau1373_decimator_text); +static SOC_ENUM_SINGLE_VIRT_DECL(adau1373_decimator_enum, + adau1373_decimator_text); static const struct snd_kcontrol_new adau1373_decimator_mux = SOC_DAPM_ENUM_VIRT("Decimator Mux", adau1373_decimator_enum); @@ -1376,15 +1376,8 @@ static int adau1373_probe(struct snd_soc_codec *codec) struct adau1373_platform_data *pdata = codec->dev->platform_data; bool lineout_differential = false; unsigned int val; - int ret; int i; - ret = snd_soc_codec_set_cache_io(codec, 0, 0, SND_SOC_REGMAP); - if (ret) { - dev_err(codec->dev, "failed to set cache I/O: %d\n", ret); - return ret; - } - if (pdata) { if (pdata->num_drc > ARRAY_SIZE(pdata->drc_setting)) return -EINVAL; diff --git a/sound/soc/codecs/adau1977-i2c.c b/sound/soc/codecs/adau1977-i2c.c new file mode 100644 index 00000000000..9700e8c838c --- /dev/null +++ b/sound/soc/codecs/adau1977-i2c.c @@ -0,0 +1,59 @@ +/* + * ADAU1977/ADAU1978/ADAU1979 driver + * + * Copyright 2014 Analog Devices Inc. + * Author: Lars-Peter Clausen <lars@metafoo.de> + * + * Licensed under the GPL-2. + */ + +#include <linux/i2c.h> +#include <linux/mod_devicetable.h> +#include <linux/module.h> +#include <linux/regmap.h> +#include <sound/soc.h> + +#include "adau1977.h" + +static int adau1977_i2c_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + struct regmap_config config; + + config = adau1977_regmap_config; + config.val_bits = 8; + config.reg_bits = 8; + + return adau1977_probe(&client->dev, + devm_regmap_init_i2c(client, &config), + id->driver_data, NULL); +} + +static int adau1977_i2c_remove(struct i2c_client *client) +{ + snd_soc_unregister_codec(&client->dev); + return 0; +} + +static const struct i2c_device_id adau1977_i2c_ids[] = { + { "adau1977", ADAU1977 }, + { "adau1978", ADAU1978 }, + { "adau1979", ADAU1978 }, + { } +}; +MODULE_DEVICE_TABLE(i2c, adau1977_i2c_ids); + +static struct i2c_driver adau1977_i2c_driver = { + .driver = { + .name = "adau1977", + .owner = THIS_MODULE, + }, + .probe = adau1977_i2c_probe, + .remove = adau1977_i2c_remove, + .id_table = adau1977_i2c_ids, +}; +module_i2c_driver(adau1977_i2c_driver); + +MODULE_DESCRIPTION("ASoC ADAU1977/ADAU1978/ADAU1979 driver"); +MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>"); +MODULE_LICENSE("GPL"); diff --git a/sound/soc/codecs/adau1977-spi.c b/sound/soc/codecs/adau1977-spi.c new file mode 100644 index 00000000000..b05cf5da3a9 --- /dev/null +++ b/sound/soc/codecs/adau1977-spi.c @@ -0,0 +1,76 @@ +/* + * ADAU1977/ADAU1978/ADAU1979 driver + * + * Copyright 2014 Analog Devices Inc. + * Author: Lars-Peter Clausen <lars@metafoo.de> + * + * Licensed under the GPL-2. + */ + +#include <linux/mod_devicetable.h> +#include <linux/module.h> +#include <linux/regmap.h> +#include <linux/spi/spi.h> +#include <sound/soc.h> + +#include "adau1977.h" + +static void adau1977_spi_switch_mode(struct device *dev) +{ + struct spi_device *spi = to_spi_device(dev); + + /* + * To get the device into SPI mode CLATCH has to be pulled low three + * times. Do this by issuing three dummy reads. + */ + spi_w8r8(spi, 0x00); + spi_w8r8(spi, 0x00); + spi_w8r8(spi, 0x00); +} + +static int adau1977_spi_probe(struct spi_device *spi) +{ + const struct spi_device_id *id = spi_get_device_id(spi); + struct regmap_config config; + + if (!id) + return -EINVAL; + + config = adau1977_regmap_config; + config.val_bits = 8; + config.reg_bits = 16; + config.read_flag_mask = 0x1; + + return adau1977_probe(&spi->dev, + devm_regmap_init_spi(spi, &config), + id->driver_data, adau1977_spi_switch_mode); +} + +static int adau1977_spi_remove(struct spi_device *spi) +{ + snd_soc_unregister_codec(&spi->dev); + return 0; +} + +static const struct spi_device_id adau1977_spi_ids[] = { + { "adau1977", ADAU1977 }, + { "adau1978", ADAU1978 }, + { "adau1979", ADAU1978 }, + { } +}; +MODULE_DEVICE_TABLE(spi, adau1977_spi_ids); + +static struct spi_driver adau1977_spi_driver = { + .driver = { + .name = "adau1977", + .owner = THIS_MODULE, + }, + .probe = adau1977_spi_probe, + .remove = adau1977_spi_remove, + .id_table = adau1977_spi_ids, +}; +module_spi_driver(adau1977_spi_driver); + +MODULE_DESCRIPTION("ASoC ADAU1977/ADAU1978/ADAU1979 driver"); +MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>"); +MODULE_LICENSE("GPL"); diff --git a/sound/soc/codecs/adau1977.c b/sound/soc/codecs/adau1977.c new file mode 100644 index 00000000000..fd55da7cb9d --- /dev/null +++ b/sound/soc/codecs/adau1977.c @@ -0,0 +1,1018 @@ +/* + * ADAU1977/ADAU1978/ADAU1979 driver + * + * Copyright 2014 Analog Devices Inc. + * Author: Lars-Peter Clausen <lars@metafoo.de> + * + * Licensed under the GPL-2. + */ + +#include <linux/delay.h> +#include <linux/device.h> +#include <linux/gpio/consumer.h> +#include <linux/i2c.h> +#include <linux/init.h> +#include <linux/module.h> +#include <linux/platform_data/adau1977.h> +#include <linux/regmap.h> +#include <linux/regulator/consumer.h> +#include <linux/slab.h> + +#include <sound/core.h> +#include <sound/initval.h> +#include <sound/pcm.h> +#include <sound/pcm_params.h> +#include <sound/soc.h> +#include <sound/tlv.h> + +#include "adau1977.h" + +#define ADAU1977_REG_POWER 0x00 +#define ADAU1977_REG_PLL 0x01 +#define ADAU1977_REG_BOOST 0x02 +#define ADAU1977_REG_MICBIAS 0x03 +#define ADAU1977_REG_BLOCK_POWER_SAI 0x04 +#define ADAU1977_REG_SAI_CTRL0 0x05 +#define ADAU1977_REG_SAI_CTRL1 0x06 +#define ADAU1977_REG_CMAP12 0x07 +#define ADAU1977_REG_CMAP34 0x08 +#define ADAU1977_REG_SAI_OVERTEMP 0x09 +#define ADAU1977_REG_POST_ADC_GAIN(x) (0x0a + (x)) +#define ADAU1977_REG_MISC_CONTROL 0x0e +#define ADAU1977_REG_DIAG_CONTROL 0x10 +#define ADAU1977_REG_STATUS(x) (0x11 + (x)) +#define ADAU1977_REG_DIAG_IRQ1 0x15 +#define ADAU1977_REG_DIAG_IRQ2 0x16 +#define ADAU1977_REG_ADJUST1 0x17 +#define ADAU1977_REG_ADJUST2 0x18 +#define ADAU1977_REG_ADC_CLIP 0x19 +#define ADAU1977_REG_DC_HPF_CAL 0x1a + +#define ADAU1977_POWER_RESET BIT(7) +#define ADAU1977_POWER_PWUP BIT(0) + +#define ADAU1977_PLL_CLK_S BIT(4) +#define ADAU1977_PLL_MCS_MASK 0x7 + +#define ADAU1977_MICBIAS_MB_VOLTS_MASK 0xf0 +#define ADAU1977_MICBIAS_MB_VOLTS_OFFSET 4 + +#define ADAU1977_BLOCK_POWER_SAI_LR_POL BIT(7) +#define ADAU1977_BLOCK_POWER_SAI_BCLK_EDGE BIT(6) +#define ADAU1977_BLOCK_POWER_SAI_LDO_EN BIT(5) + +#define ADAU1977_SAI_CTRL0_FMT_MASK (0x3 << 6) +#define ADAU1977_SAI_CTRL0_FMT_I2S (0x0 << 6) +#define ADAU1977_SAI_CTRL0_FMT_LJ (0x1 << 6) +#define ADAU1977_SAI_CTRL0_FMT_RJ_24BIT (0x2 << 6) +#define ADAU1977_SAI_CTRL0_FMT_RJ_16BIT (0x3 << 6) + +#define ADAU1977_SAI_CTRL0_SAI_MASK (0x7 << 3) +#define ADAU1977_SAI_CTRL0_SAI_I2S (0x0 << 3) +#define ADAU1977_SAI_CTRL0_SAI_TDM_2 (0x1 << 3) +#define ADAU1977_SAI_CTRL0_SAI_TDM_4 (0x2 << 3) +#define ADAU1977_SAI_CTRL0_SAI_TDM_8 (0x3 << 3) +#define ADAU1977_SAI_CTRL0_SAI_TDM_16 (0x4 << 3) + +#define ADAU1977_SAI_CTRL0_FS_MASK (0x7) +#define ADAU1977_SAI_CTRL0_FS_8000_12000 (0x0) +#define ADAU1977_SAI_CTRL0_FS_16000_24000 (0x1) +#define ADAU1977_SAI_CTRL0_FS_32000_48000 (0x2) +#define ADAU1977_SAI_CTRL0_FS_64000_96000 (0x3) +#define ADAU1977_SAI_CTRL0_FS_128000_192000 (0x4) + +#define ADAU1977_SAI_CTRL1_SLOT_WIDTH_MASK (0x3 << 5) +#define ADAU1977_SAI_CTRL1_SLOT_WIDTH_32 (0x0 << 5) +#define ADAU1977_SAI_CTRL1_SLOT_WIDTH_24 (0x1 << 5) +#define ADAU1977_SAI_CTRL1_SLOT_WIDTH_16 (0x2 << 5) +#define ADAU1977_SAI_CTRL1_DATA_WIDTH_MASK (0x1 << 4) +#define ADAU1977_SAI_CTRL1_DATA_WIDTH_16BIT (0x1 << 4) +#define ADAU1977_SAI_CTRL1_DATA_WIDTH_24BIT (0x0 << 4) +#define ADAU1977_SAI_CTRL1_LRCLK_PULSE BIT(3) +#define ADAU1977_SAI_CTRL1_MSB BIT(2) +#define ADAU1977_SAI_CTRL1_BCLKRATE_16 (0x1 << 1) +#define ADAU1977_SAI_CTRL1_BCLKRATE_32 (0x0 << 1) +#define ADAU1977_SAI_CTRL1_BCLKRATE_MASK (0x1 << 1) +#define ADAU1977_SAI_CTRL1_MASTER BIT(0) + +#define ADAU1977_SAI_OVERTEMP_DRV_C(x) BIT(4 + (x)) +#define ADAU1977_SAI_OVERTEMP_DRV_HIZ BIT(3) + +#define ADAU1977_MISC_CONTROL_SUM_MODE_MASK (0x3 << 6) +#define ADAU1977_MISC_CONTROL_SUM_MODE_1CH (0x2 << 6) +#define ADAU1977_MISC_CONTROL_SUM_MODE_2CH (0x1 << 6) +#define ADAU1977_MISC_CONTROL_SUM_MODE_4CH (0x0 << 6) +#define ADAU1977_MISC_CONTROL_MMUTE BIT(4) +#define ADAU1977_MISC_CONTROL_DC_CAL BIT(0) + +#define ADAU1977_CHAN_MAP_SECOND_SLOT_OFFSET 4 +#define ADAU1977_CHAN_MAP_FIRST_SLOT_OFFSET 0 + +struct adau1977 { + struct regmap *regmap; + bool right_j; + unsigned int sysclk; + enum adau1977_sysclk_src sysclk_src; + struct gpio_desc *reset_gpio; + enum adau1977_type type; + + struct regulator *avdd_reg; + struct regulator *dvdd_reg; + + struct snd_pcm_hw_constraint_list constraints; + + struct device *dev; + void (*switch_mode)(struct device *dev); + + unsigned int max_master_fs; + unsigned int slot_width; + bool enabled; + bool master; +}; + +static const struct reg_default adau1977_reg_defaults[] = { + { 0x00, 0x00 }, + { 0x01, 0x41 }, + { 0x02, 0x4a }, + { 0x03, 0x7d }, + { 0x04, 0x3d }, + { 0x05, 0x02 }, + { 0x06, 0x00 }, + { 0x07, 0x10 }, + { 0x08, 0x32 }, + { 0x09, 0xf0 }, + { 0x0a, 0xa0 }, + { 0x0b, 0xa0 }, + { 0x0c, 0xa0 }, + { 0x0d, 0xa0 }, + { 0x0e, 0x02 }, + { 0x10, 0x0f }, + { 0x15, 0x20 }, + { 0x16, 0x00 }, + { 0x17, 0x00 }, + { 0x18, 0x00 }, + { 0x1a, 0x00 }, +}; + +static const DECLARE_TLV_DB_MINMAX_MUTE(adau1977_adc_gain, -3562, 6000); + +static const struct snd_soc_dapm_widget adau1977_micbias_dapm_widgets[] = { + SND_SOC_DAPM_SUPPLY("MICBIAS", ADAU1977_REG_MICBIAS, + 3, 0, NULL, 0) +}; + +static const struct snd_soc_dapm_widget adau1977_dapm_widgets[] = { + SND_SOC_DAPM_SUPPLY("Vref", ADAU1977_REG_BLOCK_POWER_SAI, + 4, 0, NULL, 0), + + SND_SOC_DAPM_ADC("ADC1", "Capture", ADAU1977_REG_BLOCK_POWER_SAI, 0, 0), + SND_SOC_DAPM_ADC("ADC2", "Capture", ADAU1977_REG_BLOCK_POWER_SAI, 1, 0), + SND_SOC_DAPM_ADC("ADC3", "Capture", ADAU1977_REG_BLOCK_POWER_SAI, 2, 0), + SND_SOC_DAPM_ADC("ADC4", "Capture", ADAU1977_REG_BLOCK_POWER_SAI, 3, 0), + + SND_SOC_DAPM_INPUT("AIN1"), + SND_SOC_DAPM_INPUT("AIN2"), + SND_SOC_DAPM_INPUT("AIN3"), + SND_SOC_DAPM_INPUT("AIN4"), + + SND_SOC_DAPM_OUTPUT("VREF"), +}; + +static const struct snd_soc_dapm_route adau1977_dapm_routes[] = { + { "ADC1", NULL, "AIN1" }, + { "ADC2", NULL, "AIN2" }, + { "ADC3", NULL, "AIN3" }, + { "ADC4", NULL, "AIN4" }, + + { "ADC1", NULL, "Vref" }, + { "ADC2", NULL, "Vref" }, + { "ADC3", NULL, "Vref" }, + { "ADC4", NULL, "Vref" }, + + { "VREF", NULL, "Vref" }, +}; + +#define ADAU1977_VOLUME(x) \ + SOC_SINGLE_TLV("ADC" #x " Capture Volume", \ + ADAU1977_REG_POST_ADC_GAIN((x) - 1), \ + 0, 255, 1, adau1977_adc_gain) + +#define ADAU1977_HPF_SWITCH(x) \ + SOC_SINGLE("ADC" #x " Highpass-Filter Capture Switch", \ + ADAU1977_REG_DC_HPF_CAL, (x) - 1, 1, 0) + +#define ADAU1977_DC_SUB_SWITCH(x) \ + SOC_SINGLE("ADC" #x " DC Substraction Capture Switch", \ + ADAU1977_REG_DC_HPF_CAL, (x) + 3, 1, 0) + +static const struct snd_kcontrol_new adau1977_snd_controls[] = { + ADAU1977_VOLUME(1), + ADAU1977_VOLUME(2), + ADAU1977_VOLUME(3), + ADAU1977_VOLUME(4), + + ADAU1977_HPF_SWITCH(1), + ADAU1977_HPF_SWITCH(2), + ADAU1977_HPF_SWITCH(3), + ADAU1977_HPF_SWITCH(4), + + ADAU1977_DC_SUB_SWITCH(1), + ADAU1977_DC_SUB_SWITCH(2), + ADAU1977_DC_SUB_SWITCH(3), + ADAU1977_DC_SUB_SWITCH(4), +}; + +static int adau1977_reset(struct adau1977 *adau1977) +{ + int ret; + + /* + * The reset bit is obviously volatile, but we need to be able to cache + * the other bits in the register, so we can't just mark the whole + * register as volatile. Since this is the only place where we'll ever + * touch the reset bit just bypass the cache for this operation. + */ + regcache_cache_bypass(adau1977->regmap, true); + ret = regmap_write(adau1977->regmap, ADAU1977_REG_POWER, + ADAU1977_POWER_RESET); + regcache_cache_bypass(adau1977->regmap, false); + if (ret) + return ret; + + return ret; +} + +/* + * Returns the appropriate setting for ths FS field in the CTRL0 register + * depending on the rate. + */ +static int adau1977_lookup_fs(unsigned int rate) +{ + if (rate >= 8000 && rate <= 12000) + return ADAU1977_SAI_CTRL0_FS_8000_12000; + else if (rate >= 16000 && rate <= 24000) + return ADAU1977_SAI_CTRL0_FS_16000_24000; + else if (rate >= 32000 && rate <= 48000) + return ADAU1977_SAI_CTRL0_FS_32000_48000; + else if (rate >= 64000 && rate <= 96000) + return ADAU1977_SAI_CTRL0_FS_64000_96000; + else if (rate >= 128000 && rate <= 192000) + return ADAU1977_SAI_CTRL0_FS_128000_192000; + else + return -EINVAL; +} + +static int adau1977_lookup_mcs(struct adau1977 *adau1977, unsigned int rate, + unsigned int fs) +{ + unsigned int mcs; + + /* + * rate = sysclk / (512 * mcs_lut[mcs]) * 2**fs + * => mcs_lut[mcs] = sysclk / (512 * rate) * 2**fs + * => mcs_lut[mcs] = sysclk / ((512 / 2**fs) * rate) + */ + + rate *= 512 >> fs; + + if (adau1977->sysclk % rate != 0) + return -EINVAL; + + mcs = adau1977->sysclk / rate; + + /* The factors configured by MCS are 1, 2, 3, 4, 6 */ + if (mcs < 1 || mcs > 6 || mcs == 5) + return -EINVAL; + + mcs = mcs - 1; + if (mcs == 5) + mcs = 4; + + return mcs; +} + +static int adau1977_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params, struct snd_soc_dai *dai) +{ + struct snd_soc_codec *codec = dai->codec; + struct adau1977 *adau1977 = snd_soc_codec_get_drvdata(codec); + unsigned int rate = params_rate(params); + unsigned int slot_width; + unsigned int ctrl0, ctrl0_mask; + unsigned int ctrl1; + int mcs, fs; + int ret; + + fs = adau1977_lookup_fs(rate); + if (fs < 0) + return fs; + + if (adau1977->sysclk_src == ADAU1977_SYSCLK_SRC_MCLK) { + mcs = adau1977_lookup_mcs(adau1977, rate, fs); + if (mcs < 0) + return mcs; + } else { + mcs = 0; + } + + ctrl0_mask = ADAU1977_SAI_CTRL0_FS_MASK; + ctrl0 = fs; + + if (adau1977->right_j) { + switch (params_width(params)) { + case 16: + ctrl0 |= ADAU1977_SAI_CTRL0_FMT_RJ_16BIT; + break; + case 24: + ctrl0 |= ADAU1977_SAI_CTRL0_FMT_RJ_24BIT; + break; + default: + return -EINVAL; + } + ctrl0_mask |= ADAU1977_SAI_CTRL0_FMT_MASK; + } + + if (adau1977->master) { + switch (params_width(params)) { + case 16: + ctrl1 = ADAU1977_SAI_CTRL1_DATA_WIDTH_16BIT; + slot_width = 16; + break; + case 24: + case 32: + ctrl1 = ADAU1977_SAI_CTRL1_DATA_WIDTH_24BIT; + slot_width = 32; + break; + default: + return -EINVAL; + } + + /* In TDM mode there is a fixed slot width */ + if (adau1977->slot_width) + slot_width = adau1977->slot_width; + + if (slot_width == 16) + ctrl1 |= ADAU1977_SAI_CTRL1_BCLKRATE_16; + else + ctrl1 |= ADAU1977_SAI_CTRL1_BCLKRATE_32; + + ret = regmap_update_bits(adau1977->regmap, + ADAU1977_REG_SAI_CTRL1, + ADAU1977_SAI_CTRL1_DATA_WIDTH_MASK | + ADAU1977_SAI_CTRL1_BCLKRATE_MASK, + ctrl1); + if (ret < 0) + return ret; + } + + ret = regmap_update_bits(adau1977->regmap, ADAU1977_REG_SAI_CTRL0, + ctrl0_mask, ctrl0); + if (ret < 0) + return ret; + + return regmap_update_bits(adau1977->regmap, ADAU1977_REG_PLL, + ADAU1977_PLL_MCS_MASK, mcs); +} + +static int adau1977_power_disable(struct adau1977 *adau1977) +{ + int ret = 0; + + if (!adau1977->enabled) + return 0; + + ret = regmap_update_bits(adau1977->regmap, ADAU1977_REG_POWER, + ADAU1977_POWER_PWUP, 0); + if (ret) + return ret; + + regcache_mark_dirty(adau1977->regmap); + + if (adau1977->reset_gpio) + gpiod_set_value_cansleep(adau1977->reset_gpio, 0); + + regcache_cache_only(adau1977->regmap, true); + + regulator_disable(adau1977->avdd_reg); + if (adau1977->dvdd_reg) + regulator_disable(adau1977->dvdd_reg); + + adau1977->enabled = false; + + return 0; +} + +static int adau1977_power_enable(struct adau1977 *adau1977) +{ + unsigned int val; + int ret = 0; + + if (adau1977->enabled) + return 0; + + ret = regulator_enable(adau1977->avdd_reg); + if (ret) + return ret; + + if (adau1977->dvdd_reg) { + ret = regulator_enable(adau1977->dvdd_reg); + if (ret) + goto err_disable_avdd; + } + + if (adau1977->reset_gpio) + gpiod_set_value_cansleep(adau1977->reset_gpio, 1); + + regcache_cache_only(adau1977->regmap, false); + + if (adau1977->switch_mode) + adau1977->switch_mode(adau1977->dev); + + ret = adau1977_reset(adau1977); + if (ret) + goto err_disable_dvdd; + + ret = regmap_update_bits(adau1977->regmap, ADAU1977_REG_POWER, + ADAU1977_POWER_PWUP, ADAU1977_POWER_PWUP); + if (ret) + goto err_disable_dvdd; + + ret = regcache_sync(adau1977->regmap); + if (ret) + goto err_disable_dvdd; + + /* + * The PLL register is not affected by the software reset. It is + * possible that the value of the register was changed to the + * default value while we were in cache only mode. In this case + * regcache_sync will skip over it and we have to manually sync + * it. + */ + ret = regmap_read(adau1977->regmap, ADAU1977_REG_PLL, &val); + if (ret) + goto err_disable_dvdd; + + if (val == 0x41) { + regcache_cache_bypass(adau1977->regmap, true); + ret = regmap_write(adau1977->regmap, ADAU1977_REG_PLL, + 0x41); + if (ret) + goto err_disable_dvdd; + regcache_cache_bypass(adau1977->regmap, false); + } + + adau1977->enabled = true; + + return ret; + +err_disable_dvdd: + if (adau1977->dvdd_reg) + regulator_disable(adau1977->dvdd_reg); +err_disable_avdd: + regulator_disable(adau1977->avdd_reg); + return ret; +} + +static int adau1977_set_bias_level(struct snd_soc_codec *codec, + enum snd_soc_bias_level level) +{ + struct adau1977 *adau1977 = snd_soc_codec_get_drvdata(codec); + int ret = 0; + + switch (level) { + case SND_SOC_BIAS_ON: + break; + case SND_SOC_BIAS_PREPARE: + break; + case SND_SOC_BIAS_STANDBY: + if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) + ret = adau1977_power_enable(adau1977); + break; + case SND_SOC_BIAS_OFF: + ret = adau1977_power_disable(adau1977); + break; + } + + if (ret) + return ret; + + codec->dapm.bias_level = level; + + return 0; +} + +static int adau1977_set_tdm_slot(struct snd_soc_dai *dai, unsigned int tx_mask, + unsigned int rx_mask, int slots, int width) +{ + struct adau1977 *adau1977 = snd_soc_codec_get_drvdata(dai->codec); + unsigned int ctrl0, ctrl1, drv; + unsigned int slot[4]; + unsigned int i; + int ret; + + if (slots == 0) { + /* 0 = No fixed slot width */ + adau1977->slot_width = 0; + adau1977->max_master_fs = 192000; + return regmap_update_bits(adau1977->regmap, + ADAU1977_REG_SAI_CTRL0, ADAU1977_SAI_CTRL0_SAI_MASK, + ADAU1977_SAI_CTRL0_SAI_I2S); + } + + if (rx_mask == 0 || tx_mask != 0) + return -EINVAL; + + drv = 0; + for (i = 0; i < 4; i++) { + slot[i] = __ffs(rx_mask); + drv |= ADAU1977_SAI_OVERTEMP_DRV_C(i); + rx_mask &= ~(1 << slot[i]); + if (slot[i] >= slots) + return -EINVAL; + if (rx_mask == 0) + break; + } + + if (rx_mask != 0) + return -EINVAL; + + switch (width) { + case 16: + ctrl1 = ADAU1977_SAI_CTRL1_SLOT_WIDTH_16; + break; + case 24: + /* We can only generate 16 bit or 32 bit wide slots */ + if (adau1977->master) + return -EINVAL; + ctrl1 = ADAU1977_SAI_CTRL1_SLOT_WIDTH_24; + break; + case 32: + ctrl1 = ADAU1977_SAI_CTRL1_SLOT_WIDTH_32; + break; + default: + return -EINVAL; + } + + switch (slots) { + case 2: + ctrl0 = ADAU1977_SAI_CTRL0_SAI_TDM_2; + break; + case 4: + ctrl0 = ADAU1977_SAI_CTRL0_SAI_TDM_4; + break; + case 8: + ctrl0 = ADAU1977_SAI_CTRL0_SAI_TDM_8; + break; + case 16: + ctrl0 = ADAU1977_SAI_CTRL0_SAI_TDM_16; + break; + default: + return -EINVAL; + } + + ret = regmap_update_bits(adau1977->regmap, ADAU1977_REG_SAI_OVERTEMP, + ADAU1977_SAI_OVERTEMP_DRV_C(0) | + ADAU1977_SAI_OVERTEMP_DRV_C(1) | + ADAU1977_SAI_OVERTEMP_DRV_C(2) | + ADAU1977_SAI_OVERTEMP_DRV_C(3), drv); + if (ret) + return ret; + + ret = regmap_write(adau1977->regmap, ADAU1977_REG_CMAP12, + (slot[1] << ADAU1977_CHAN_MAP_SECOND_SLOT_OFFSET) | + (slot[0] << ADAU1977_CHAN_MAP_FIRST_SLOT_OFFSET)); + if (ret) + return ret; + + ret = regmap_write(adau1977->regmap, ADAU1977_REG_CMAP34, + (slot[3] << ADAU1977_CHAN_MAP_SECOND_SLOT_OFFSET) | + (slot[2] << ADAU1977_CHAN_MAP_FIRST_SLOT_OFFSET)); + if (ret) + return ret; + + ret = regmap_update_bits(adau1977->regmap, ADAU1977_REG_SAI_CTRL0, + ADAU1977_SAI_CTRL0_SAI_MASK, ctrl0); + if (ret) + return ret; + + ret = regmap_update_bits(adau1977->regmap, ADAU1977_REG_SAI_CTRL1, + ADAU1977_SAI_CTRL1_SLOT_WIDTH_MASK, ctrl1); + if (ret) + return ret; + + adau1977->slot_width = width; + + /* In master mode the maximum bitclock is 24.576 MHz */ + adau1977->max_master_fs = min(192000, 24576000 / width / slots); + + return 0; +} + +static int adau1977_mute(struct snd_soc_dai *dai, int mute, int stream) +{ + struct adau1977 *adau1977 = snd_soc_codec_get_drvdata(dai->codec); + unsigned int val; + + if (mute) + val = ADAU1977_MISC_CONTROL_MMUTE; + else + val = 0; + + return regmap_update_bits(adau1977->regmap, ADAU1977_REG_MISC_CONTROL, + ADAU1977_MISC_CONTROL_MMUTE, val); +} + +static int adau1977_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt) +{ + struct adau1977 *adau1977 = snd_soc_codec_get_drvdata(dai->codec); + unsigned int ctrl0 = 0, ctrl1 = 0, block_power = 0; + bool invert_lrclk; + int ret; + + switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { + case SND_SOC_DAIFMT_CBS_CFS: + adau1977->master = false; + break; + case SND_SOC_DAIFMT_CBM_CFM: + ctrl1 |= ADAU1977_SAI_CTRL1_MASTER; + adau1977->master = true; + break; + default: + return -EINVAL; + } + + switch (fmt & SND_SOC_DAIFMT_INV_MASK) { + case SND_SOC_DAIFMT_NB_NF: + invert_lrclk = false; + break; + case SND_SOC_DAIFMT_IB_NF: + block_power |= ADAU1977_BLOCK_POWER_SAI_BCLK_EDGE; + invert_lrclk = false; + break; + case SND_SOC_DAIFMT_NB_IF: + invert_lrclk = true; + break; + case SND_SOC_DAIFMT_IB_IF: + block_power |= ADAU1977_BLOCK_POWER_SAI_BCLK_EDGE; + invert_lrclk = true; + break; + default: + return -EINVAL; + } + + adau1977->right_j = false; + switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { + case SND_SOC_DAIFMT_I2S: + ctrl0 |= ADAU1977_SAI_CTRL0_FMT_I2S; + break; + case SND_SOC_DAIFMT_LEFT_J: + ctrl0 |= ADAU1977_SAI_CTRL0_FMT_LJ; + invert_lrclk = !invert_lrclk; + break; + case SND_SOC_DAIFMT_RIGHT_J: + ctrl0 |= ADAU1977_SAI_CTRL0_FMT_RJ_24BIT; + adau1977->right_j = true; + invert_lrclk = !invert_lrclk; + break; + case SND_SOC_DAIFMT_DSP_A: + ctrl1 |= ADAU1977_SAI_CTRL1_LRCLK_PULSE; + ctrl0 |= ADAU1977_SAI_CTRL0_FMT_I2S; + invert_lrclk = false; + break; + case SND_SOC_DAIFMT_DSP_B: + ctrl1 |= ADAU1977_SAI_CTRL1_LRCLK_PULSE; + ctrl0 |= ADAU1977_SAI_CTRL0_FMT_LJ; + invert_lrclk = false; + break; + default: + return -EINVAL; + } + + if (invert_lrclk) + block_power |= ADAU1977_BLOCK_POWER_SAI_LR_POL; + + ret = regmap_update_bits(adau1977->regmap, ADAU1977_REG_BLOCK_POWER_SAI, + ADAU1977_BLOCK_POWER_SAI_LR_POL | + ADAU1977_BLOCK_POWER_SAI_BCLK_EDGE, block_power); + if (ret) + return ret; + + ret = regmap_update_bits(adau1977->regmap, ADAU1977_REG_SAI_CTRL0, + ADAU1977_SAI_CTRL0_FMT_MASK, + ctrl0); + if (ret) + return ret; + + return regmap_update_bits(adau1977->regmap, ADAU1977_REG_SAI_CTRL1, + ADAU1977_SAI_CTRL1_MASTER | ADAU1977_SAI_CTRL1_LRCLK_PULSE, + ctrl1); +} + +static int adau1977_startup(struct snd_pcm_substream *substream, + struct snd_soc_dai *dai) +{ + struct adau1977 *adau1977 = snd_soc_codec_get_drvdata(dai->codec); + u64 formats = 0; + + if (adau1977->slot_width == 16) + formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S16_BE; + else if (adau1977->right_j || adau1977->slot_width == 24) + formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S16_BE | + SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S24_BE; + + snd_pcm_hw_constraint_list(substream->runtime, 0, + SNDRV_PCM_HW_PARAM_RATE, &adau1977->constraints); + + if (adau1977->master) + snd_pcm_hw_constraint_minmax(substream->runtime, + SNDRV_PCM_HW_PARAM_RATE, 8000, adau1977->max_master_fs); + + if (formats != 0) + snd_pcm_hw_constraint_mask64(substream->runtime, + SNDRV_PCM_HW_PARAM_FORMAT, formats); + + return 0; +} + +static int adau1977_set_tristate(struct snd_soc_dai *dai, int tristate) +{ + struct adau1977 *adau1977 = snd_soc_codec_get_drvdata(dai->codec); + unsigned int val; + + if (tristate) + val = ADAU1977_SAI_OVERTEMP_DRV_HIZ; + else + val = 0; + + return regmap_update_bits(adau1977->regmap, ADAU1977_REG_SAI_OVERTEMP, + ADAU1977_SAI_OVERTEMP_DRV_HIZ, val); +} + +static const struct snd_soc_dai_ops adau1977_dai_ops = { + .startup = adau1977_startup, + .hw_params = adau1977_hw_params, + .mute_stream = adau1977_mute, + .set_fmt = adau1977_set_dai_fmt, + .set_tdm_slot = adau1977_set_tdm_slot, + .set_tristate = adau1977_set_tristate, +}; + +static struct snd_soc_dai_driver adau1977_dai = { + .name = "adau1977-hifi", + .capture = { + .stream_name = "Capture", + .channels_min = 1, + .channels_max = 4, + .rates = SNDRV_PCM_RATE_KNOT, + .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE | + SNDRV_PCM_FMTBIT_S32_LE, + .sig_bits = 24, + }, + .ops = &adau1977_dai_ops, +}; + +static const unsigned int adau1977_rates[] = { + 8000, 16000, 32000, 64000, 128000, + 11025, 22050, 44100, 88200, 172400, + 12000, 24000, 48000, 96000, 192000, +}; + +#define ADAU1977_RATE_CONSTRAINT_MASK_32000 0x001f +#define ADAU1977_RATE_CONSTRAINT_MASK_44100 0x03e0 +#define ADAU1977_RATE_CONSTRAINT_MASK_48000 0x7c00 +/* All rates >= 32000 */ +#define ADAU1977_RATE_CONSTRAINT_MASK_LRCLK 0x739c + +static bool adau1977_check_sysclk(unsigned int mclk, unsigned int base_freq) +{ + unsigned int mcs; + + if (mclk % (base_freq * 128) != 0) + return false; + + mcs = mclk / (128 * base_freq); + if (mcs < 1 || mcs > 6 || mcs == 5) + return false; + + return true; +} + +static int adau1977_set_sysclk(struct snd_soc_codec *codec, + int clk_id, int source, unsigned int freq, int dir) +{ + struct adau1977 *adau1977 = snd_soc_codec_get_drvdata(codec); + unsigned int mask = 0; + unsigned int clk_src; + unsigned int ret; + + if (dir != SND_SOC_CLOCK_IN) + return -EINVAL; + + if (clk_id != ADAU1977_SYSCLK) + return -EINVAL; + + switch (source) { + case ADAU1977_SYSCLK_SRC_MCLK: + clk_src = 0; + break; + case ADAU1977_SYSCLK_SRC_LRCLK: + clk_src = ADAU1977_PLL_CLK_S; + break; + default: + return -EINVAL; + } + + if (freq != 0 && source == ADAU1977_SYSCLK_SRC_MCLK) { + if (freq < 4000000 || freq > 36864000) + return -EINVAL; + + if (adau1977_check_sysclk(freq, 32000)) + mask |= ADAU1977_RATE_CONSTRAINT_MASK_32000; + if (adau1977_check_sysclk(freq, 44100)) + mask |= ADAU1977_RATE_CONSTRAINT_MASK_44100; + if (adau1977_check_sysclk(freq, 48000)) + mask |= ADAU1977_RATE_CONSTRAINT_MASK_48000; + + if (mask == 0) + return -EINVAL; + } else if (source == ADAU1977_SYSCLK_SRC_LRCLK) { + mask = ADAU1977_RATE_CONSTRAINT_MASK_LRCLK; + } + + ret = regmap_update_bits(adau1977->regmap, ADAU1977_REG_PLL, + ADAU1977_PLL_CLK_S, clk_src); + if (ret) + return ret; + + adau1977->constraints.mask = mask; + adau1977->sysclk_src = source; + adau1977->sysclk = freq; + + return 0; +} + +static int adau1977_codec_probe(struct snd_soc_codec *codec) +{ + struct adau1977 *adau1977 = snd_soc_codec_get_drvdata(codec); + int ret; + + switch (adau1977->type) { + case ADAU1977: + ret = snd_soc_dapm_new_controls(&codec->dapm, + adau1977_micbias_dapm_widgets, + ARRAY_SIZE(adau1977_micbias_dapm_widgets)); + if (ret < 0) + return ret; + break; + default: + break; + } + + return 0; +} + +static struct snd_soc_codec_driver adau1977_codec_driver = { + .probe = adau1977_codec_probe, + .set_bias_level = adau1977_set_bias_level, + .set_sysclk = adau1977_set_sysclk, + .idle_bias_off = true, + + .controls = adau1977_snd_controls, + .num_controls = ARRAY_SIZE(adau1977_snd_controls), + .dapm_widgets = adau1977_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(adau1977_dapm_widgets), + .dapm_routes = adau1977_dapm_routes, + .num_dapm_routes = ARRAY_SIZE(adau1977_dapm_routes), +}; + +static int adau1977_setup_micbias(struct adau1977 *adau1977) +{ + struct adau1977_platform_data *pdata = adau1977->dev->platform_data; + unsigned int micbias; + + if (pdata) { + micbias = pdata->micbias; + if (micbias > ADAU1977_MICBIAS_9V0) + return -EINVAL; + + } else { + micbias = ADAU1977_MICBIAS_8V5; + } + + return regmap_update_bits(adau1977->regmap, ADAU1977_REG_MICBIAS, + ADAU1977_MICBIAS_MB_VOLTS_MASK, + micbias << ADAU1977_MICBIAS_MB_VOLTS_OFFSET); +} + +int adau1977_probe(struct device *dev, struct regmap *regmap, + enum adau1977_type type, void (*switch_mode)(struct device *dev)) +{ + unsigned int power_off_mask; + struct adau1977 *adau1977; + int ret; + + if (IS_ERR(regmap)) + return PTR_ERR(regmap); + + adau1977 = devm_kzalloc(dev, sizeof(*adau1977), GFP_KERNEL); + if (adau1977 == NULL) + return -ENOMEM; + + adau1977->dev = dev; + adau1977->type = type; + adau1977->regmap = regmap; + adau1977->switch_mode = switch_mode; + adau1977->max_master_fs = 192000; + + adau1977->constraints.list = adau1977_rates; + adau1977->constraints.count = ARRAY_SIZE(adau1977_rates); + + adau1977->avdd_reg = devm_regulator_get(dev, "AVDD"); + if (IS_ERR(adau1977->avdd_reg)) + return PTR_ERR(adau1977->avdd_reg); + + adau1977->dvdd_reg = devm_regulator_get_optional(dev, "DVDD"); + if (IS_ERR(adau1977->dvdd_reg)) { + if (PTR_ERR(adau1977->dvdd_reg) != -ENODEV) + return PTR_ERR(adau1977->dvdd_reg); + adau1977->dvdd_reg = NULL; + } + + adau1977->reset_gpio = devm_gpiod_get(dev, "reset"); + if (IS_ERR(adau1977->reset_gpio)) { + ret = PTR_ERR(adau1977->reset_gpio); + if (ret != -ENOENT && ret != -ENOSYS) + return PTR_ERR(adau1977->reset_gpio); + adau1977->reset_gpio = NULL; + } + + dev_set_drvdata(dev, adau1977); + + if (adau1977->reset_gpio) { + ret = gpiod_direction_output(adau1977->reset_gpio, 0); + if (ret) + return ret; + ndelay(100); + } + + ret = adau1977_power_enable(adau1977); + if (ret) + return ret; + + if (type == ADAU1977) { + ret = adau1977_setup_micbias(adau1977); + if (ret) + goto err_poweroff; + } + + if (adau1977->dvdd_reg) + power_off_mask = ~0; + else + power_off_mask = ~ADAU1977_BLOCK_POWER_SAI_LDO_EN; + + ret = regmap_update_bits(adau1977->regmap, ADAU1977_REG_BLOCK_POWER_SAI, + power_off_mask, 0x00); + if (ret) + goto err_poweroff; + + ret = adau1977_power_disable(adau1977); + if (ret) + return ret; + + return snd_soc_register_codec(dev, &adau1977_codec_driver, + &adau1977_dai, 1); + +err_poweroff: + adau1977_power_disable(adau1977); + return ret; + +} +EXPORT_SYMBOL_GPL(adau1977_probe); + +static bool adau1977_register_volatile(struct device *dev, unsigned int reg) +{ + switch (reg) { + case ADAU1977_REG_STATUS(0): + case ADAU1977_REG_STATUS(1): + case ADAU1977_REG_STATUS(2): + case ADAU1977_REG_STATUS(3): + case ADAU1977_REG_ADC_CLIP: + return true; + } + + return false; +} + +const struct regmap_config adau1977_regmap_config = { + .max_register = ADAU1977_REG_DC_HPF_CAL, + .volatile_reg = adau1977_register_volatile, + + .cache_type = REGCACHE_RBTREE, + .reg_defaults = adau1977_reg_defaults, + .num_reg_defaults = ARRAY_SIZE(adau1977_reg_defaults), +}; +EXPORT_SYMBOL_GPL(adau1977_regmap_config); + +MODULE_DESCRIPTION("ASoC ADAU1977/ADAU1978/ADAU1979 driver"); +MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>"); +MODULE_LICENSE("GPL"); diff --git a/sound/soc/codecs/adau1977.h b/sound/soc/codecs/adau1977.h new file mode 100644 index 00000000000..95e714345a8 --- /dev/null +++ b/sound/soc/codecs/adau1977.h @@ -0,0 +1,37 @@ +/* + * ADAU1977/ADAU1978/ADAU1979 driver + * + * Copyright 2014 Analog Devices Inc. + * Author: Lars-Peter Clausen <lars@metafoo.de> + * + * Licensed under the GPL-2. + */ + +#ifndef __SOUND_SOC_CODECS_ADAU1977_H__ +#define __SOUND_SOC_CODECS_ADAU1977_H__ + +#include <linux/regmap.h> + +struct device; + +enum adau1977_type { + ADAU1977, + ADAU1978, + ADAU1979, +}; + +int adau1977_probe(struct device *dev, struct regmap *regmap, + enum adau1977_type type, void (*switch_mode)(struct device *dev)); + +extern const struct regmap_config adau1977_regmap_config; + +enum adau1977_clk_id { + ADAU1977_SYSCLK, +}; + +enum adau1977_sysclk_src { + ADAU1977_SYSCLK_SRC_MCLK, + ADAU1977_SYSCLK_SRC_LRCLK, +}; + +#endif diff --git a/sound/soc/codecs/adav801.c b/sound/soc/codecs/adav801.c new file mode 100644 index 00000000000..790fce33ab1 --- /dev/null +++ b/sound/soc/codecs/adav801.c @@ -0,0 +1,53 @@ +/* + * ADAV801 audio driver + * + * Copyright 2014 Analog Devices Inc. + * + * Licensed under the GPL-2. + */ + +#include <linux/module.h> +#include <linux/spi/spi.h> +#include <linux/regmap.h> + +#include <sound/soc.h> + +#include "adav80x.h" + +static const struct spi_device_id adav80x_spi_id[] = { + { "adav801", 0 }, + { } +}; +MODULE_DEVICE_TABLE(spi, adav80x_spi_id); + +static int adav80x_spi_probe(struct spi_device *spi) +{ + struct regmap_config config; + + config = adav80x_regmap_config; + config.read_flag_mask = 0x01; + + return adav80x_bus_probe(&spi->dev, devm_regmap_init_spi(spi, &config)); +} + +static int adav80x_spi_remove(struct spi_device *spi) +{ + snd_soc_unregister_codec(&spi->dev); + return 0; +} + +static struct spi_driver adav80x_spi_driver = { + .driver = { + .name = "adav801", + .owner = THIS_MODULE, + }, + .probe = adav80x_spi_probe, + .remove = adav80x_spi_remove, + .id_table = adav80x_spi_id, +}; +module_spi_driver(adav80x_spi_driver); + +MODULE_DESCRIPTION("ASoC ADAV801 driver"); +MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>"); +MODULE_AUTHOR("Yi Li <yi.li@analog.com>>"); +MODULE_LICENSE("GPL"); diff --git a/sound/soc/codecs/adav803.c b/sound/soc/codecs/adav803.c new file mode 100644 index 00000000000..66d9fce34e6 --- /dev/null +++ b/sound/soc/codecs/adav803.c @@ -0,0 +1,50 @@ +/* + * ADAV803 audio driver + * + * Copyright 2014 Analog Devices Inc. + * + * Licensed under the GPL-2. + */ + +#include <linux/module.h> +#include <linux/i2c.h> +#include <linux/regmap.h> + +#include <sound/soc.h> + +#include "adav80x.h" + +static const struct i2c_device_id adav803_id[] = { + { "adav803", 0 }, + { } +}; +MODULE_DEVICE_TABLE(i2c, adav803_id); + +static int adav803_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + return adav80x_bus_probe(&client->dev, + devm_regmap_init_i2c(client, &adav80x_regmap_config)); +} + +static int adav803_remove(struct i2c_client *client) +{ + snd_soc_unregister_codec(&client->dev); + return 0; +} + +static struct i2c_driver adav803_driver = { + .driver = { + .name = "adav803", + .owner = THIS_MODULE, + }, + .probe = adav803_probe, + .remove = adav803_remove, + .id_table = adav803_id, +}; +module_i2c_driver(adav803_driver); + +MODULE_DESCRIPTION("ASoC ADAV803 driver"); +MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>"); +MODULE_AUTHOR("Yi Li <yi.li@analog.com>>"); +MODULE_LICENSE("GPL"); diff --git a/sound/soc/codecs/adav80x.c b/sound/soc/codecs/adav80x.c index f78b27a7c46..5062e34ee8d 100644 --- a/sound/soc/codecs/adav80x.c +++ b/sound/soc/codecs/adav80x.c @@ -8,17 +8,15 @@ * Licensed under the GPL-2 or later. */ -#include <linux/init.h> #include <linux/module.h> #include <linux/kernel.h> -#include <linux/i2c.h> -#include <linux/spi/spi.h> +#include <linux/regmap.h> #include <linux/slab.h> -#include <sound/core.h> + #include <sound/pcm.h> #include <sound/pcm_params.h> -#include <sound/tlv.h> #include <sound/soc.h> +#include <sound/tlv.h> #include "adav80x.h" @@ -541,6 +539,7 @@ static int adav80x_set_sysclk(struct snd_soc_codec *codec, unsigned int freq, int dir) { struct adav80x *adav80x = snd_soc_codec_get_drvdata(codec); + struct snd_soc_dapm_context *dapm = &codec->dapm; if (dir == SND_SOC_CLOCK_IN) { switch (clk_id) { @@ -573,7 +572,7 @@ static int adav80x_set_sysclk(struct snd_soc_codec *codec, regmap_write(adav80x->regmap, ADAV80X_ICLK_CTRL2, iclk_ctrl2); - snd_soc_dapm_sync(&codec->dapm); + snd_soc_dapm_sync(dapm); } } else { unsigned int mask; @@ -600,17 +599,21 @@ static int adav80x_set_sysclk(struct snd_soc_codec *codec, adav80x->sysclk_pd[clk_id] = false; } + snd_soc_dapm_mutex_lock(dapm); + if (adav80x->sysclk_pd[0]) - snd_soc_dapm_disable_pin(&codec->dapm, "PLL1"); + snd_soc_dapm_disable_pin_unlocked(dapm, "PLL1"); else - snd_soc_dapm_force_enable_pin(&codec->dapm, "PLL1"); + snd_soc_dapm_force_enable_pin_unlocked(dapm, "PLL1"); if (adav80x->sysclk_pd[1] || adav80x->sysclk_pd[2]) - snd_soc_dapm_disable_pin(&codec->dapm, "PLL2"); + snd_soc_dapm_disable_pin_unlocked(dapm, "PLL2"); else - snd_soc_dapm_force_enable_pin(&codec->dapm, "PLL2"); + snd_soc_dapm_force_enable_pin_unlocked(dapm, "PLL2"); - snd_soc_dapm_sync(&codec->dapm); + snd_soc_dapm_sync_unlocked(dapm); + + snd_soc_dapm_mutex_unlock(dapm); } return 0; @@ -722,7 +725,7 @@ static int adav80x_dai_startup(struct snd_pcm_substream *substream, struct snd_soc_codec *codec = dai->codec; struct adav80x *adav80x = snd_soc_codec_get_drvdata(codec); - if (!codec->active || !adav80x->rate) + if (!snd_soc_codec_is_active(codec) || !adav80x->rate) return 0; return snd_pcm_hw_constraint_minmax(substream->runtime, @@ -735,7 +738,7 @@ static void adav80x_dai_shutdown(struct snd_pcm_substream *substream, struct snd_soc_codec *codec = dai->codec; struct adav80x *adav80x = snd_soc_codec_get_drvdata(codec); - if (!codec->active) + if (!snd_soc_codec_is_active(codec)) adav80x->rate = 0; } @@ -798,15 +801,8 @@ static struct snd_soc_dai_driver adav80x_dais[] = { static int adav80x_probe(struct snd_soc_codec *codec) { - int ret; struct adav80x *adav80x = snd_soc_codec_get_drvdata(codec); - ret = snd_soc_codec_set_cache_io(codec, 0, 0, SND_SOC_REGMAP); - if (ret) { - dev_err(codec->dev, "failed to set cache I/O: %d\n", ret); - return ret; - } - /* Force PLLs on for SYSCLK output */ snd_soc_dapm_force_enable_pin(&codec->dapm, "PLL1"); snd_soc_dapm_force_enable_pin(&codec->dapm, "PLL2"); @@ -864,39 +860,26 @@ static struct snd_soc_codec_driver adav80x_codec_driver = { .num_dapm_routes = ARRAY_SIZE(adav80x_dapm_routes), }; -static int adav80x_bus_probe(struct device *dev, struct regmap *regmap) +int adav80x_bus_probe(struct device *dev, struct regmap *regmap) { struct adav80x *adav80x; - int ret; if (IS_ERR(regmap)) return PTR_ERR(regmap); - adav80x = kzalloc(sizeof(*adav80x), GFP_KERNEL); + adav80x = devm_kzalloc(dev, sizeof(*adav80x), GFP_KERNEL); if (!adav80x) return -ENOMEM; - dev_set_drvdata(dev, adav80x); adav80x->regmap = regmap; - ret = snd_soc_register_codec(dev, &adav80x_codec_driver, + return snd_soc_register_codec(dev, &adav80x_codec_driver, adav80x_dais, ARRAY_SIZE(adav80x_dais)); - if (ret) - kfree(adav80x); - - return ret; -} - -static int adav80x_bus_remove(struct device *dev) -{ - snd_soc_unregister_codec(dev); - kfree(dev_get_drvdata(dev)); - return 0; } +EXPORT_SYMBOL_GPL(adav80x_bus_probe); -#if defined(CONFIG_SPI_MASTER) -static const struct regmap_config adav80x_spi_regmap_config = { +const struct regmap_config adav80x_regmap_config = { .val_bits = 8, .pad_bits = 1, .reg_bits = 7, @@ -908,105 +891,7 @@ static const struct regmap_config adav80x_spi_regmap_config = { .reg_defaults = adav80x_reg_defaults, .num_reg_defaults = ARRAY_SIZE(adav80x_reg_defaults), }; - -static const struct spi_device_id adav80x_spi_id[] = { - { "adav801", 0 }, - { } -}; -MODULE_DEVICE_TABLE(spi, adav80x_spi_id); - -static int adav80x_spi_probe(struct spi_device *spi) -{ - return adav80x_bus_probe(&spi->dev, - devm_regmap_init_spi(spi, &adav80x_spi_regmap_config)); -} - -static int adav80x_spi_remove(struct spi_device *spi) -{ - return adav80x_bus_remove(&spi->dev); -} - -static struct spi_driver adav80x_spi_driver = { - .driver = { - .name = "adav801", - .owner = THIS_MODULE, - }, - .probe = adav80x_spi_probe, - .remove = adav80x_spi_remove, - .id_table = adav80x_spi_id, -}; -#endif - -#if IS_ENABLED(CONFIG_I2C) -static const struct regmap_config adav80x_i2c_regmap_config = { - .val_bits = 8, - .pad_bits = 1, - .reg_bits = 7, - - .max_register = ADAV80X_PLL_OUTE, - - .cache_type = REGCACHE_RBTREE, - .reg_defaults = adav80x_reg_defaults, - .num_reg_defaults = ARRAY_SIZE(adav80x_reg_defaults), -}; - -static const struct i2c_device_id adav80x_i2c_id[] = { - { "adav803", 0 }, - { } -}; -MODULE_DEVICE_TABLE(i2c, adav80x_i2c_id); - -static int adav80x_i2c_probe(struct i2c_client *client, - const struct i2c_device_id *id) -{ - return adav80x_bus_probe(&client->dev, - devm_regmap_init_i2c(client, &adav80x_i2c_regmap_config)); -} - -static int adav80x_i2c_remove(struct i2c_client *client) -{ - return adav80x_bus_remove(&client->dev); -} - -static struct i2c_driver adav80x_i2c_driver = { - .driver = { - .name = "adav803", - .owner = THIS_MODULE, - }, - .probe = adav80x_i2c_probe, - .remove = adav80x_i2c_remove, - .id_table = adav80x_i2c_id, -}; -#endif - -static int __init adav80x_init(void) -{ - int ret = 0; - -#if IS_ENABLED(CONFIG_I2C) - ret = i2c_add_driver(&adav80x_i2c_driver); - if (ret) - return ret; -#endif - -#if defined(CONFIG_SPI_MASTER) - ret = spi_register_driver(&adav80x_spi_driver); -#endif - - return ret; -} -module_init(adav80x_init); - -static void __exit adav80x_exit(void) -{ -#if IS_ENABLED(CONFIG_I2C) - i2c_del_driver(&adav80x_i2c_driver); -#endif -#if defined(CONFIG_SPI_MASTER) - spi_unregister_driver(&adav80x_spi_driver); -#endif -} -module_exit(adav80x_exit); +EXPORT_SYMBOL_GPL(adav80x_regmap_config); MODULE_DESCRIPTION("ASoC ADAV80x driver"); MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>"); diff --git a/sound/soc/codecs/adav80x.h b/sound/soc/codecs/adav80x.h index adb0fc76d4e..8a1d7c09dca 100644 --- a/sound/soc/codecs/adav80x.h +++ b/sound/soc/codecs/adav80x.h @@ -9,6 +9,13 @@ #ifndef _ADAV80X_H #define _ADAV80X_H +#include <linux/regmap.h> + +struct device; + +extern const struct regmap_config adav80x_regmap_config; +int adav80x_bus_probe(struct device *dev, struct regmap *regmap); + enum adav80x_pll_src { ADAV80X_PLL_SRC_XIN, ADAV80X_PLL_SRC_XTAL, diff --git a/sound/soc/codecs/ak4104.c b/sound/soc/codecs/ak4104.c index b4819dcd4f4..10adf25d4c1 100644 --- a/sound/soc/codecs/ak4104.c +++ b/sound/soc/codecs/ak4104.c @@ -174,8 +174,6 @@ static int ak4104_probe(struct snd_soc_codec *codec) struct ak4104_private *ak4104 = snd_soc_codec_get_drvdata(codec); int ret; - codec->control_data = ak4104->regmap; - /* set power-up and non-reset bits */ ret = regmap_update_bits(ak4104->regmap, AK4104_REG_CONTROL1, AK4104_CONTROL1_PW | AK4104_CONTROL1_RSTN, diff --git a/sound/soc/codecs/ak4535.c b/sound/soc/codecs/ak4535.c index 684fe910669..30e297890fe 100644 --- a/sound/soc/codecs/ak4535.c +++ b/sound/soc/codecs/ak4535.c @@ -388,15 +388,6 @@ static int ak4535_resume(struct snd_soc_codec *codec) static int ak4535_probe(struct snd_soc_codec *codec) { - struct ak4535_priv *ak4535 = snd_soc_codec_get_drvdata(codec); - int ret; - - codec->control_data = ak4535->regmap; - ret = snd_soc_codec_set_cache_io(codec, 8, 8, SND_SOC_REGMAP); - if (ret < 0) { - dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); - return ret; - } /* power on device */ ak4535_set_bias_level(codec, SND_SOC_BIAS_STANDBY); diff --git a/sound/soc/codecs/ak4641.c b/sound/soc/codecs/ak4641.c index 94cbe508dd3..868c0e2da1e 100644 --- a/sound/soc/codecs/ak4641.c +++ b/sound/soc/codecs/ak4641.c @@ -113,14 +113,14 @@ static const DECLARE_TLV_DB_SCALE(alc_tlv, -800, 50, 0); static const DECLARE_TLV_DB_SCALE(aux_in_tlv, -2100, 300, 0); -static const struct soc_enum ak4641_mono_out_enum = - SOC_ENUM_SINGLE(AK4641_SIG1, 6, 2, ak4641_mono_out); -static const struct soc_enum ak4641_hp_out_enum = - SOC_ENUM_SINGLE(AK4641_MODE2, 2, 2, ak4641_hp_out); -static const struct soc_enum ak4641_mic_select_enum = - SOC_ENUM_SINGLE(AK4641_MIC, 1, 2, ak4641_mic_select); -static const struct soc_enum ak4641_mic_or_dac_enum = - SOC_ENUM_SINGLE(AK4641_BTIF, 4, 2, ak4641_mic_or_dac); +static SOC_ENUM_SINGLE_DECL(ak4641_mono_out_enum, + AK4641_SIG1, 6, ak4641_mono_out); +static SOC_ENUM_SINGLE_DECL(ak4641_hp_out_enum, + AK4641_MODE2, 2, ak4641_hp_out); +static SOC_ENUM_SINGLE_DECL(ak4641_mic_select_enum, + AK4641_MIC, 1, ak4641_mic_select); +static SOC_ENUM_SINGLE_DECL(ak4641_mic_or_dac_enum, + AK4641_BTIF, 4, ak4641_mic_or_dac); static const struct snd_kcontrol_new ak4641_snd_controls[] = { SOC_ENUM("Mono 1 Output", ak4641_mono_out_enum), @@ -519,14 +519,6 @@ static int ak4641_resume(struct snd_soc_codec *codec) static int ak4641_probe(struct snd_soc_codec *codec) { - int ret; - - ret = snd_soc_codec_set_cache_io(codec, 8, 8, SND_SOC_REGMAP); - if (ret != 0) { - dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); - return ret; - } - /* power on device */ ak4641_set_bias_level(codec, SND_SOC_BIAS_STANDBY); diff --git a/sound/soc/codecs/ak4642.c b/sound/soc/codecs/ak4642.c index 1f646c6e90c..92655cc189a 100644 --- a/sound/soc/codecs/ak4642.c +++ b/sound/soc/codecs/ak4642.c @@ -465,14 +465,6 @@ static int ak4642_resume(struct snd_soc_codec *codec) static int ak4642_probe(struct snd_soc_codec *codec) { - int ret; - - ret = snd_soc_codec_set_cache_io(codec, 8, 8, SND_SOC_REGMAP); - if (ret < 0) { - dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); - return ret; - } - ak4642_set_bias_level(codec, SND_SOC_BIAS_STANDBY); return 0; diff --git a/sound/soc/codecs/ak4671.c b/sound/soc/codecs/ak4671.c index 25bdf6ad4a5..998fa0c5a0b 100644 --- a/sound/soc/codecs/ak4671.c +++ b/sound/soc/codecs/ak4671.c @@ -15,6 +15,7 @@ #include <linux/init.h> #include <linux/i2c.h> #include <linux/delay.h> +#include <linux/regmap.h> #include <linux/slab.h> #include <sound/soc.h> #include <sound/initval.h> @@ -23,104 +24,99 @@ #include "ak4671.h" -/* codec private data */ -struct ak4671_priv { - enum snd_soc_control_type control_type; -}; - /* ak4671 register cache & default register settings */ -static const u8 ak4671_reg[AK4671_CACHEREGNUM] = { - 0x00, /* AK4671_AD_DA_POWER_MANAGEMENT (0x00) */ - 0xf6, /* AK4671_PLL_MODE_SELECT0 (0x01) */ - 0x00, /* AK4671_PLL_MODE_SELECT1 (0x02) */ - 0x02, /* AK4671_FORMAT_SELECT (0x03) */ - 0x00, /* AK4671_MIC_SIGNAL_SELECT (0x04) */ - 0x55, /* AK4671_MIC_AMP_GAIN (0x05) */ - 0x00, /* AK4671_MIXING_POWER_MANAGEMENT0 (0x06) */ - 0x00, /* AK4671_MIXING_POWER_MANAGEMENT1 (0x07) */ - 0xb5, /* AK4671_OUTPUT_VOLUME_CONTROL (0x08) */ - 0x00, /* AK4671_LOUT1_SIGNAL_SELECT (0x09) */ - 0x00, /* AK4671_ROUT1_SIGNAL_SELECT (0x0a) */ - 0x00, /* AK4671_LOUT2_SIGNAL_SELECT (0x0b) */ - 0x00, /* AK4671_ROUT2_SIGNAL_SELECT (0x0c) */ - 0x00, /* AK4671_LOUT3_SIGNAL_SELECT (0x0d) */ - 0x00, /* AK4671_ROUT3_SIGNAL_SELECT (0x0e) */ - 0x00, /* AK4671_LOUT1_POWER_MANAGERMENT (0x0f) */ - 0x00, /* AK4671_LOUT2_POWER_MANAGERMENT (0x10) */ - 0x80, /* AK4671_LOUT3_POWER_MANAGERMENT (0x11) */ - 0x91, /* AK4671_LCH_INPUT_VOLUME_CONTROL (0x12) */ - 0x91, /* AK4671_RCH_INPUT_VOLUME_CONTROL (0x13) */ - 0xe1, /* AK4671_ALC_REFERENCE_SELECT (0x14) */ - 0x00, /* AK4671_DIGITAL_MIXING_CONTROL (0x15) */ - 0x00, /* AK4671_ALC_TIMER_SELECT (0x16) */ - 0x00, /* AK4671_ALC_MODE_CONTROL (0x17) */ - 0x02, /* AK4671_MODE_CONTROL1 (0x18) */ - 0x01, /* AK4671_MODE_CONTROL2 (0x19) */ - 0x18, /* AK4671_LCH_OUTPUT_VOLUME_CONTROL (0x1a) */ - 0x18, /* AK4671_RCH_OUTPUT_VOLUME_CONTROL (0x1b) */ - 0x00, /* AK4671_SIDETONE_A_CONTROL (0x1c) */ - 0x02, /* AK4671_DIGITAL_FILTER_SELECT (0x1d) */ - 0x00, /* AK4671_FIL3_COEFFICIENT0 (0x1e) */ - 0x00, /* AK4671_FIL3_COEFFICIENT1 (0x1f) */ - 0x00, /* AK4671_FIL3_COEFFICIENT2 (0x20) */ - 0x00, /* AK4671_FIL3_COEFFICIENT3 (0x21) */ - 0x00, /* AK4671_EQ_COEFFICIENT0 (0x22) */ - 0x00, /* AK4671_EQ_COEFFICIENT1 (0x23) */ - 0x00, /* AK4671_EQ_COEFFICIENT2 (0x24) */ - 0x00, /* AK4671_EQ_COEFFICIENT3 (0x25) */ - 0x00, /* AK4671_EQ_COEFFICIENT4 (0x26) */ - 0x00, /* AK4671_EQ_COEFFICIENT5 (0x27) */ - 0xa9, /* AK4671_FIL1_COEFFICIENT0 (0x28) */ - 0x1f, /* AK4671_FIL1_COEFFICIENT1 (0x29) */ - 0xad, /* AK4671_FIL1_COEFFICIENT2 (0x2a) */ - 0x20, /* AK4671_FIL1_COEFFICIENT3 (0x2b) */ - 0x00, /* AK4671_FIL2_COEFFICIENT0 (0x2c) */ - 0x00, /* AK4671_FIL2_COEFFICIENT1 (0x2d) */ - 0x00, /* AK4671_FIL2_COEFFICIENT2 (0x2e) */ - 0x00, /* AK4671_FIL2_COEFFICIENT3 (0x2f) */ - 0x00, /* AK4671_DIGITAL_FILTER_SELECT2 (0x30) */ - 0x00, /* this register not used */ - 0x00, /* AK4671_E1_COEFFICIENT0 (0x32) */ - 0x00, /* AK4671_E1_COEFFICIENT1 (0x33) */ - 0x00, /* AK4671_E1_COEFFICIENT2 (0x34) */ - 0x00, /* AK4671_E1_COEFFICIENT3 (0x35) */ - 0x00, /* AK4671_E1_COEFFICIENT4 (0x36) */ - 0x00, /* AK4671_E1_COEFFICIENT5 (0x37) */ - 0x00, /* AK4671_E2_COEFFICIENT0 (0x38) */ - 0x00, /* AK4671_E2_COEFFICIENT1 (0x39) */ - 0x00, /* AK4671_E2_COEFFICIENT2 (0x3a) */ - 0x00, /* AK4671_E2_COEFFICIENT3 (0x3b) */ - 0x00, /* AK4671_E2_COEFFICIENT4 (0x3c) */ - 0x00, /* AK4671_E2_COEFFICIENT5 (0x3d) */ - 0x00, /* AK4671_E3_COEFFICIENT0 (0x3e) */ - 0x00, /* AK4671_E3_COEFFICIENT1 (0x3f) */ - 0x00, /* AK4671_E3_COEFFICIENT2 (0x40) */ - 0x00, /* AK4671_E3_COEFFICIENT3 (0x41) */ - 0x00, /* AK4671_E3_COEFFICIENT4 (0x42) */ - 0x00, /* AK4671_E3_COEFFICIENT5 (0x43) */ - 0x00, /* AK4671_E4_COEFFICIENT0 (0x44) */ - 0x00, /* AK4671_E4_COEFFICIENT1 (0x45) */ - 0x00, /* AK4671_E4_COEFFICIENT2 (0x46) */ - 0x00, /* AK4671_E4_COEFFICIENT3 (0x47) */ - 0x00, /* AK4671_E4_COEFFICIENT4 (0x48) */ - 0x00, /* AK4671_E4_COEFFICIENT5 (0x49) */ - 0x00, /* AK4671_E5_COEFFICIENT0 (0x4a) */ - 0x00, /* AK4671_E5_COEFFICIENT1 (0x4b) */ - 0x00, /* AK4671_E5_COEFFICIENT2 (0x4c) */ - 0x00, /* AK4671_E5_COEFFICIENT3 (0x4d) */ - 0x00, /* AK4671_E5_COEFFICIENT4 (0x4e) */ - 0x00, /* AK4671_E5_COEFFICIENT5 (0x4f) */ - 0x88, /* AK4671_EQ_CONTROL_250HZ_100HZ (0x50) */ - 0x88, /* AK4671_EQ_CONTROL_3500HZ_1KHZ (0x51) */ - 0x08, /* AK4671_EQ_CONTRO_10KHZ (0x52) */ - 0x00, /* AK4671_PCM_IF_CONTROL0 (0x53) */ - 0x00, /* AK4671_PCM_IF_CONTROL1 (0x54) */ - 0x00, /* AK4671_PCM_IF_CONTROL2 (0x55) */ - 0x18, /* AK4671_DIGITAL_VOLUME_B_CONTROL (0x56) */ - 0x18, /* AK4671_DIGITAL_VOLUME_C_CONTROL (0x57) */ - 0x00, /* AK4671_SIDETONE_VOLUME_CONTROL (0x58) */ - 0x00, /* AK4671_DIGITAL_MIXING_CONTROL2 (0x59) */ - 0x00, /* AK4671_SAR_ADC_CONTROL (0x5a) */ +static const struct reg_default ak4671_reg_defaults[] = { + { 0x00, 0x00 }, /* AK4671_AD_DA_POWER_MANAGEMENT (0x00) */ + { 0x01, 0xf6 }, /* AK4671_PLL_MODE_SELECT0 (0x01) */ + { 0x02, 0x00 }, /* AK4671_PLL_MODE_SELECT1 (0x02) */ + { 0x03, 0x02 }, /* AK4671_FORMAT_SELECT (0x03) */ + { 0x04, 0x00 }, /* AK4671_MIC_SIGNAL_SELECT (0x04) */ + { 0x05, 0x55 }, /* AK4671_MIC_AMP_GAIN (0x05) */ + { 0x06, 0x00 }, /* AK4671_MIXING_POWER_MANAGEMENT0 (0x06) */ + { 0x07, 0x00 }, /* AK4671_MIXING_POWER_MANAGEMENT1 (0x07) */ + { 0x08, 0xb5 }, /* AK4671_OUTPUT_VOLUME_CONTROL (0x08) */ + { 0x09, 0x00 }, /* AK4671_LOUT1_SIGNAL_SELECT (0x09) */ + { 0x0a, 0x00 }, /* AK4671_ROUT1_SIGNAL_SELECT (0x0a) */ + { 0x0b, 0x00 }, /* AK4671_LOUT2_SIGNAL_SELECT (0x0b) */ + { 0x0c, 0x00 }, /* AK4671_ROUT2_SIGNAL_SELECT (0x0c) */ + { 0x0d, 0x00 }, /* AK4671_LOUT3_SIGNAL_SELECT (0x0d) */ + { 0x0e, 0x00 }, /* AK4671_ROUT3_SIGNAL_SELECT (0x0e) */ + { 0x0f, 0x00 }, /* AK4671_LOUT1_POWER_MANAGERMENT (0x0f) */ + { 0x10, 0x00 }, /* AK4671_LOUT2_POWER_MANAGERMENT (0x10) */ + { 0x11, 0x80 }, /* AK4671_LOUT3_POWER_MANAGERMENT (0x11) */ + { 0x12, 0x91 }, /* AK4671_LCH_INPUT_VOLUME_CONTROL (0x12) */ + { 0x13, 0x91 }, /* AK4671_RCH_INPUT_VOLUME_CONTROL (0x13) */ + { 0x14, 0xe1 }, /* AK4671_ALC_REFERENCE_SELECT (0x14) */ + { 0x15, 0x00 }, /* AK4671_DIGITAL_MIXING_CONTROL (0x15) */ + { 0x16, 0x00 }, /* AK4671_ALC_TIMER_SELECT (0x16) */ + { 0x17, 0x00 }, /* AK4671_ALC_MODE_CONTROL (0x17) */ + { 0x18, 0x02 }, /* AK4671_MODE_CONTROL1 (0x18) */ + { 0x19, 0x01 }, /* AK4671_MODE_CONTROL2 (0x19) */ + { 0x1a, 0x18 }, /* AK4671_LCH_OUTPUT_VOLUME_CONTROL (0x1a) */ + { 0x1b, 0x18 }, /* AK4671_RCH_OUTPUT_VOLUME_CONTROL (0x1b) */ + { 0x1c, 0x00 }, /* AK4671_SIDETONE_A_CONTROL (0x1c) */ + { 0x1d, 0x02 }, /* AK4671_DIGITAL_FILTER_SELECT (0x1d) */ + { 0x1e, 0x00 }, /* AK4671_FIL3_COEFFICIENT0 (0x1e) */ + { 0x1f, 0x00 }, /* AK4671_FIL3_COEFFICIENT1 (0x1f) */ + { 0x20, 0x00 }, /* AK4671_FIL3_COEFFICIENT2 (0x20) */ + { 0x21, 0x00 }, /* AK4671_FIL3_COEFFICIENT3 (0x21) */ + { 0x22, 0x00 }, /* AK4671_EQ_COEFFICIENT0 (0x22) */ + { 0x23, 0x00 }, /* AK4671_EQ_COEFFICIENT1 (0x23) */ + { 0x24, 0x00 }, /* AK4671_EQ_COEFFICIENT2 (0x24) */ + { 0x25, 0x00 }, /* AK4671_EQ_COEFFICIENT3 (0x25) */ + { 0x26, 0x00 }, /* AK4671_EQ_COEFFICIENT4 (0x26) */ + { 0x27, 0x00 }, /* AK4671_EQ_COEFFICIENT5 (0x27) */ + { 0x28, 0xa9 }, /* AK4671_FIL1_COEFFICIENT0 (0x28) */ + { 0x29, 0x1f }, /* AK4671_FIL1_COEFFICIENT1 (0x29) */ + { 0x2a, 0xad }, /* AK4671_FIL1_COEFFICIENT2 (0x2a) */ + { 0x2b, 0x20 }, /* AK4671_FIL1_COEFFICIENT3 (0x2b) */ + { 0x2c, 0x00 }, /* AK4671_FIL2_COEFFICIENT0 (0x2c) */ + { 0x2d, 0x00 }, /* AK4671_FIL2_COEFFICIENT1 (0x2d) */ + { 0x2e, 0x00 }, /* AK4671_FIL2_COEFFICIENT2 (0x2e) */ + { 0x2f, 0x00 }, /* AK4671_FIL2_COEFFICIENT3 (0x2f) */ + { 0x30, 0x00 }, /* AK4671_DIGITAL_FILTER_SELECT2 (0x30) */ + + { 0x32, 0x00 }, /* AK4671_E1_COEFFICIENT0 (0x32) */ + { 0x33, 0x00 }, /* AK4671_E1_COEFFICIENT1 (0x33) */ + { 0x34, 0x00 }, /* AK4671_E1_COEFFICIENT2 (0x34) */ + { 0x35, 0x00 }, /* AK4671_E1_COEFFICIENT3 (0x35) */ + { 0x36, 0x00 }, /* AK4671_E1_COEFFICIENT4 (0x36) */ + { 0x37, 0x00 }, /* AK4671_E1_COEFFICIENT5 (0x37) */ + { 0x38, 0x00 }, /* AK4671_E2_COEFFICIENT0 (0x38) */ + { 0x39, 0x00 }, /* AK4671_E2_COEFFICIENT1 (0x39) */ + { 0x3a, 0x00 }, /* AK4671_E2_COEFFICIENT2 (0x3a) */ + { 0x3b, 0x00 }, /* AK4671_E2_COEFFICIENT3 (0x3b) */ + { 0x3c, 0x00 }, /* AK4671_E2_COEFFICIENT4 (0x3c) */ + { 0x3d, 0x00 }, /* AK4671_E2_COEFFICIENT5 (0x3d) */ + { 0x3e, 0x00 }, /* AK4671_E3_COEFFICIENT0 (0x3e) */ + { 0x3f, 0x00 }, /* AK4671_E3_COEFFICIENT1 (0x3f) */ + { 0x40, 0x00 }, /* AK4671_E3_COEFFICIENT2 (0x40) */ + { 0x41, 0x00 }, /* AK4671_E3_COEFFICIENT3 (0x41) */ + { 0x42, 0x00 }, /* AK4671_E3_COEFFICIENT4 (0x42) */ + { 0x43, 0x00 }, /* AK4671_E3_COEFFICIENT5 (0x43) */ + { 0x44, 0x00 }, /* AK4671_E4_COEFFICIENT0 (0x44) */ + { 0x45, 0x00 }, /* AK4671_E4_COEFFICIENT1 (0x45) */ + { 0x46, 0x00 }, /* AK4671_E4_COEFFICIENT2 (0x46) */ + { 0x47, 0x00 }, /* AK4671_E4_COEFFICIENT3 (0x47) */ + { 0x48, 0x00 }, /* AK4671_E4_COEFFICIENT4 (0x48) */ + { 0x49, 0x00 }, /* AK4671_E4_COEFFICIENT5 (0x49) */ + { 0x4a, 0x00 }, /* AK4671_E5_COEFFICIENT0 (0x4a) */ + { 0x4b, 0x00 }, /* AK4671_E5_COEFFICIENT1 (0x4b) */ + { 0x4c, 0x00 }, /* AK4671_E5_COEFFICIENT2 (0x4c) */ + { 0x4d, 0x00 }, /* AK4671_E5_COEFFICIENT3 (0x4d) */ + { 0x4e, 0x00 }, /* AK4671_E5_COEFFICIENT4 (0x4e) */ + { 0x4f, 0x00 }, /* AK4671_E5_COEFFICIENT5 (0x4f) */ + { 0x50, 0x88 }, /* AK4671_EQ_CONTROL_250HZ_100HZ (0x50) */ + { 0x51, 0x88 }, /* AK4671_EQ_CONTROL_3500HZ_1KHZ (0x51) */ + { 0x52, 0x08 }, /* AK4671_EQ_CONTRO_10KHZ (0x52) */ + { 0x53, 0x00 }, /* AK4671_PCM_IF_CONTROL0 (0x53) */ + { 0x54, 0x00 }, /* AK4671_PCM_IF_CONTROL1 (0x54) */ + { 0x55, 0x00 }, /* AK4671_PCM_IF_CONTROL2 (0x55) */ + { 0x56, 0x18 }, /* AK4671_DIGITAL_VOLUME_B_CONTROL (0x56) */ + { 0x57, 0x18 }, /* AK4671_DIGITAL_VOLUME_C_CONTROL (0x57) */ + { 0x58, 0x00 }, /* AK4671_SIDETONE_VOLUME_CONTROL (0x58) */ + { 0x59, 0x00 }, /* AK4671_DIGITAL_MIXING_CONTROL2 (0x59) */ + { 0x5a, 0x00 }, /* AK4671_SAR_ADC_CONTROL (0x5a) */ }; /* @@ -241,19 +237,17 @@ static const struct snd_kcontrol_new ak4671_rout3_mixer_controls[] = { /* Input MUXs */ static const char *ak4671_lin_mux_texts[] = {"LIN1", "LIN2", "LIN3", "LIN4"}; -static const struct soc_enum ak4671_lin_mux_enum = - SOC_ENUM_SINGLE(AK4671_MIC_SIGNAL_SELECT, 0, - ARRAY_SIZE(ak4671_lin_mux_texts), - ak4671_lin_mux_texts); +static SOC_ENUM_SINGLE_DECL(ak4671_lin_mux_enum, + AK4671_MIC_SIGNAL_SELECT, 0, + ak4671_lin_mux_texts); static const struct snd_kcontrol_new ak4671_lin_mux_control = SOC_DAPM_ENUM("Route", ak4671_lin_mux_enum); static const char *ak4671_rin_mux_texts[] = {"RIN1", "RIN2", "RIN3", "RIN4"}; -static const struct soc_enum ak4671_rin_mux_enum = - SOC_ENUM_SINGLE(AK4671_MIC_SIGNAL_SELECT, 2, - ARRAY_SIZE(ak4671_rin_mux_texts), - ak4671_rin_mux_texts); +static SOC_ENUM_SINGLE_DECL(ak4671_rin_mux_enum, + AK4671_MIC_SIGNAL_SELECT, 2, + ak4671_rin_mux_texts); static const struct snd_kcontrol_new ak4671_rin_mux_control = SOC_DAPM_ENUM("Route", ak4671_rin_mux_enum); @@ -619,21 +613,7 @@ static struct snd_soc_dai_driver ak4671_dai = { static int ak4671_probe(struct snd_soc_codec *codec) { - struct ak4671_priv *ak4671 = snd_soc_codec_get_drvdata(codec); - int ret; - - ret = snd_soc_codec_set_cache_io(codec, 8, 8, ak4671->control_type); - if (ret < 0) { - dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); - return ret; - } - - snd_soc_add_codec_controls(codec, ak4671_snd_controls, - ARRAY_SIZE(ak4671_snd_controls)); - - ak4671_set_bias_level(codec, SND_SOC_BIAS_STANDBY); - - return ret; + return ak4671_set_bias_level(codec, SND_SOC_BIAS_STANDBY); } static int ak4671_remove(struct snd_soc_codec *codec) @@ -646,28 +626,36 @@ static struct snd_soc_codec_driver soc_codec_dev_ak4671 = { .probe = ak4671_probe, .remove = ak4671_remove, .set_bias_level = ak4671_set_bias_level, - .reg_cache_size = AK4671_CACHEREGNUM, - .reg_word_size = sizeof(u8), - .reg_cache_default = ak4671_reg, + .controls = ak4671_snd_controls, + .num_controls = ARRAY_SIZE(ak4671_snd_controls), .dapm_widgets = ak4671_dapm_widgets, .num_dapm_widgets = ARRAY_SIZE(ak4671_dapm_widgets), .dapm_routes = ak4671_intercon, .num_dapm_routes = ARRAY_SIZE(ak4671_intercon), }; +static const struct regmap_config ak4671_regmap = { + .reg_bits = 8, + .val_bits = 8, + + .max_register = AK4671_SAR_ADC_CONTROL, + .reg_defaults = ak4671_reg_defaults, + .num_reg_defaults = ARRAY_SIZE(ak4671_reg_defaults), + .cache_type = REGCACHE_RBTREE, +}; + static int ak4671_i2c_probe(struct i2c_client *client, const struct i2c_device_id *id) { - struct ak4671_priv *ak4671; + struct regmap *regmap; int ret; - ak4671 = devm_kzalloc(&client->dev, sizeof(struct ak4671_priv), - GFP_KERNEL); - if (ak4671 == NULL) - return -ENOMEM; - - i2c_set_clientdata(client, ak4671); - ak4671->control_type = SND_SOC_I2C; + regmap = devm_regmap_init_i2c(client, &ak4671_regmap); + if (IS_ERR(regmap)) { + ret = PTR_ERR(regmap); + dev_err(&client->dev, "Failed to create regmap: %d\n", ret); + return ret; + } ret = snd_soc_register_codec(&client->dev, &soc_codec_dev_ak4671, &ak4671_dai, 1); diff --git a/sound/soc/codecs/ak4671.h b/sound/soc/codecs/ak4671.h index 61cb7ab7552..394a34d3f50 100644 --- a/sound/soc/codecs/ak4671.h +++ b/sound/soc/codecs/ak4671.h @@ -105,8 +105,6 @@ #define AK4671_DIGITAL_MIXING_CONTROL2 0x59 #define AK4671_SAR_ADC_CONTROL 0x5a -#define AK4671_CACHEREGNUM (AK4671_SAR_ADC_CONTROL + 1) - /* Bitfield Definitions */ /* AK4671_AD_DA_POWER_MANAGEMENT (0x00) Fields */ diff --git a/sound/soc/codecs/alc5623.c b/sound/soc/codecs/alc5623.c index d3036283482..09f7e773baf 100644 --- a/sound/soc/codecs/alc5623.c +++ b/sound/soc/codecs/alc5623.c @@ -21,6 +21,7 @@ #include <linux/delay.h> #include <linux/pm.h> #include <linux/i2c.h> +#include <linux/regmap.h> #include <linux/slab.h> #include <sound/core.h> #include <sound/pcm.h> @@ -38,26 +39,13 @@ MODULE_PARM_DESC(caps_charge, "ALC5623 cap charge time (msecs)"); /* codec private data */ struct alc5623_priv { - enum snd_soc_control_type control_type; + struct regmap *regmap; u8 id; unsigned int sysclk; - u16 reg_cache[ALC5623_VENDOR_ID2+2]; unsigned int add_ctrl; unsigned int jack_det_ctrl; }; -static void alc5623_fill_cache(struct snd_soc_codec *codec) -{ - int i, step = codec->driver->reg_cache_step; - u16 *cache = codec->reg_cache; - - /* not really efficient ... */ - codec->cache_bypass = 1; - for (i = 0 ; i < codec->driver->reg_cache_size ; i += step) - cache[i] = snd_soc_read(codec, i); - codec->cache_bypass = 0; -} - static inline int alc5623_reset(struct snd_soc_codec *codec) { return snd_soc_write(codec, ALC5623_RESET, 0); @@ -228,32 +216,37 @@ static const char *alc5623_aux_out_input_sel[] = { "Vmid", "HPOut Mix", "Speaker Mix", "Mono Mix"}; /* auxout output mux */ -static const struct soc_enum alc5623_aux_out_input_enum = -SOC_ENUM_SINGLE(ALC5623_OUTPUT_MIXER_CTRL, 6, 4, alc5623_aux_out_input_sel); +static SOC_ENUM_SINGLE_DECL(alc5623_aux_out_input_enum, + ALC5623_OUTPUT_MIXER_CTRL, 6, + alc5623_aux_out_input_sel); static const struct snd_kcontrol_new alc5623_auxout_mux_controls = SOC_DAPM_ENUM("Route", alc5623_aux_out_input_enum); /* speaker output mux */ -static const struct soc_enum alc5623_spkout_input_enum = -SOC_ENUM_SINGLE(ALC5623_OUTPUT_MIXER_CTRL, 10, 4, alc5623_spkout_input_sel); +static SOC_ENUM_SINGLE_DECL(alc5623_spkout_input_enum, + ALC5623_OUTPUT_MIXER_CTRL, 10, + alc5623_spkout_input_sel); static const struct snd_kcontrol_new alc5623_spkout_mux_controls = SOC_DAPM_ENUM("Route", alc5623_spkout_input_enum); /* headphone left output mux */ -static const struct soc_enum alc5623_hpl_out_input_enum = -SOC_ENUM_SINGLE(ALC5623_OUTPUT_MIXER_CTRL, 9, 2, alc5623_hpl_out_input_sel); +static SOC_ENUM_SINGLE_DECL(alc5623_hpl_out_input_enum, + ALC5623_OUTPUT_MIXER_CTRL, 9, + alc5623_hpl_out_input_sel); static const struct snd_kcontrol_new alc5623_hpl_out_mux_controls = SOC_DAPM_ENUM("Route", alc5623_hpl_out_input_enum); /* headphone right output mux */ -static const struct soc_enum alc5623_hpr_out_input_enum = -SOC_ENUM_SINGLE(ALC5623_OUTPUT_MIXER_CTRL, 8, 2, alc5623_hpr_out_input_sel); +static SOC_ENUM_SINGLE_DECL(alc5623_hpr_out_input_enum, + ALC5623_OUTPUT_MIXER_CTRL, 8, + alc5623_hpr_out_input_sel); static const struct snd_kcontrol_new alc5623_hpr_out_mux_controls = SOC_DAPM_ENUM("Route", alc5623_hpr_out_input_enum); /* speaker output N select */ -static const struct soc_enum alc5623_spk_n_sour_enum = -SOC_ENUM_SINGLE(ALC5623_OUTPUT_MIXER_CTRL, 14, 4, alc5623_spk_n_sour_sel); +static SOC_ENUM_SINGLE_DECL(alc5623_spk_n_sour_enum, + ALC5623_OUTPUT_MIXER_CTRL, 14, + alc5623_spk_n_sour_sel); static const struct snd_kcontrol_new alc5623_spkoutn_mux_controls = SOC_DAPM_ENUM("Route", alc5623_spk_n_sour_enum); @@ -338,8 +331,9 @@ SND_SOC_DAPM_VMID("Vmid"), }; static const char *alc5623_amp_names[] = {"AB Amp", "D Amp"}; -static const struct soc_enum alc5623_amp_enum = - SOC_ENUM_SINGLE(ALC5623_OUTPUT_MIXER_CTRL, 13, 2, alc5623_amp_names); +static SOC_ENUM_SINGLE_DECL(alc5623_amp_enum, + ALC5623_OUTPUT_MIXER_CTRL, 13, + alc5623_amp_names); static const struct snd_kcontrol_new alc5623_amp_mux_controls = SOC_DAPM_ENUM("Route", alc5623_amp_enum); @@ -869,18 +863,28 @@ static struct snd_soc_dai_driver alc5623_dai = { static int alc5623_suspend(struct snd_soc_codec *codec) { + struct alc5623_priv *alc5623 = snd_soc_codec_get_drvdata(codec); + alc5623_set_bias_level(codec, SND_SOC_BIAS_OFF); + regcache_cache_only(alc5623->regmap, true); + return 0; } static int alc5623_resume(struct snd_soc_codec *codec) { - int i, step = codec->driver->reg_cache_step; - u16 *cache = codec->reg_cache; + struct alc5623_priv *alc5623 = snd_soc_codec_get_drvdata(codec); + int ret; /* Sync reg_cache with the hardware */ - for (i = 2 ; i < codec->driver->reg_cache_size ; i += step) - snd_soc_write(codec, i, cache[i]); + regcache_cache_only(alc5623->regmap, false); + ret = regcache_sync(alc5623->regmap); + if (ret != 0) { + dev_err(codec->dev, "Failed to sync register cache: %d\n", + ret); + regcache_cache_only(alc5623->regmap, true); + return ret; + } alc5623_set_bias_level(codec, SND_SOC_BIAS_STANDBY); @@ -900,14 +904,7 @@ static int alc5623_probe(struct snd_soc_codec *codec) struct snd_soc_dapm_context *dapm = &codec->dapm; int ret; - ret = snd_soc_codec_set_cache_io(codec, 8, 16, alc5623->control_type); - if (ret < 0) { - dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); - return ret; - } - alc5623_reset(codec); - alc5623_fill_cache(codec); /* power on device */ alc5623_set_bias_level(codec, SND_SOC_BIAS_STANDBY); @@ -980,9 +977,15 @@ static struct snd_soc_codec_driver soc_codec_device_alc5623 = { .suspend = alc5623_suspend, .resume = alc5623_resume, .set_bias_level = alc5623_set_bias_level, - .reg_cache_size = ALC5623_VENDOR_ID2+2, - .reg_word_size = sizeof(u16), - .reg_cache_step = 2, +}; + +static const struct regmap_config alc5623_regmap = { + .reg_bits = 8, + .val_bits = 16, + .reg_stride = 2, + + .max_register = ALC5623_VENDOR_ID2, + .cache_type = REGCACHE_RBTREE, }; /* @@ -996,19 +999,32 @@ static int alc5623_i2c_probe(struct i2c_client *client, { struct alc5623_platform_data *pdata; struct alc5623_priv *alc5623; - int ret, vid1, vid2; + unsigned int vid1, vid2; + int ret; - vid1 = i2c_smbus_read_word_data(client, ALC5623_VENDOR_ID1); - if (vid1 < 0) { - dev_err(&client->dev, "failed to read I2C\n"); - return -EIO; + alc5623 = devm_kzalloc(&client->dev, sizeof(struct alc5623_priv), + GFP_KERNEL); + if (alc5623 == NULL) + return -ENOMEM; + + alc5623->regmap = devm_regmap_init_i2c(client, &alc5623_regmap); + if (IS_ERR(alc5623->regmap)) { + ret = PTR_ERR(alc5623->regmap); + dev_err(&client->dev, "Failed to initialise I/O: %d\n", ret); + return ret; + } + + ret = regmap_read(alc5623->regmap, ALC5623_VENDOR_ID1, &vid1); + if (ret < 0) { + dev_err(&client->dev, "failed to read vendor ID1: %d\n", ret); + return ret; } vid1 = ((vid1 & 0xff) << 8) | (vid1 >> 8); - vid2 = i2c_smbus_read_byte_data(client, ALC5623_VENDOR_ID2); - if (vid2 < 0) { - dev_err(&client->dev, "failed to read I2C\n"); - return -EIO; + ret = regmap_read(alc5623->regmap, ALC5623_VENDOR_ID2, &vid2); + if (ret < 0) { + dev_err(&client->dev, "failed to read vendor ID2: %d\n", ret); + return ret; } if ((vid1 != 0x10ec) || (vid2 != id->driver_data)) { @@ -1021,11 +1037,6 @@ static int alc5623_i2c_probe(struct i2c_client *client, dev_dbg(&client->dev, "Found codec id : alc56%02x\n", vid2); - alc5623 = devm_kzalloc(&client->dev, sizeof(struct alc5623_priv), - GFP_KERNEL); - if (alc5623 == NULL) - return -ENOMEM; - pdata = client->dev.platform_data; if (pdata) { alc5623->add_ctrl = pdata->add_ctrl; @@ -1048,7 +1059,6 @@ static int alc5623_i2c_probe(struct i2c_client *client, } i2c_set_clientdata(client, alc5623); - alc5623->control_type = SND_SOC_I2C; ret = snd_soc_register_codec(&client->dev, &soc_codec_device_alc5623, &alc5623_dai, 1); diff --git a/sound/soc/codecs/alc5632.c b/sound/soc/codecs/alc5632.c index fb001c56cf8..ec071a6306e 100644 --- a/sound/soc/codecs/alc5632.c +++ b/sound/soc/codecs/alc5632.c @@ -293,51 +293,59 @@ static const char * const alc5632_i2s_out_sel[] = { "ADC LR", "Voice Stereo Digital"}; /* auxout output mux */ -static const struct soc_enum alc5632_aux_out_input_enum = -SOC_ENUM_SINGLE(ALC5632_OUTPUT_MIXER_CTRL, 6, 4, alc5632_aux_out_input_sel); +static SOC_ENUM_SINGLE_DECL(alc5632_aux_out_input_enum, + ALC5632_OUTPUT_MIXER_CTRL, 6, + alc5632_aux_out_input_sel); static const struct snd_kcontrol_new alc5632_auxout_mux_controls = SOC_DAPM_ENUM("AuxOut Mux", alc5632_aux_out_input_enum); /* speaker output mux */ -static const struct soc_enum alc5632_spkout_input_enum = -SOC_ENUM_SINGLE(ALC5632_OUTPUT_MIXER_CTRL, 10, 4, alc5632_spkout_input_sel); +static SOC_ENUM_SINGLE_DECL(alc5632_spkout_input_enum, + ALC5632_OUTPUT_MIXER_CTRL, 10, + alc5632_spkout_input_sel); static const struct snd_kcontrol_new alc5632_spkout_mux_controls = SOC_DAPM_ENUM("SpeakerOut Mux", alc5632_spkout_input_enum); /* headphone left output mux */ -static const struct soc_enum alc5632_hpl_out_input_enum = -SOC_ENUM_SINGLE(ALC5632_OUTPUT_MIXER_CTRL, 9, 2, alc5632_hpl_out_input_sel); +static SOC_ENUM_SINGLE_DECL(alc5632_hpl_out_input_enum, + ALC5632_OUTPUT_MIXER_CTRL, 9, + alc5632_hpl_out_input_sel); static const struct snd_kcontrol_new alc5632_hpl_out_mux_controls = SOC_DAPM_ENUM("Left Headphone Mux", alc5632_hpl_out_input_enum); /* headphone right output mux */ -static const struct soc_enum alc5632_hpr_out_input_enum = -SOC_ENUM_SINGLE(ALC5632_OUTPUT_MIXER_CTRL, 8, 2, alc5632_hpr_out_input_sel); +static SOC_ENUM_SINGLE_DECL(alc5632_hpr_out_input_enum, + ALC5632_OUTPUT_MIXER_CTRL, 8, + alc5632_hpr_out_input_sel); static const struct snd_kcontrol_new alc5632_hpr_out_mux_controls = SOC_DAPM_ENUM("Right Headphone Mux", alc5632_hpr_out_input_enum); /* speaker output N select */ -static const struct soc_enum alc5632_spk_n_sour_enum = -SOC_ENUM_SINGLE(ALC5632_OUTPUT_MIXER_CTRL, 14, 4, alc5632_spk_n_sour_sel); +static SOC_ENUM_SINGLE_DECL(alc5632_spk_n_sour_enum, + ALC5632_OUTPUT_MIXER_CTRL, 14, + alc5632_spk_n_sour_sel); static const struct snd_kcontrol_new alc5632_spkoutn_mux_controls = SOC_DAPM_ENUM("SpeakerOut N Mux", alc5632_spk_n_sour_enum); /* speaker amplifier */ static const char *alc5632_amp_names[] = {"AB Amp", "D Amp"}; -static const struct soc_enum alc5632_amp_enum = - SOC_ENUM_SINGLE(ALC5632_OUTPUT_MIXER_CTRL, 13, 2, alc5632_amp_names); +static SOC_ENUM_SINGLE_DECL(alc5632_amp_enum, + ALC5632_OUTPUT_MIXER_CTRL, 13, + alc5632_amp_names); static const struct snd_kcontrol_new alc5632_amp_mux_controls = SOC_DAPM_ENUM("AB-D Amp Mux", alc5632_amp_enum); /* ADC output select */ -static const struct soc_enum alc5632_adcr_func_enum = - SOC_ENUM_SINGLE(ALC5632_DAC_FUNC_SELECT, 5, 2, alc5632_adcr_func_sel); +static SOC_ENUM_SINGLE_DECL(alc5632_adcr_func_enum, + ALC5632_DAC_FUNC_SELECT, 5, + alc5632_adcr_func_sel); static const struct snd_kcontrol_new alc5632_adcr_func_controls = SOC_DAPM_ENUM("ADCR Mux", alc5632_adcr_func_enum); /* I2S out select */ -static const struct soc_enum alc5632_i2s_out_enum = - SOC_ENUM_SINGLE(ALC5632_I2S_OUT_CTL, 5, 2, alc5632_i2s_out_sel); +static SOC_ENUM_SINGLE_DECL(alc5632_i2s_out_enum, + ALC5632_I2S_OUT_CTL, 5, + alc5632_i2s_out_sel); static const struct snd_kcontrol_new alc5632_i2s_out_controls = SOC_DAPM_ENUM("I2SOut Mux", alc5632_i2s_out_enum); @@ -1055,14 +1063,6 @@ static int alc5632_probe(struct snd_soc_codec *codec) struct alc5632_priv *alc5632 = snd_soc_codec_get_drvdata(codec); int ret; - codec->control_data = alc5632->regmap; - - ret = snd_soc_codec_set_cache_io(codec, 8, 16, SND_SOC_REGMAP); - if (ret != 0) { - dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); - return ret; - } - /* power on device */ alc5632_set_bias_level(codec, SND_SOC_BIAS_STANDBY); diff --git a/sound/soc/codecs/arizona.c b/sound/soc/codecs/arizona.c index e4295fee8f1..29e198f57d4 100644 --- a/sound/soc/codecs/arizona.c +++ b/sound/soc/codecs/arizona.c @@ -53,6 +53,14 @@ #define ARIZONA_AIF_RX_ENABLES 0x1A #define ARIZONA_AIF_FORCE_WRITE 0x1B +#define ARIZONA_FLL_VCO_CORNER 141900000 +#define ARIZONA_FLL_MAX_FREF 13500000 +#define ARIZONA_FLL_MIN_FVCO 90000000 +#define ARIZONA_FLL_MAX_FRATIO 16 +#define ARIZONA_FLL_MAX_REFDIV 8 +#define ARIZONA_FLL_MIN_OUTDIV 2 +#define ARIZONA_FLL_MAX_OUTDIV 7 + #define arizona_fll_err(_fll, fmt, ...) \ dev_err(_fll->arizona->dev, "FLL%d: " fmt, _fll->id, ##__VA_ARGS__) #define arizona_fll_warn(_fll, fmt, ...) \ @@ -542,67 +550,76 @@ static const char *arizona_vol_ramp_text[] = { "15ms/6dB", "30ms/6dB", }; -const struct soc_enum arizona_in_vd_ramp = - SOC_ENUM_SINGLE(ARIZONA_INPUT_VOLUME_RAMP, - ARIZONA_IN_VD_RAMP_SHIFT, 7, arizona_vol_ramp_text); +SOC_ENUM_SINGLE_DECL(arizona_in_vd_ramp, + ARIZONA_INPUT_VOLUME_RAMP, + ARIZONA_IN_VD_RAMP_SHIFT, + arizona_vol_ramp_text); EXPORT_SYMBOL_GPL(arizona_in_vd_ramp); -const struct soc_enum arizona_in_vi_ramp = - SOC_ENUM_SINGLE(ARIZONA_INPUT_VOLUME_RAMP, - ARIZONA_IN_VI_RAMP_SHIFT, 7, arizona_vol_ramp_text); +SOC_ENUM_SINGLE_DECL(arizona_in_vi_ramp, + ARIZONA_INPUT_VOLUME_RAMP, + ARIZONA_IN_VI_RAMP_SHIFT, + arizona_vol_ramp_text); EXPORT_SYMBOL_GPL(arizona_in_vi_ramp); -const struct soc_enum arizona_out_vd_ramp = - SOC_ENUM_SINGLE(ARIZONA_OUTPUT_VOLUME_RAMP, - ARIZONA_OUT_VD_RAMP_SHIFT, 7, arizona_vol_ramp_text); +SOC_ENUM_SINGLE_DECL(arizona_out_vd_ramp, + ARIZONA_OUTPUT_VOLUME_RAMP, + ARIZONA_OUT_VD_RAMP_SHIFT, + arizona_vol_ramp_text); EXPORT_SYMBOL_GPL(arizona_out_vd_ramp); -const struct soc_enum arizona_out_vi_ramp = - SOC_ENUM_SINGLE(ARIZONA_OUTPUT_VOLUME_RAMP, - ARIZONA_OUT_VI_RAMP_SHIFT, 7, arizona_vol_ramp_text); +SOC_ENUM_SINGLE_DECL(arizona_out_vi_ramp, + ARIZONA_OUTPUT_VOLUME_RAMP, + ARIZONA_OUT_VI_RAMP_SHIFT, + arizona_vol_ramp_text); EXPORT_SYMBOL_GPL(arizona_out_vi_ramp); static const char *arizona_lhpf_mode_text[] = { "Low-pass", "High-pass" }; -const struct soc_enum arizona_lhpf1_mode = - SOC_ENUM_SINGLE(ARIZONA_HPLPF1_1, ARIZONA_LHPF1_MODE_SHIFT, 2, - arizona_lhpf_mode_text); +SOC_ENUM_SINGLE_DECL(arizona_lhpf1_mode, + ARIZONA_HPLPF1_1, + ARIZONA_LHPF1_MODE_SHIFT, + arizona_lhpf_mode_text); EXPORT_SYMBOL_GPL(arizona_lhpf1_mode); -const struct soc_enum arizona_lhpf2_mode = - SOC_ENUM_SINGLE(ARIZONA_HPLPF2_1, ARIZONA_LHPF2_MODE_SHIFT, 2, - arizona_lhpf_mode_text); +SOC_ENUM_SINGLE_DECL(arizona_lhpf2_mode, + ARIZONA_HPLPF2_1, + ARIZONA_LHPF2_MODE_SHIFT, + arizona_lhpf_mode_text); EXPORT_SYMBOL_GPL(arizona_lhpf2_mode); -const struct soc_enum arizona_lhpf3_mode = - SOC_ENUM_SINGLE(ARIZONA_HPLPF3_1, ARIZONA_LHPF3_MODE_SHIFT, 2, - arizona_lhpf_mode_text); +SOC_ENUM_SINGLE_DECL(arizona_lhpf3_mode, + ARIZONA_HPLPF3_1, + ARIZONA_LHPF3_MODE_SHIFT, + arizona_lhpf_mode_text); EXPORT_SYMBOL_GPL(arizona_lhpf3_mode); -const struct soc_enum arizona_lhpf4_mode = - SOC_ENUM_SINGLE(ARIZONA_HPLPF4_1, ARIZONA_LHPF4_MODE_SHIFT, 2, - arizona_lhpf_mode_text); +SOC_ENUM_SINGLE_DECL(arizona_lhpf4_mode, + ARIZONA_HPLPF4_1, + ARIZONA_LHPF4_MODE_SHIFT, + arizona_lhpf_mode_text); EXPORT_SYMBOL_GPL(arizona_lhpf4_mode); static const char *arizona_ng_hold_text[] = { "30ms", "120ms", "250ms", "500ms", }; -const struct soc_enum arizona_ng_hold = - SOC_ENUM_SINGLE(ARIZONA_NOISE_GATE_CONTROL, ARIZONA_NGATE_HOLD_SHIFT, - 4, arizona_ng_hold_text); +SOC_ENUM_SINGLE_DECL(arizona_ng_hold, + ARIZONA_NOISE_GATE_CONTROL, + ARIZONA_NGATE_HOLD_SHIFT, + arizona_ng_hold_text); EXPORT_SYMBOL_GPL(arizona_ng_hold); static const char * const arizona_in_hpf_cut_text[] = { "2.5Hz", "5Hz", "10Hz", "20Hz", "40Hz" }; -const struct soc_enum arizona_in_hpf_cut_enum = - SOC_ENUM_SINGLE(ARIZONA_HPF_CONTROL, ARIZONA_IN_HPF_CUT_SHIFT, - ARRAY_SIZE(arizona_in_hpf_cut_text), - arizona_in_hpf_cut_text); +SOC_ENUM_SINGLE_DECL(arizona_in_hpf_cut_enum, + ARIZONA_HPF_CONTROL, + ARIZONA_IN_HPF_CUT_SHIFT, + arizona_in_hpf_cut_text); EXPORT_SYMBOL_GPL(arizona_in_hpf_cut_enum); static const char * const arizona_in_dmic_osr_text[] = { @@ -1377,74 +1394,147 @@ struct arizona_fll_cfg { int gain; }; -static int arizona_calc_fll(struct arizona_fll *fll, - struct arizona_fll_cfg *cfg, - unsigned int Fref, - unsigned int Fout) +static int arizona_validate_fll(struct arizona_fll *fll, + unsigned int Fref, + unsigned int Fout) { - unsigned int target, div, gcd_fll; - int i, ratio; + unsigned int Fvco_min; + + if (Fref / ARIZONA_FLL_MAX_REFDIV > ARIZONA_FLL_MAX_FREF) { + arizona_fll_err(fll, + "Can't scale %dMHz in to <=13.5MHz\n", + Fref); + return -EINVAL; + } - arizona_fll_dbg(fll, "Fref=%u Fout=%u\n", Fref, Fout); + Fvco_min = ARIZONA_FLL_MIN_FVCO * fll->vco_mult; + if (Fout * ARIZONA_FLL_MAX_OUTDIV < Fvco_min) { + arizona_fll_err(fll, "No FLL_OUTDIV for Fout=%uHz\n", + Fout); + return -EINVAL; + } + + return 0; +} + +static int arizona_find_fratio(unsigned int Fref, int *fratio) +{ + int i; + + /* Find an appropriate FLL_FRATIO */ + for (i = 0; i < ARRAY_SIZE(fll_fratios); i++) { + if (fll_fratios[i].min <= Fref && Fref <= fll_fratios[i].max) { + if (fratio) + *fratio = fll_fratios[i].fratio; + return fll_fratios[i].ratio; + } + } + + return -EINVAL; +} + +static int arizona_calc_fratio(struct arizona_fll *fll, + struct arizona_fll_cfg *cfg, + unsigned int target, + unsigned int Fref, bool sync) +{ + int init_ratio, ratio; + int refdiv, div; - /* Fref must be <=13.5MHz */ + /* Fref must be <=13.5MHz, find initial refdiv */ div = 1; cfg->refdiv = 0; - while ((Fref / div) > 13500000) { + while (Fref > ARIZONA_FLL_MAX_FREF) { div *= 2; + Fref /= 2; cfg->refdiv++; - if (div > 8) { - arizona_fll_err(fll, - "Can't scale %dMHz in to <=13.5MHz\n", - Fref); + if (div > ARIZONA_FLL_MAX_REFDIV) return -EINVAL; + } + + /* Find an appropriate FLL_FRATIO */ + init_ratio = arizona_find_fratio(Fref, &cfg->fratio); + if (init_ratio < 0) { + arizona_fll_err(fll, "Unable to find FRATIO for Fref=%uHz\n", + Fref); + return init_ratio; + } + + switch (fll->arizona->type) { + case WM5110: + if (fll->arizona->rev < 3 || sync) + return init_ratio; + break; + default: + return init_ratio; + } + + cfg->fratio = init_ratio - 1; + + /* Adjust FRATIO/refdiv to avoid integer mode if possible */ + refdiv = cfg->refdiv; + + while (div <= ARIZONA_FLL_MAX_REFDIV) { + for (ratio = init_ratio; ratio <= ARIZONA_FLL_MAX_FRATIO; + ratio++) { + if (target % (ratio * Fref)) { + cfg->refdiv = refdiv; + cfg->fratio = ratio - 1; + return ratio; + } } + + for (ratio = init_ratio - 1; ratio >= 0; ratio--) { + if (ARIZONA_FLL_VCO_CORNER / (fll->vco_mult * ratio) < + Fref) + break; + + if (target % (ratio * Fref)) { + cfg->refdiv = refdiv; + cfg->fratio = ratio - 1; + return ratio; + } + } + + div *= 2; + Fref /= 2; + refdiv++; + init_ratio = arizona_find_fratio(Fref, NULL); } - /* Apply the division for our remaining calculations */ - Fref /= div; + arizona_fll_warn(fll, "Falling back to integer mode operation\n"); + return cfg->fratio + 1; +} + +static int arizona_calc_fll(struct arizona_fll *fll, + struct arizona_fll_cfg *cfg, + unsigned int Fref, bool sync) +{ + unsigned int target, div, gcd_fll; + int i, ratio; + + arizona_fll_dbg(fll, "Fref=%u Fout=%u\n", Fref, fll->fout); /* Fvco should be over the targt; don't check the upper bound */ - div = 1; - while (Fout * div < 90000000 * fll->vco_mult) { + div = ARIZONA_FLL_MIN_OUTDIV; + while (fll->fout * div < ARIZONA_FLL_MIN_FVCO * fll->vco_mult) { div++; - if (div > 7) { - arizona_fll_err(fll, "No FLL_OUTDIV for Fout=%uHz\n", - Fout); + if (div > ARIZONA_FLL_MAX_OUTDIV) return -EINVAL; - } } - target = Fout * div / fll->vco_mult; + target = fll->fout * div / fll->vco_mult; cfg->outdiv = div; arizona_fll_dbg(fll, "Fvco=%dHz\n", target); - /* Find an appropraite FLL_FRATIO and factor it out of the target */ - for (i = 0; i < ARRAY_SIZE(fll_fratios); i++) { - if (fll_fratios[i].min <= Fref && Fref <= fll_fratios[i].max) { - cfg->fratio = fll_fratios[i].fratio; - ratio = fll_fratios[i].ratio; - break; - } - } - if (i == ARRAY_SIZE(fll_fratios)) { - arizona_fll_err(fll, "Unable to find FRATIO for Fref=%uHz\n", - Fref); - return -EINVAL; - } + /* Find an appropriate FLL_FRATIO and refdiv */ + ratio = arizona_calc_fratio(fll, cfg, target, Fref, sync); + if (ratio < 0) + return ratio; - for (i = 0; i < ARRAY_SIZE(fll_gains); i++) { - if (fll_gains[i].min <= Fref && Fref <= fll_gains[i].max) { - cfg->gain = fll_gains[i].gain; - break; - } - } - if (i == ARRAY_SIZE(fll_gains)) { - arizona_fll_err(fll, "Unable to find gain for Fref=%uHz\n", - Fref); - return -EINVAL; - } + /* Apply the division for our remaining calculations */ + Fref = Fref / (1 << cfg->refdiv); cfg->n = target / (ratio * Fref); @@ -1469,6 +1559,18 @@ static int arizona_calc_fll(struct arizona_fll *fll, cfg->lambda >>= 1; } + for (i = 0; i < ARRAY_SIZE(fll_gains); i++) { + if (fll_gains[i].min <= Fref && Fref <= fll_gains[i].max) { + cfg->gain = fll_gains[i].gain; + break; + } + } + if (i == ARRAY_SIZE(fll_gains)) { + arizona_fll_err(fll, "Unable to find gain for Fref=%uHz\n", + Fref); + return -EINVAL; + } + arizona_fll_dbg(fll, "N=%x THETA=%x LAMBDA=%x\n", cfg->n, cfg->theta, cfg->lambda); arizona_fll_dbg(fll, "FRATIO=%x(%d) OUTDIV=%x REFCLK_DIV=%x\n", @@ -1496,14 +1598,18 @@ static void arizona_apply_fll(struct arizona *arizona, unsigned int base, cfg->refdiv << ARIZONA_FLL1_CLK_REF_DIV_SHIFT | source << ARIZONA_FLL1_CLK_REF_SRC_SHIFT); - if (sync) - regmap_update_bits_async(arizona->regmap, base + 0x7, - ARIZONA_FLL1_GAIN_MASK, - cfg->gain << ARIZONA_FLL1_GAIN_SHIFT); - else - regmap_update_bits_async(arizona->regmap, base + 0x9, - ARIZONA_FLL1_GAIN_MASK, - cfg->gain << ARIZONA_FLL1_GAIN_SHIFT); + if (sync) { + regmap_update_bits(arizona->regmap, base + 0x7, + ARIZONA_FLL1_GAIN_MASK, + cfg->gain << ARIZONA_FLL1_GAIN_SHIFT); + } else { + regmap_update_bits(arizona->regmap, base + 0x5, + ARIZONA_FLL1_OUTDIV_MASK, + cfg->outdiv << ARIZONA_FLL1_OUTDIV_SHIFT); + regmap_update_bits(arizona->regmap, base + 0x9, + ARIZONA_FLL1_GAIN_MASK, + cfg->gain << ARIZONA_FLL1_GAIN_SHIFT); + } regmap_update_bits_async(arizona->regmap, base + 2, ARIZONA_FLL1_CTRL_UPD | ARIZONA_FLL1_N_MASK, @@ -1526,13 +1632,12 @@ static bool arizona_is_enabled_fll(struct arizona_fll *fll) return reg & ARIZONA_FLL1_ENA; } -static void arizona_enable_fll(struct arizona_fll *fll, - struct arizona_fll_cfg *ref, - struct arizona_fll_cfg *sync) +static void arizona_enable_fll(struct arizona_fll *fll) { struct arizona *arizona = fll->arizona; int ret; bool use_sync = false; + struct arizona_fll_cfg cfg; /* * If we have both REFCLK and SYNCCLK then enable both, @@ -1540,23 +1645,21 @@ static void arizona_enable_fll(struct arizona_fll *fll, */ if (fll->ref_src >= 0 && fll->ref_freq && fll->ref_src != fll->sync_src) { - regmap_update_bits_async(arizona->regmap, fll->base + 5, - ARIZONA_FLL1_OUTDIV_MASK, - ref->outdiv << ARIZONA_FLL1_OUTDIV_SHIFT); + arizona_calc_fll(fll, &cfg, fll->ref_freq, false); - arizona_apply_fll(arizona, fll->base, ref, fll->ref_src, + arizona_apply_fll(arizona, fll->base, &cfg, fll->ref_src, false); if (fll->sync_src >= 0) { - arizona_apply_fll(arizona, fll->base + 0x10, sync, + arizona_calc_fll(fll, &cfg, fll->sync_freq, true); + + arizona_apply_fll(arizona, fll->base + 0x10, &cfg, fll->sync_src, true); use_sync = true; } } else if (fll->sync_src >= 0) { - regmap_update_bits_async(arizona->regmap, fll->base + 5, - ARIZONA_FLL1_OUTDIV_MASK, - sync->outdiv << ARIZONA_FLL1_OUTDIV_SHIFT); + arizona_calc_fll(fll, &cfg, fll->sync_freq, false); - arizona_apply_fll(arizona, fll->base, sync, + arizona_apply_fll(arizona, fll->base, &cfg, fll->sync_src, false); regmap_update_bits_async(arizona->regmap, fll->base + 0x11, @@ -1618,32 +1721,22 @@ static void arizona_disable_fll(struct arizona_fll *fll) int arizona_set_fll_refclk(struct arizona_fll *fll, int source, unsigned int Fref, unsigned int Fout) { - struct arizona_fll_cfg ref, sync; int ret; if (fll->ref_src == source && fll->ref_freq == Fref) return 0; - if (fll->fout) { - if (Fref > 0) { - ret = arizona_calc_fll(fll, &ref, Fref, fll->fout); - if (ret != 0) - return ret; - } - - if (fll->sync_src >= 0) { - ret = arizona_calc_fll(fll, &sync, fll->sync_freq, - fll->fout); - if (ret != 0) - return ret; - } + if (fll->fout && Fref > 0) { + ret = arizona_validate_fll(fll, Fref, fll->fout); + if (ret != 0) + return ret; } fll->ref_src = source; fll->ref_freq = Fref; if (fll->fout && Fref > 0) { - arizona_enable_fll(fll, &ref, &sync); + arizona_enable_fll(fll); } return 0; @@ -1653,7 +1746,6 @@ EXPORT_SYMBOL_GPL(arizona_set_fll_refclk); int arizona_set_fll(struct arizona_fll *fll, int source, unsigned int Fref, unsigned int Fout) { - struct arizona_fll_cfg ref, sync; int ret; if (fll->sync_src == source && @@ -1662,13 +1754,12 @@ int arizona_set_fll(struct arizona_fll *fll, int source, if (Fout) { if (fll->ref_src >= 0) { - ret = arizona_calc_fll(fll, &ref, fll->ref_freq, - Fout); + ret = arizona_validate_fll(fll, fll->ref_freq, Fout); if (ret != 0) return ret; } - ret = arizona_calc_fll(fll, &sync, Fref, Fout); + ret = arizona_validate_fll(fll, Fref, Fout); if (ret != 0) return ret; } @@ -1678,7 +1769,7 @@ int arizona_set_fll(struct arizona_fll *fll, int source, fll->fout = Fout; if (Fout) { - arizona_enable_fll(fll, &ref, &sync); + arizona_enable_fll(fll); } else { arizona_disable_fll(fll); } diff --git a/sound/soc/codecs/cq93vc.c b/sound/soc/codecs/cq93vc.c index 43737a27d79..1e25c7af853 100644 --- a/sound/soc/codecs/cq93vc.c +++ b/sound/soc/codecs/cq93vc.c @@ -138,9 +138,8 @@ static int cq93vc_probe(struct snd_soc_codec *codec) struct davinci_vc *davinci_vc = codec->dev->platform_data; davinci_vc->cq93vc.codec = codec; - codec->control_data = davinci_vc->regmap; - snd_soc_codec_set_cache_io(codec, 32, 32, SND_SOC_REGMAP); + snd_soc_codec_set_cache_io(codec, davinci_vc->regmap); /* Off, with power on */ cq93vc_set_bias_level(codec, SND_SOC_BIAS_STANDBY); diff --git a/sound/soc/codecs/cs4270.c b/sound/soc/codecs/cs4270.c index 83c835d9fd8..3920e626494 100644 --- a/sound/soc/codecs/cs4270.c +++ b/sound/soc/codecs/cs4270.c @@ -506,15 +506,6 @@ static int cs4270_probe(struct snd_soc_codec *codec) struct cs4270_private *cs4270 = snd_soc_codec_get_drvdata(codec); int ret; - /* Tell ASoC what kind of I/O to use to read the registers. ASoC will - * then do the I2C transactions itself. - */ - ret = snd_soc_codec_set_cache_io(codec, 8, 8, SND_SOC_REGMAP); - if (ret < 0) { - dev_err(codec->dev, "failed to set cache I/O (ret=%i)\n", ret); - return ret; - } - /* Disable auto-mute. This feature appears to be buggy. In some * situations, auto-mute will not deactivate when it should, so we want * this feature disabled by default. An application (e.g. alsactl) can diff --git a/sound/soc/codecs/cs4271.c b/sound/soc/codecs/cs4271.c index ce05fd93dc7..aef4965750c 100644 --- a/sound/soc/codecs/cs4271.c +++ b/sound/soc/codecs/cs4271.c @@ -159,7 +159,6 @@ static bool cs4271_volatile_reg(struct device *dev, unsigned int reg) } struct cs4271_private { - /* SND_SOC_I2C or SND_SOC_SPI */ unsigned int mclk; bool master; bool deemph; @@ -540,14 +539,10 @@ static int cs4271_probe(struct snd_soc_codec *codec) struct cs4271_private *cs4271 = snd_soc_codec_get_drvdata(codec); struct cs4271_platform_data *cs4271plat = codec->dev->platform_data; int ret; - int gpio_nreset = -EINVAL; bool amutec_eq_bmutec = false; #ifdef CONFIG_OF if (of_match_device(cs4271_dt_ids, codec->dev)) { - gpio_nreset = of_get_named_gpio(codec->dev->of_node, - "reset-gpio", 0); - if (of_get_property(codec->dev->of_node, "cirrus,amutec-eq-bmutec", NULL)) amutec_eq_bmutec = true; @@ -559,27 +554,19 @@ static int cs4271_probe(struct snd_soc_codec *codec) #endif if (cs4271plat) { - if (gpio_is_valid(cs4271plat->gpio_nreset)) - gpio_nreset = cs4271plat->gpio_nreset; - amutec_eq_bmutec = cs4271plat->amutec_eq_bmutec; cs4271->enable_soft_reset = cs4271plat->enable_soft_reset; } - if (gpio_nreset >= 0) - if (devm_gpio_request(codec->dev, gpio_nreset, "CS4271 Reset")) - gpio_nreset = -EINVAL; - if (gpio_nreset >= 0) { + if (gpio_is_valid(cs4271->gpio_nreset)) { /* Reset codec */ - gpio_direction_output(gpio_nreset, 0); + gpio_direction_output(cs4271->gpio_nreset, 0); udelay(1); - gpio_set_value(gpio_nreset, 1); + gpio_set_value(cs4271->gpio_nreset, 1); /* Give the codec time to wake up */ udelay(1); } - cs4271->gpio_nreset = gpio_nreset; - ret = regmap_update_bits(cs4271->regmap, CS4271_MODE2, CS4271_MODE2_PDN | CS4271_MODE2_CPEN, CS4271_MODE2_PDN | CS4271_MODE2_CPEN); @@ -625,6 +612,36 @@ static struct snd_soc_codec_driver soc_codec_dev_cs4271 = { .num_dapm_routes = ARRAY_SIZE(cs4271_dapm_routes), }; +static int cs4271_common_probe(struct device *dev, + struct cs4271_private **c) +{ + struct cs4271_platform_data *cs4271plat = dev->platform_data; + struct cs4271_private *cs4271; + + cs4271 = devm_kzalloc(dev, sizeof(*cs4271), GFP_KERNEL); + if (!cs4271) + return -ENOMEM; + + if (of_match_device(cs4271_dt_ids, dev)) + cs4271->gpio_nreset = + of_get_named_gpio(dev->of_node, "reset-gpio", 0); + + if (cs4271plat) + cs4271->gpio_nreset = cs4271plat->gpio_nreset; + + if (gpio_is_valid(cs4271->gpio_nreset)) { + int ret; + + ret = devm_gpio_request(dev, cs4271->gpio_nreset, + "CS4271 Reset"); + if (ret < 0) + return ret; + } + + *c = cs4271; + return 0; +} + #if defined(CONFIG_SPI_MASTER) static const struct regmap_config cs4271_spi_regmap = { @@ -644,10 +661,11 @@ static const struct regmap_config cs4271_spi_regmap = { static int cs4271_spi_probe(struct spi_device *spi) { struct cs4271_private *cs4271; + int ret; - cs4271 = devm_kzalloc(&spi->dev, sizeof(*cs4271), GFP_KERNEL); - if (!cs4271) - return -ENOMEM; + ret = cs4271_common_probe(&spi->dev, &cs4271); + if (ret < 0) + return ret; spi_set_drvdata(spi, cs4271); cs4271->regmap = devm_regmap_init_spi(spi, &cs4271_spi_regmap); @@ -698,10 +716,11 @@ static int cs4271_i2c_probe(struct i2c_client *client, const struct i2c_device_id *id) { struct cs4271_private *cs4271; + int ret; - cs4271 = devm_kzalloc(&client->dev, sizeof(*cs4271), GFP_KERNEL); - if (!cs4271) - return -ENOMEM; + ret = cs4271_common_probe(&client->dev, &cs4271); + if (ret < 0) + return ret; i2c_set_clientdata(client, cs4271); cs4271->regmap = devm_regmap_init_i2c(client, &cs4271_i2c_regmap); diff --git a/sound/soc/codecs/cs42l51.c b/sound/soc/codecs/cs42l51.c index 6e9ea8379a9..6c0da2baa15 100644 --- a/sound/soc/codecs/cs42l51.c +++ b/sound/soc/codecs/cs42l51.c @@ -30,6 +30,7 @@ #include <sound/pcm_params.h> #include <sound/pcm.h> #include <linux/i2c.h> +#include <linux/regmap.h> #include "cs42l51.h" @@ -40,7 +41,6 @@ enum master_slave_mode { }; struct cs42l51_private { - enum snd_soc_control_type control_type; unsigned int mclk; unsigned int audio_mode; /* The mode (I2S or left-justified) */ enum master_slave_mode func; @@ -52,24 +52,6 @@ struct cs42l51_private { SNDRV_PCM_FMTBIT_S20_3LE | SNDRV_PCM_FMTBIT_S20_3BE | \ SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S24_BE) -static int cs42l51_fill_cache(struct snd_soc_codec *codec) -{ - u8 *cache = codec->reg_cache + 1; - struct i2c_client *i2c_client = to_i2c_client(codec->dev); - s32 length; - - length = i2c_smbus_read_i2c_block_data(i2c_client, - CS42L51_FIRSTREG | 0x80, CS42L51_NUMREGS, cache); - if (length != CS42L51_NUMREGS) { - dev_err(&i2c_client->dev, - "I2C read failure, addr=0x%x (ret=%d vs %d)\n", - i2c_client->addr, length, CS42L51_NUMREGS); - return -EIO; - } - - return 0; -} - static int cs42l51_get_chan_mix(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { @@ -124,9 +106,8 @@ static int cs42l51_set_chan_mix(struct snd_kcontrol *kcontrol, static const DECLARE_TLV_DB_SCALE(adc_pcm_tlv, -5150, 50, 0); static const DECLARE_TLV_DB_SCALE(tone_tlv, -1050, 150, 0); -/* This is a lie. after -102 db, it stays at -102 */ -/* maybe a range would be better */ -static const DECLARE_TLV_DB_SCALE(aout_tlv, -11550, 50, 0); + +static const DECLARE_TLV_DB_SCALE(aout_tlv, -10200, 50, 0); static const DECLARE_TLV_DB_SCALE(boost_tlv, 1600, 1600, 0); static const char *chan_mix[] = { @@ -135,13 +116,12 @@ static const char *chan_mix[] = { "R L", }; -static const struct soc_enum cs42l51_chan_mix = - SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(chan_mix), chan_mix); +static SOC_ENUM_SINGLE_EXT_DECL(cs42l51_chan_mix, chan_mix); static const struct snd_kcontrol_new cs42l51_snd_controls[] = { SOC_DOUBLE_R_SX_TLV("PCM Playback Volume", CS42L51_PCMA_VOL, CS42L51_PCMB_VOL, - 6, 0x19, 0x7F, adc_pcm_tlv), + 0, 0x19, 0x7F, adc_pcm_tlv), SOC_DOUBLE_R("PCM Playback Switch", CS42L51_PCMA_VOL, CS42L51_PCMB_VOL, 7, 1, 1), SOC_DOUBLE_R_SX_TLV("Analog Playback Volume", @@ -149,7 +129,7 @@ static const struct snd_kcontrol_new cs42l51_snd_controls[] = { 0, 0x34, 0xE4, aout_tlv), SOC_DOUBLE_R_SX_TLV("ADC Mixer Volume", CS42L51_ADCA_VOL, CS42L51_ADCB_VOL, - 6, 0x19, 0x7F, adc_pcm_tlv), + 0, 0x19, 0x7F, adc_pcm_tlv), SOC_DOUBLE_R("ADC Mixer Switch", CS42L51_ADCA_VOL, CS42L51_ADCB_VOL, 7, 1, 1), SOC_SINGLE("Playback Deemphasis Switch", CS42L51_DAC_CTL, 3, 1, 0), @@ -192,22 +172,22 @@ static int cs42l51_pdn_event(struct snd_soc_dapm_widget *w, static const char *cs42l51_dac_names[] = {"Direct PCM", "DSP PCM", "ADC"}; -static const struct soc_enum cs42l51_dac_mux_enum = - SOC_ENUM_SINGLE(CS42L51_DAC_CTL, 6, 3, cs42l51_dac_names); +static SOC_ENUM_SINGLE_DECL(cs42l51_dac_mux_enum, + CS42L51_DAC_CTL, 6, cs42l51_dac_names); static const struct snd_kcontrol_new cs42l51_dac_mux_controls = SOC_DAPM_ENUM("Route", cs42l51_dac_mux_enum); static const char *cs42l51_adcl_names[] = {"AIN1 Left", "AIN2 Left", "MIC Left", "MIC+preamp Left"}; -static const struct soc_enum cs42l51_adcl_mux_enum = - SOC_ENUM_SINGLE(CS42L51_ADC_INPUT, 4, 4, cs42l51_adcl_names); +static SOC_ENUM_SINGLE_DECL(cs42l51_adcl_mux_enum, + CS42L51_ADC_INPUT, 4, cs42l51_adcl_names); static const struct snd_kcontrol_new cs42l51_adcl_mux_controls = SOC_DAPM_ENUM("Route", cs42l51_adcl_mux_enum); static const char *cs42l51_adcr_names[] = {"AIN1 Right", "AIN2 Right", "MIC Right", "MIC+preamp Right"}; -static const struct soc_enum cs42l51_adcr_mux_enum = - SOC_ENUM_SINGLE(CS42L51_ADC_INPUT, 6, 4, cs42l51_adcr_names); +static SOC_ENUM_SINGLE_DECL(cs42l51_adcr_mux_enum, + CS42L51_ADC_INPUT, 6, cs42l51_adcr_names); static const struct snd_kcontrol_new cs42l51_adcr_mux_controls = SOC_DAPM_ENUM("Route", cs42l51_adcr_mux_enum); @@ -505,21 +485,8 @@ static struct snd_soc_dai_driver cs42l51_dai = { static int cs42l51_probe(struct snd_soc_codec *codec) { - struct cs42l51_private *cs42l51 = snd_soc_codec_get_drvdata(codec); int ret, reg; - ret = cs42l51_fill_cache(codec); - if (ret < 0) { - dev_err(codec->dev, "failed to fill register cache\n"); - return ret; - } - - ret = snd_soc_codec_set_cache_io(codec, 8, 8, cs42l51->control_type); - if (ret < 0) { - dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); - return ret; - } - /* * DAC configuration * - Use signal processor @@ -538,8 +505,6 @@ static int cs42l51_probe(struct snd_soc_codec *codec) static struct snd_soc_codec_driver soc_codec_device_cs42l51 = { .probe = cs42l51_probe, - .reg_cache_size = CS42L51_NUMREGS + 1, - .reg_word_size = sizeof(u8), .controls = cs42l51_snd_controls, .num_controls = ARRAY_SIZE(cs42l51_snd_controls), @@ -549,38 +514,53 @@ static struct snd_soc_codec_driver soc_codec_device_cs42l51 = { .num_dapm_routes = ARRAY_SIZE(cs42l51_routes), }; +static const struct regmap_config cs42l51_regmap = { + .reg_bits = 8, + .val_bits = 8, + + .max_register = CS42L51_CHARGE_FREQ, + .cache_type = REGCACHE_RBTREE, +}; + static int cs42l51_i2c_probe(struct i2c_client *i2c_client, const struct i2c_device_id *id) { struct cs42l51_private *cs42l51; + struct regmap *regmap; + unsigned int val; int ret; + regmap = devm_regmap_init_i2c(i2c_client, &cs42l51_regmap); + if (IS_ERR(regmap)) { + ret = PTR_ERR(regmap); + dev_err(&i2c_client->dev, "Failed to create regmap: %d\n", + ret); + return ret; + } + /* Verify that we have a CS42L51 */ - ret = i2c_smbus_read_byte_data(i2c_client, CS42L51_CHIP_REV_ID); + ret = regmap_read(regmap, CS42L51_CHIP_REV_ID, &val); if (ret < 0) { dev_err(&i2c_client->dev, "failed to read I2C\n"); goto error; } - if ((ret != CS42L51_MK_CHIP_REV(CS42L51_CHIP_ID, CS42L51_CHIP_REV_A)) && - (ret != CS42L51_MK_CHIP_REV(CS42L51_CHIP_ID, CS42L51_CHIP_REV_B))) { - dev_err(&i2c_client->dev, "Invalid chip id\n"); + if ((val != CS42L51_MK_CHIP_REV(CS42L51_CHIP_ID, CS42L51_CHIP_REV_A)) && + (val != CS42L51_MK_CHIP_REV(CS42L51_CHIP_ID, CS42L51_CHIP_REV_B))) { + dev_err(&i2c_client->dev, "Invalid chip id: %x\n", val); ret = -ENODEV; goto error; } dev_info(&i2c_client->dev, "found device cs42l51 rev %d\n", - ret & 7); + val & 7); cs42l51 = devm_kzalloc(&i2c_client->dev, sizeof(struct cs42l51_private), GFP_KERNEL); - if (!cs42l51) { - dev_err(&i2c_client->dev, "could not allocate codec\n"); + if (!cs42l51) return -ENOMEM; - } i2c_set_clientdata(i2c_client, cs42l51); - cs42l51->control_type = SND_SOC_I2C; ret = snd_soc_register_codec(&i2c_client->dev, &soc_codec_device_cs42l51, &cs42l51_dai, 1); @@ -600,10 +580,17 @@ static const struct i2c_device_id cs42l51_id[] = { }; MODULE_DEVICE_TABLE(i2c, cs42l51_id); +static const struct of_device_id cs42l51_of_match[] = { + { .compatible = "cirrus,cs42l51", }, + { } +}; +MODULE_DEVICE_TABLE(of, cs42l51_of_match); + static struct i2c_driver cs42l51_i2c_driver = { .driver = { .name = "cs42l51-codec", .owner = THIS_MODULE, + .of_match_table = cs42l51_of_match, }, .id_table = cs42l51_id, .probe = cs42l51_i2c_probe, diff --git a/sound/soc/codecs/cs42l52.c b/sound/soc/codecs/cs42l52.c index 0bac6d5a4ac..f0ca6bee677 100644 --- a/sound/soc/codecs/cs42l52.c +++ b/sound/soc/codecs/cs42l52.c @@ -210,13 +210,11 @@ static const char * const cs42l52_adca_text[] = { static const char * const cs42l52_adcb_text[] = { "Input1B", "Input2B", "Input3B", "Input4B", "PGA Input Right"}; -static const struct soc_enum adca_enum = - SOC_ENUM_SINGLE(CS42L52_ADC_PGA_A, 5, - ARRAY_SIZE(cs42l52_adca_text), cs42l52_adca_text); +static SOC_ENUM_SINGLE_DECL(adca_enum, + CS42L52_ADC_PGA_A, 5, cs42l52_adca_text); -static const struct soc_enum adcb_enum = - SOC_ENUM_SINGLE(CS42L52_ADC_PGA_B, 5, - ARRAY_SIZE(cs42l52_adcb_text), cs42l52_adcb_text); +static SOC_ENUM_SINGLE_DECL(adcb_enum, + CS42L52_ADC_PGA_B, 5, cs42l52_adcb_text); static const struct snd_kcontrol_new adca_mux = SOC_DAPM_ENUM("Left ADC Input Capture Mux", adca_enum); @@ -229,26 +227,22 @@ static const char * const mic_bias_level_text[] = { "0.8 +VA", "0.83 +VA", "0.91 +VA" }; -static const struct soc_enum mic_bias_level_enum = - SOC_ENUM_SINGLE(CS42L52_IFACE_CTL2, 0, - ARRAY_SIZE(mic_bias_level_text), mic_bias_level_text); +static SOC_ENUM_SINGLE_DECL(mic_bias_level_enum, + CS42L52_IFACE_CTL2, 0, mic_bias_level_text); static const char * const cs42l52_mic_text[] = { "MIC1", "MIC2" }; -static const struct soc_enum mica_enum = - SOC_ENUM_SINGLE(CS42L52_MICA_CTL, 5, - ARRAY_SIZE(cs42l52_mic_text), cs42l52_mic_text); +static SOC_ENUM_SINGLE_DECL(mica_enum, + CS42L52_MICA_CTL, 5, cs42l52_mic_text); -static const struct soc_enum micb_enum = - SOC_ENUM_SINGLE(CS42L52_MICB_CTL, 5, - ARRAY_SIZE(cs42l52_mic_text), cs42l52_mic_text); +static SOC_ENUM_SINGLE_DECL(micb_enum, + CS42L52_MICB_CTL, 5, cs42l52_mic_text); static const char * const digital_output_mux_text[] = {"ADC", "DSP"}; -static const struct soc_enum digital_output_mux_enum = - SOC_ENUM_SINGLE(CS42L52_ADC_MISC_CTL, 6, - ARRAY_SIZE(digital_output_mux_text), - digital_output_mux_text); +static SOC_ENUM_SINGLE_DECL(digital_output_mux_enum, + CS42L52_ADC_MISC_CTL, 6, + digital_output_mux_text); static const struct snd_kcontrol_new digital_output_mux = SOC_DAPM_ENUM("Digital Output Mux", digital_output_mux_enum); @@ -258,18 +252,18 @@ static const char * const hp_gain_num_text[] = { "0.7099", "0.8399", "1.000", "1.1430" }; -static const struct soc_enum hp_gain_enum = - SOC_ENUM_SINGLE(CS42L52_PB_CTL1, 5, - ARRAY_SIZE(hp_gain_num_text), hp_gain_num_text); +static SOC_ENUM_SINGLE_DECL(hp_gain_enum, + CS42L52_PB_CTL1, 5, + hp_gain_num_text); static const char * const beep_pitch_text[] = { "C4", "C5", "D5", "E5", "F5", "G5", "A5", "B5", "C6", "D6", "E6", "F6", "G6", "A6", "B6", "C7" }; -static const struct soc_enum beep_pitch_enum = - SOC_ENUM_SINGLE(CS42L52_BEEP_FREQ, 4, - ARRAY_SIZE(beep_pitch_text), beep_pitch_text); +static SOC_ENUM_SINGLE_DECL(beep_pitch_enum, + CS42L52_BEEP_FREQ, 4, + beep_pitch_text); static const char * const beep_ontime_text[] = { "86 ms", "430 ms", "780 ms", "1.20 s", "1.50 s", @@ -277,66 +271,66 @@ static const char * const beep_ontime_text[] = { "3.50 s", "3.80 s", "4.20 s", "4.50 s", "4.80 s", "5.20 s" }; -static const struct soc_enum beep_ontime_enum = - SOC_ENUM_SINGLE(CS42L52_BEEP_FREQ, 0, - ARRAY_SIZE(beep_ontime_text), beep_ontime_text); +static SOC_ENUM_SINGLE_DECL(beep_ontime_enum, + CS42L52_BEEP_FREQ, 0, + beep_ontime_text); static const char * const beep_offtime_text[] = { "1.23 s", "2.58 s", "3.90 s", "5.20 s", "6.60 s", "8.05 s", "9.35 s", "10.80 s" }; -static const struct soc_enum beep_offtime_enum = - SOC_ENUM_SINGLE(CS42L52_BEEP_VOL, 5, - ARRAY_SIZE(beep_offtime_text), beep_offtime_text); +static SOC_ENUM_SINGLE_DECL(beep_offtime_enum, + CS42L52_BEEP_VOL, 5, + beep_offtime_text); static const char * const beep_config_text[] = { "Off", "Single", "Multiple", "Continuous" }; -static const struct soc_enum beep_config_enum = - SOC_ENUM_SINGLE(CS42L52_BEEP_TONE_CTL, 6, - ARRAY_SIZE(beep_config_text), beep_config_text); +static SOC_ENUM_SINGLE_DECL(beep_config_enum, + CS42L52_BEEP_TONE_CTL, 6, + beep_config_text); static const char * const beep_bass_text[] = { "50 Hz", "100 Hz", "200 Hz", "250 Hz" }; -static const struct soc_enum beep_bass_enum = - SOC_ENUM_SINGLE(CS42L52_BEEP_TONE_CTL, 1, - ARRAY_SIZE(beep_bass_text), beep_bass_text); +static SOC_ENUM_SINGLE_DECL(beep_bass_enum, + CS42L52_BEEP_TONE_CTL, 1, + beep_bass_text); static const char * const beep_treble_text[] = { "5 kHz", "7 kHz", "10 kHz", " 15 kHz" }; -static const struct soc_enum beep_treble_enum = - SOC_ENUM_SINGLE(CS42L52_BEEP_TONE_CTL, 3, - ARRAY_SIZE(beep_treble_text), beep_treble_text); +static SOC_ENUM_SINGLE_DECL(beep_treble_enum, + CS42L52_BEEP_TONE_CTL, 3, + beep_treble_text); static const char * const ng_threshold_text[] = { "-34dB", "-37dB", "-40dB", "-43dB", "-46dB", "-52dB", "-58dB", "-64dB" }; -static const struct soc_enum ng_threshold_enum = - SOC_ENUM_SINGLE(CS42L52_NOISE_GATE_CTL, 2, - ARRAY_SIZE(ng_threshold_text), ng_threshold_text); +static SOC_ENUM_SINGLE_DECL(ng_threshold_enum, + CS42L52_NOISE_GATE_CTL, 2, + ng_threshold_text); static const char * const cs42l52_ng_delay_text[] = { "50ms", "100ms", "150ms", "200ms"}; -static const struct soc_enum ng_delay_enum = - SOC_ENUM_SINGLE(CS42L52_NOISE_GATE_CTL, 0, - ARRAY_SIZE(cs42l52_ng_delay_text), cs42l52_ng_delay_text); +static SOC_ENUM_SINGLE_DECL(ng_delay_enum, + CS42L52_NOISE_GATE_CTL, 0, + cs42l52_ng_delay_text); static const char * const cs42l52_ng_type_text[] = { "Apply Specific", "Apply All" }; -static const struct soc_enum ng_type_enum = - SOC_ENUM_SINGLE(CS42L52_NOISE_GATE_CTL, 6, - ARRAY_SIZE(cs42l52_ng_type_text), cs42l52_ng_type_text); +static SOC_ENUM_SINGLE_DECL(ng_type_enum, + CS42L52_NOISE_GATE_CTL, 6, + cs42l52_ng_type_text); static const char * const left_swap_text[] = { "Left", "LR 2", "Right"}; @@ -347,7 +341,7 @@ static const char * const right_swap_text[] = { static const unsigned int swap_values[] = { 0, 1, 3 }; static const struct soc_enum adca_swap_enum = - SOC_VALUE_ENUM_SINGLE(CS42L52_ADC_PCM_MIXER, 2, 1, + SOC_VALUE_ENUM_SINGLE(CS42L52_ADC_PCM_MIXER, 2, 3, ARRAY_SIZE(left_swap_text), left_swap_text, swap_values); @@ -356,7 +350,7 @@ static const struct snd_kcontrol_new adca_mixer = SOC_DAPM_ENUM("Route", adca_swap_enum); static const struct soc_enum pcma_swap_enum = - SOC_VALUE_ENUM_SINGLE(CS42L52_ADC_PCM_MIXER, 6, 1, + SOC_VALUE_ENUM_SINGLE(CS42L52_ADC_PCM_MIXER, 6, 3, ARRAY_SIZE(left_swap_text), left_swap_text, swap_values); @@ -365,7 +359,7 @@ static const struct snd_kcontrol_new pcma_mixer = SOC_DAPM_ENUM("Route", pcma_swap_enum); static const struct soc_enum adcb_swap_enum = - SOC_VALUE_ENUM_SINGLE(CS42L52_ADC_PCM_MIXER, 0, 1, + SOC_VALUE_ENUM_SINGLE(CS42L52_ADC_PCM_MIXER, 0, 3, ARRAY_SIZE(right_swap_text), right_swap_text, swap_values); @@ -374,7 +368,7 @@ static const struct snd_kcontrol_new adcb_mixer = SOC_DAPM_ENUM("Route", adcb_swap_enum); static const struct soc_enum pcmb_swap_enum = - SOC_VALUE_ENUM_SINGLE(CS42L52_ADC_PCM_MIXER, 4, 1, + SOC_VALUE_ENUM_SINGLE(CS42L52_ADC_PCM_MIXER, 4, 3, ARRAY_SIZE(right_swap_text), right_swap_text, swap_values); @@ -1115,14 +1109,7 @@ static void cs42l52_free_beep(struct snd_soc_codec *codec) static int cs42l52_probe(struct snd_soc_codec *codec) { struct cs42l52_private *cs42l52 = snd_soc_codec_get_drvdata(codec); - int ret; - codec->control_data = cs42l52->regmap; - ret = snd_soc_codec_set_cache_io(codec, 8, 8, SND_SOC_REGMAP); - if (ret < 0) { - dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); - return ret; - } regcache_cache_only(cs42l52->regmap, true); cs42l52_add_mic_controls(codec); @@ -1134,7 +1121,7 @@ static int cs42l52_probe(struct snd_soc_codec *codec) cs42l52->sysclk = CS42L52_DEFAULT_CLK; cs42l52->config.format = CS42L52_DEFAULT_FORMAT; - return ret; + return 0; } static int cs42l52_remove(struct snd_soc_codec *codec) diff --git a/sound/soc/codecs/cs42l73.c b/sound/soc/codecs/cs42l73.c index 549d5d6a3fe..0ee60a19a26 100644 --- a/sound/soc/codecs/cs42l73.c +++ b/sound/soc/codecs/cs42l73.c @@ -278,13 +278,13 @@ static const DECLARE_TLV_DB_SCALE(attn_tlv, -6300, 100, 1); static const char * const cs42l73_pgaa_text[] = { "Line A", "Mic 1" }; static const char * const cs42l73_pgab_text[] = { "Line B", "Mic 2" }; -static const struct soc_enum pgaa_enum = - SOC_ENUM_SINGLE(CS42L73_ADCIPC, 3, - ARRAY_SIZE(cs42l73_pgaa_text), cs42l73_pgaa_text); +static SOC_ENUM_SINGLE_DECL(pgaa_enum, + CS42L73_ADCIPC, 3, + cs42l73_pgaa_text); -static const struct soc_enum pgab_enum = - SOC_ENUM_SINGLE(CS42L73_ADCIPC, 7, - ARRAY_SIZE(cs42l73_pgab_text), cs42l73_pgab_text); +static SOC_ENUM_SINGLE_DECL(pgab_enum, + CS42L73_ADCIPC, 7, + cs42l73_pgab_text); static const struct snd_kcontrol_new pgaa_mux = SOC_DAPM_ENUM("Left Analog Input Capture Mux", pgaa_enum); @@ -309,9 +309,9 @@ static const struct snd_kcontrol_new input_right_mixer[] = { static const char * const cs42l73_ng_delay_text[] = { "50ms", "100ms", "150ms", "200ms" }; -static const struct soc_enum ng_delay_enum = - SOC_ENUM_SINGLE(CS42L73_NGCAB, 0, - ARRAY_SIZE(cs42l73_ng_delay_text), cs42l73_ng_delay_text); +static SOC_ENUM_SINGLE_DECL(ng_delay_enum, + CS42L73_NGCAB, 0, + cs42l73_ng_delay_text); static const char * const cs42l73_mono_mix_texts[] = { "Left", "Right", "Mono Mix"}; @@ -319,7 +319,7 @@ static const char * const cs42l73_mono_mix_texts[] = { static const unsigned int cs42l73_mono_mix_values[] = { 0, 1, 2 }; static const struct soc_enum spk_asp_enum = - SOC_VALUE_ENUM_SINGLE(CS42L73_MMIXCTL, 6, 1, + SOC_VALUE_ENUM_SINGLE(CS42L73_MMIXCTL, 6, 3, ARRAY_SIZE(cs42l73_mono_mix_texts), cs42l73_mono_mix_texts, cs42l73_mono_mix_values); @@ -337,7 +337,7 @@ static const struct snd_kcontrol_new spk_xsp_mixer = SOC_DAPM_ENUM("Route", spk_xsp_enum); static const struct soc_enum esl_asp_enum = - SOC_VALUE_ENUM_SINGLE(CS42L73_MMIXCTL, 2, 5, + SOC_VALUE_ENUM_SINGLE(CS42L73_MMIXCTL, 2, 3, ARRAY_SIZE(cs42l73_mono_mix_texts), cs42l73_mono_mix_texts, cs42l73_mono_mix_values); @@ -346,7 +346,7 @@ static const struct snd_kcontrol_new esl_asp_mixer = SOC_DAPM_ENUM("Route", esl_asp_enum); static const struct soc_enum esl_xsp_enum = - SOC_VALUE_ENUM_SINGLE(CS42L73_MMIXCTL, 0, 7, + SOC_VALUE_ENUM_SINGLE(CS42L73_MMIXCTL, 0, 3, ARRAY_SIZE(cs42l73_mono_mix_texts), cs42l73_mono_mix_texts, cs42l73_mono_mix_values); @@ -357,19 +357,19 @@ static const struct snd_kcontrol_new esl_xsp_mixer = static const char * const cs42l73_ip_swap_text[] = { "Stereo", "Mono A", "Mono B", "Swap A-B"}; -static const struct soc_enum ip_swap_enum = - SOC_ENUM_SINGLE(CS42L73_MIOPC, 6, - ARRAY_SIZE(cs42l73_ip_swap_text), cs42l73_ip_swap_text); +static SOC_ENUM_SINGLE_DECL(ip_swap_enum, + CS42L73_MIOPC, 6, + cs42l73_ip_swap_text); static const char * const cs42l73_spo_mixer_text[] = {"Mono", "Stereo"}; -static const struct soc_enum vsp_output_mux_enum = - SOC_ENUM_SINGLE(CS42L73_MIXERCTL, 5, - ARRAY_SIZE(cs42l73_spo_mixer_text), cs42l73_spo_mixer_text); +static SOC_ENUM_SINGLE_DECL(vsp_output_mux_enum, + CS42L73_MIXERCTL, 5, + cs42l73_spo_mixer_text); -static const struct soc_enum xsp_output_mux_enum = - SOC_ENUM_SINGLE(CS42L73_MIXERCTL, 4, - ARRAY_SIZE(cs42l73_spo_mixer_text), cs42l73_spo_mixer_text); +static SOC_ENUM_SINGLE_DECL(xsp_output_mux_enum, + CS42L73_MIXERCTL, 4, + cs42l73_spo_mixer_text); static const struct snd_kcontrol_new vsp_output_mux = SOC_DAPM_ENUM("Route", vsp_output_mux_enum); @@ -1108,7 +1108,7 @@ static int cs42l73_set_dai_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt) return 0; } -static u32 cs42l73_asrc_rates[] = { +static const unsigned int cs42l73_asrc_rates[] = { 8000, 11025, 12000, 16000, 22050, 24000, 32000, 44100, 48000 }; @@ -1241,7 +1241,7 @@ static int cs42l73_set_tristate(struct snd_soc_dai *dai, int tristate) 0x7F, tristate << 7); } -static struct snd_pcm_hw_constraint_list constraints_12_24 = { +static const struct snd_pcm_hw_constraint_list constraints_12_24 = { .count = ARRAY_SIZE(cs42l73_asrc_rates), .list = cs42l73_asrc_rates, }; @@ -1255,9 +1255,6 @@ static int cs42l73_pcm_startup(struct snd_pcm_substream *substream, return 0; } -/* SNDRV_PCM_RATE_KNOT -> 12000, 24000 Hz, limit with constraint list */ -#define CS42L73_RATES (SNDRV_PCM_RATE_8000_48000 | SNDRV_PCM_RATE_KNOT) - #define CS42L73_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\ SNDRV_PCM_FMTBIT_S24_LE) @@ -1278,14 +1275,14 @@ static struct snd_soc_dai_driver cs42l73_dai[] = { .stream_name = "XSP Playback", .channels_min = 1, .channels_max = 2, - .rates = CS42L73_RATES, + .rates = SNDRV_PCM_RATE_KNOT, .formats = CS42L73_FORMATS, }, .capture = { .stream_name = "XSP Capture", .channels_min = 1, .channels_max = 2, - .rates = CS42L73_RATES, + .rates = SNDRV_PCM_RATE_KNOT, .formats = CS42L73_FORMATS, }, .ops = &cs42l73_ops, @@ -1298,14 +1295,14 @@ static struct snd_soc_dai_driver cs42l73_dai[] = { .stream_name = "ASP Playback", .channels_min = 2, .channels_max = 2, - .rates = CS42L73_RATES, + .rates = SNDRV_PCM_RATE_KNOT, .formats = CS42L73_FORMATS, }, .capture = { .stream_name = "ASP Capture", .channels_min = 2, .channels_max = 2, - .rates = CS42L73_RATES, + .rates = SNDRV_PCM_RATE_KNOT, .formats = CS42L73_FORMATS, }, .ops = &cs42l73_ops, @@ -1318,14 +1315,14 @@ static struct snd_soc_dai_driver cs42l73_dai[] = { .stream_name = "VSP Playback", .channels_min = 1, .channels_max = 2, - .rates = CS42L73_RATES, + .rates = SNDRV_PCM_RATE_KNOT, .formats = CS42L73_FORMATS, }, .capture = { .stream_name = "VSP Capture", .channels_min = 1, .channels_max = 2, - .rates = CS42L73_RATES, + .rates = SNDRV_PCM_RATE_KNOT, .formats = CS42L73_FORMATS, }, .ops = &cs42l73_ops, @@ -1348,17 +1345,8 @@ static int cs42l73_resume(struct snd_soc_codec *codec) static int cs42l73_probe(struct snd_soc_codec *codec) { - int ret; struct cs42l73_private *cs42l73 = snd_soc_codec_get_drvdata(codec); - codec->control_data = cs42l73->regmap; - - ret = snd_soc_codec_set_cache_io(codec, 8, 8, SND_SOC_REGMAP); - if (ret < 0) { - dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); - return ret; - } - cs42l73_set_bias_level(codec, SND_SOC_BIAS_STANDBY); /* Set Charge Pump Frequency */ @@ -1371,7 +1359,7 @@ static int cs42l73_probe(struct snd_soc_codec *codec) cs42l73->mclksel = CS42L73_CLKID_MCLK1; cs42l73->mclk = 0; - return ret; + return 0; } static int cs42l73_remove(struct snd_soc_codec *codec) diff --git a/sound/soc/codecs/cs42xx8-i2c.c b/sound/soc/codecs/cs42xx8-i2c.c new file mode 100644 index 00000000000..657dce27ead --- /dev/null +++ b/sound/soc/codecs/cs42xx8-i2c.c @@ -0,0 +1,64 @@ +/* + * Cirrus Logic CS42448/CS42888 Audio CODEC DAI I2C driver + * + * Copyright (C) 2014 Freescale Semiconductor, Inc. + * + * Author: Nicolin Chen <Guangyu.Chen@freescale.com> + * + * This file is licensed under the terms of the GNU General Public License + * version 2. This program is licensed "as is" without any warranty of any + * kind, whether express or implied. + */ + +#include <linux/i2c.h> +#include <linux/module.h> +#include <linux/pm_runtime.h> +#include <sound/soc.h> + +#include "cs42xx8.h" + +static int cs42xx8_i2c_probe(struct i2c_client *i2c, + const struct i2c_device_id *id) +{ + u32 ret = cs42xx8_probe(&i2c->dev, + devm_regmap_init_i2c(i2c, &cs42xx8_regmap_config)); + if (ret) + return ret; + + pm_runtime_enable(&i2c->dev); + pm_request_idle(&i2c->dev); + + return 0; +} + +static int cs42xx8_i2c_remove(struct i2c_client *i2c) +{ + snd_soc_unregister_codec(&i2c->dev); + pm_runtime_disable(&i2c->dev); + + return 0; +} + +static struct i2c_device_id cs42xx8_i2c_id[] = { + {"cs42448", (kernel_ulong_t)&cs42448_data}, + {"cs42888", (kernel_ulong_t)&cs42888_data}, + {} +}; +MODULE_DEVICE_TABLE(i2c, cs42xx8_i2c_id); + +static struct i2c_driver cs42xx8_i2c_driver = { + .driver = { + .name = "cs42xx8", + .owner = THIS_MODULE, + .pm = &cs42xx8_pm, + }, + .probe = cs42xx8_i2c_probe, + .remove = cs42xx8_i2c_remove, + .id_table = cs42xx8_i2c_id, +}; + +module_i2c_driver(cs42xx8_i2c_driver); + +MODULE_DESCRIPTION("Cirrus Logic CS42448/CS42888 ALSA SoC Codec I2C Driver"); +MODULE_AUTHOR("Freescale Semiconductor, Inc."); +MODULE_LICENSE("GPL"); diff --git a/sound/soc/codecs/cs42xx8.c b/sound/soc/codecs/cs42xx8.c new file mode 100644 index 00000000000..082299a4e2f --- /dev/null +++ b/sound/soc/codecs/cs42xx8.c @@ -0,0 +1,602 @@ +/* + * Cirrus Logic CS42448/CS42888 Audio CODEC Digital Audio Interface (DAI) driver + * + * Copyright (C) 2014 Freescale Semiconductor, Inc. + * + * Author: Nicolin Chen <Guangyu.Chen@freescale.com> + * + * This file is licensed under the terms of the GNU General Public License + * version 2. This program is licensed "as is" without any warranty of any + * kind, whether express or implied. + */ + +#include <linux/clk.h> +#include <linux/delay.h> +#include <linux/module.h> +#include <linux/of_device.h> +#include <linux/pm_runtime.h> +#include <linux/regulator/consumer.h> +#include <sound/pcm_params.h> +#include <sound/soc.h> +#include <sound/tlv.h> + +#include "cs42xx8.h" + +#define CS42XX8_NUM_SUPPLIES 4 +static const char *const cs42xx8_supply_names[CS42XX8_NUM_SUPPLIES] = { + "VA", + "VD", + "VLS", + "VLC", +}; + +#define CS42XX8_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | \ + SNDRV_PCM_FMTBIT_S20_3LE | \ + SNDRV_PCM_FMTBIT_S24_LE | \ + SNDRV_PCM_FMTBIT_S32_LE) + +/* codec private data */ +struct cs42xx8_priv { + struct regulator_bulk_data supplies[CS42XX8_NUM_SUPPLIES]; + const struct cs42xx8_driver_data *drvdata; + struct regmap *regmap; + struct clk *clk; + + bool slave_mode; + unsigned long sysclk; +}; + +/* -127.5dB to 0dB with step of 0.5dB */ +static const DECLARE_TLV_DB_SCALE(dac_tlv, -12750, 50, 1); +/* -64dB to 24dB with step of 0.5dB */ +static const DECLARE_TLV_DB_SCALE(adc_tlv, -6400, 50, 0); + +static const char *const cs42xx8_adc_single[] = { "Differential", "Single-Ended" }; +static const char *const cs42xx8_szc[] = { "Immediate Change", "Zero Cross", + "Soft Ramp", "Soft Ramp on Zero Cross" }; + +static const struct soc_enum adc1_single_enum = + SOC_ENUM_SINGLE(CS42XX8_ADCCTL, 4, 2, cs42xx8_adc_single); +static const struct soc_enum adc2_single_enum = + SOC_ENUM_SINGLE(CS42XX8_ADCCTL, 3, 2, cs42xx8_adc_single); +static const struct soc_enum adc3_single_enum = + SOC_ENUM_SINGLE(CS42XX8_ADCCTL, 2, 2, cs42xx8_adc_single); +static const struct soc_enum dac_szc_enum = + SOC_ENUM_SINGLE(CS42XX8_TXCTL, 5, 4, cs42xx8_szc); +static const struct soc_enum adc_szc_enum = + SOC_ENUM_SINGLE(CS42XX8_TXCTL, 0, 4, cs42xx8_szc); + +static const struct snd_kcontrol_new cs42xx8_snd_controls[] = { + SOC_DOUBLE_R_TLV("DAC1 Playback Volume", CS42XX8_VOLAOUT1, + CS42XX8_VOLAOUT2, 0, 0xff, 1, dac_tlv), + SOC_DOUBLE_R_TLV("DAC2 Playback Volume", CS42XX8_VOLAOUT3, + CS42XX8_VOLAOUT4, 0, 0xff, 1, dac_tlv), + SOC_DOUBLE_R_TLV("DAC3 Playback Volume", CS42XX8_VOLAOUT5, + CS42XX8_VOLAOUT6, 0, 0xff, 1, dac_tlv), + SOC_DOUBLE_R_TLV("DAC4 Playback Volume", CS42XX8_VOLAOUT7, + CS42XX8_VOLAOUT8, 0, 0xff, 1, dac_tlv), + SOC_DOUBLE_R_S_TLV("ADC1 Capture Volume", CS42XX8_VOLAIN1, + CS42XX8_VOLAIN2, 0, -0x80, 0x30, 7, 0, adc_tlv), + SOC_DOUBLE_R_S_TLV("ADC2 Capture Volume", CS42XX8_VOLAIN3, + CS42XX8_VOLAIN4, 0, -0x80, 0x30, 7, 0, adc_tlv), + SOC_DOUBLE("DAC1 Invert Switch", CS42XX8_DACINV, 0, 1, 1, 0), + SOC_DOUBLE("DAC2 Invert Switch", CS42XX8_DACINV, 2, 3, 1, 0), + SOC_DOUBLE("DAC3 Invert Switch", CS42XX8_DACINV, 4, 5, 1, 0), + SOC_DOUBLE("DAC4 Invert Switch", CS42XX8_DACINV, 6, 7, 1, 0), + SOC_DOUBLE("ADC1 Invert Switch", CS42XX8_ADCINV, 0, 1, 1, 0), + SOC_DOUBLE("ADC2 Invert Switch", CS42XX8_ADCINV, 2, 3, 1, 0), + SOC_SINGLE("ADC High-Pass Filter Switch", CS42XX8_ADCCTL, 7, 1, 1), + SOC_SINGLE("DAC De-emphasis Switch", CS42XX8_ADCCTL, 5, 1, 0), + SOC_ENUM("ADC1 Single Ended Mode Switch", adc1_single_enum), + SOC_ENUM("ADC2 Single Ended Mode Switch", adc2_single_enum), + SOC_SINGLE("DAC Single Volume Control Switch", CS42XX8_TXCTL, 7, 1, 0), + SOC_ENUM("DAC Soft Ramp & Zero Cross Control Switch", dac_szc_enum), + SOC_SINGLE("DAC Auto Mute Switch", CS42XX8_TXCTL, 4, 1, 0), + SOC_SINGLE("Mute ADC Serial Port Switch", CS42XX8_TXCTL, 3, 1, 0), + SOC_SINGLE("ADC Single Volume Control Switch", CS42XX8_TXCTL, 2, 1, 0), + SOC_ENUM("ADC Soft Ramp & Zero Cross Control Switch", adc_szc_enum), +}; + +static const struct snd_kcontrol_new cs42xx8_adc3_snd_controls[] = { + SOC_DOUBLE_R_S_TLV("ADC3 Capture Volume", CS42XX8_VOLAIN5, + CS42XX8_VOLAIN6, 0, -0x80, 0x30, 7, 0, adc_tlv), + SOC_DOUBLE("ADC3 Invert Switch", CS42XX8_ADCINV, 4, 5, 1, 0), + SOC_ENUM("ADC3 Single Ended Mode Switch", adc3_single_enum), +}; + +static const struct snd_soc_dapm_widget cs42xx8_dapm_widgets[] = { + SND_SOC_DAPM_DAC("DAC1", "Playback", CS42XX8_PWRCTL, 1, 1), + SND_SOC_DAPM_DAC("DAC2", "Playback", CS42XX8_PWRCTL, 2, 1), + SND_SOC_DAPM_DAC("DAC3", "Playback", CS42XX8_PWRCTL, 3, 1), + SND_SOC_DAPM_DAC("DAC4", "Playback", CS42XX8_PWRCTL, 4, 1), + + SND_SOC_DAPM_OUTPUT("AOUT1L"), + SND_SOC_DAPM_OUTPUT("AOUT1R"), + SND_SOC_DAPM_OUTPUT("AOUT2L"), + SND_SOC_DAPM_OUTPUT("AOUT2R"), + SND_SOC_DAPM_OUTPUT("AOUT3L"), + SND_SOC_DAPM_OUTPUT("AOUT3R"), + SND_SOC_DAPM_OUTPUT("AOUT4L"), + SND_SOC_DAPM_OUTPUT("AOUT4R"), + + SND_SOC_DAPM_ADC("ADC1", "Capture", CS42XX8_PWRCTL, 5, 1), + SND_SOC_DAPM_ADC("ADC2", "Capture", CS42XX8_PWRCTL, 6, 1), + + SND_SOC_DAPM_INPUT("AIN1L"), + SND_SOC_DAPM_INPUT("AIN1R"), + SND_SOC_DAPM_INPUT("AIN2L"), + SND_SOC_DAPM_INPUT("AIN2R"), + + SND_SOC_DAPM_SUPPLY("PWR", CS42XX8_PWRCTL, 0, 1, NULL, 0), +}; + +static const struct snd_soc_dapm_widget cs42xx8_adc3_dapm_widgets[] = { + SND_SOC_DAPM_ADC("ADC3", "Capture", CS42XX8_PWRCTL, 7, 1), + + SND_SOC_DAPM_INPUT("AIN3L"), + SND_SOC_DAPM_INPUT("AIN3R"), +}; + +static const struct snd_soc_dapm_route cs42xx8_dapm_routes[] = { + /* Playback */ + { "AOUT1L", NULL, "DAC1" }, + { "AOUT1R", NULL, "DAC1" }, + { "DAC1", NULL, "PWR" }, + + { "AOUT2L", NULL, "DAC2" }, + { "AOUT2R", NULL, "DAC2" }, + { "DAC2", NULL, "PWR" }, + + { "AOUT3L", NULL, "DAC3" }, + { "AOUT3R", NULL, "DAC3" }, + { "DAC3", NULL, "PWR" }, + + { "AOUT4L", NULL, "DAC4" }, + { "AOUT4R", NULL, "DAC4" }, + { "DAC4", NULL, "PWR" }, + + /* Capture */ + { "ADC1", NULL, "AIN1L" }, + { "ADC1", NULL, "AIN1R" }, + { "ADC1", NULL, "PWR" }, + + { "ADC2", NULL, "AIN2L" }, + { "ADC2", NULL, "AIN2R" }, + { "ADC2", NULL, "PWR" }, +}; + +static const struct snd_soc_dapm_route cs42xx8_adc3_dapm_routes[] = { + /* Capture */ + { "ADC3", NULL, "AIN3L" }, + { "ADC3", NULL, "AIN3R" }, + { "ADC3", NULL, "PWR" }, +}; + +struct cs42xx8_ratios { + unsigned int ratio; + unsigned char speed; + unsigned char mclk; +}; + +static const struct cs42xx8_ratios cs42xx8_ratios[] = { + { 64, CS42XX8_FM_QUAD, CS42XX8_FUNCMOD_MFREQ_256(4) }, + { 96, CS42XX8_FM_QUAD, CS42XX8_FUNCMOD_MFREQ_384(4) }, + { 128, CS42XX8_FM_QUAD, CS42XX8_FUNCMOD_MFREQ_512(4) }, + { 192, CS42XX8_FM_QUAD, CS42XX8_FUNCMOD_MFREQ_768(4) }, + { 256, CS42XX8_FM_SINGLE, CS42XX8_FUNCMOD_MFREQ_256(1) }, + { 384, CS42XX8_FM_SINGLE, CS42XX8_FUNCMOD_MFREQ_384(1) }, + { 512, CS42XX8_FM_SINGLE, CS42XX8_FUNCMOD_MFREQ_512(1) }, + { 768, CS42XX8_FM_SINGLE, CS42XX8_FUNCMOD_MFREQ_768(1) }, + { 1024, CS42XX8_FM_SINGLE, CS42XX8_FUNCMOD_MFREQ_1024(1) } +}; + +static int cs42xx8_set_dai_sysclk(struct snd_soc_dai *codec_dai, + int clk_id, unsigned int freq, int dir) +{ + struct snd_soc_codec *codec = codec_dai->codec; + struct cs42xx8_priv *cs42xx8 = snd_soc_codec_get_drvdata(codec); + + cs42xx8->sysclk = freq; + + return 0; +} + +static int cs42xx8_set_dai_fmt(struct snd_soc_dai *codec_dai, + unsigned int format) +{ + struct snd_soc_codec *codec = codec_dai->codec; + struct cs42xx8_priv *cs42xx8 = snd_soc_codec_get_drvdata(codec); + u32 val; + + /* Set DAI format */ + switch (format & SND_SOC_DAIFMT_FORMAT_MASK) { + case SND_SOC_DAIFMT_LEFT_J: + val = CS42XX8_INTF_DAC_DIF_LEFTJ | CS42XX8_INTF_ADC_DIF_LEFTJ; + break; + case SND_SOC_DAIFMT_I2S: + val = CS42XX8_INTF_DAC_DIF_I2S | CS42XX8_INTF_ADC_DIF_I2S; + break; + case SND_SOC_DAIFMT_RIGHT_J: + val = CS42XX8_INTF_DAC_DIF_RIGHTJ | CS42XX8_INTF_ADC_DIF_RIGHTJ; + break; + default: + dev_err(codec->dev, "unsupported dai format\n"); + return -EINVAL; + } + + regmap_update_bits(cs42xx8->regmap, CS42XX8_INTF, + CS42XX8_INTF_DAC_DIF_MASK | + CS42XX8_INTF_ADC_DIF_MASK, val); + + /* Set master/slave audio interface */ + switch (format & SND_SOC_DAIFMT_MASTER_MASK) { + case SND_SOC_DAIFMT_CBS_CFS: + cs42xx8->slave_mode = true; + break; + case SND_SOC_DAIFMT_CBM_CFM: + cs42xx8->slave_mode = false; + break; + default: + dev_err(codec->dev, "unsupported master/slave mode\n"); + return -EINVAL; + } + + return 0; +} + +static int cs42xx8_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params, + struct snd_soc_dai *dai) +{ + struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_codec *codec = rtd->codec; + struct cs42xx8_priv *cs42xx8 = snd_soc_codec_get_drvdata(codec); + bool tx = substream->stream == SNDRV_PCM_STREAM_PLAYBACK; + u32 ratio = cs42xx8->sysclk / params_rate(params); + u32 i, fm, val, mask; + + for (i = 0; i < ARRAY_SIZE(cs42xx8_ratios); i++) { + if (cs42xx8_ratios[i].ratio == ratio) + break; + } + + if (i == ARRAY_SIZE(cs42xx8_ratios)) { + dev_err(codec->dev, "unsupported sysclk ratio\n"); + return -EINVAL; + } + + mask = CS42XX8_FUNCMOD_MFREQ_MASK; + val = cs42xx8_ratios[i].mclk; + + fm = cs42xx8->slave_mode ? CS42XX8_FM_AUTO : cs42xx8_ratios[i].speed; + + regmap_update_bits(cs42xx8->regmap, CS42XX8_FUNCMOD, + CS42XX8_FUNCMOD_xC_FM_MASK(tx) | mask, + CS42XX8_FUNCMOD_xC_FM(tx, fm) | val); + + return 0; +} + +static int cs42xx8_digital_mute(struct snd_soc_dai *dai, int mute) +{ + struct snd_soc_codec *codec = dai->codec; + struct cs42xx8_priv *cs42xx8 = snd_soc_codec_get_drvdata(codec); + + regmap_update_bits(cs42xx8->regmap, CS42XX8_DACMUTE, + CS42XX8_DACMUTE_ALL, mute ? CS42XX8_DACMUTE_ALL : 0); + + return 0; +} + +static const struct snd_soc_dai_ops cs42xx8_dai_ops = { + .set_fmt = cs42xx8_set_dai_fmt, + .set_sysclk = cs42xx8_set_dai_sysclk, + .hw_params = cs42xx8_hw_params, + .digital_mute = cs42xx8_digital_mute, +}; + +static struct snd_soc_dai_driver cs42xx8_dai = { + .playback = { + .stream_name = "Playback", + .channels_min = 1, + .channels_max = 8, + .rates = SNDRV_PCM_RATE_8000_192000, + .formats = CS42XX8_FORMATS, + }, + .capture = { + .stream_name = "Capture", + .channels_min = 1, + .rates = SNDRV_PCM_RATE_8000_192000, + .formats = CS42XX8_FORMATS, + }, + .ops = &cs42xx8_dai_ops, +}; + +static const struct reg_default cs42xx8_reg[] = { + { 0x01, 0x01 }, /* Chip I.D. and Revision Register */ + { 0x02, 0x00 }, /* Power Control */ + { 0x03, 0xF0 }, /* Functional Mode */ + { 0x04, 0x46 }, /* Interface Formats */ + { 0x05, 0x00 }, /* ADC Control & DAC De-Emphasis */ + { 0x06, 0x10 }, /* Transition Control */ + { 0x07, 0x00 }, /* DAC Channel Mute */ + { 0x08, 0x00 }, /* Volume Control AOUT1 */ + { 0x09, 0x00 }, /* Volume Control AOUT2 */ + { 0x0a, 0x00 }, /* Volume Control AOUT3 */ + { 0x0b, 0x00 }, /* Volume Control AOUT4 */ + { 0x0c, 0x00 }, /* Volume Control AOUT5 */ + { 0x0d, 0x00 }, /* Volume Control AOUT6 */ + { 0x0e, 0x00 }, /* Volume Control AOUT7 */ + { 0x0f, 0x00 }, /* Volume Control AOUT8 */ + { 0x10, 0x00 }, /* DAC Channel Invert */ + { 0x11, 0x00 }, /* Volume Control AIN1 */ + { 0x12, 0x00 }, /* Volume Control AIN2 */ + { 0x13, 0x00 }, /* Volume Control AIN3 */ + { 0x14, 0x00 }, /* Volume Control AIN4 */ + { 0x15, 0x00 }, /* Volume Control AIN5 */ + { 0x16, 0x00 }, /* Volume Control AIN6 */ + { 0x17, 0x00 }, /* ADC Channel Invert */ + { 0x18, 0x00 }, /* Status Control */ + { 0x1a, 0x00 }, /* Status Mask */ + { 0x1b, 0x00 }, /* MUTEC Pin Control */ +}; + +static bool cs42xx8_volatile_register(struct device *dev, unsigned int reg) +{ + switch (reg) { + case CS42XX8_STATUS: + return true; + default: + return false; + } +} + +static bool cs42xx8_writeable_register(struct device *dev, unsigned int reg) +{ + switch (reg) { + case CS42XX8_CHIPID: + case CS42XX8_STATUS: + return false; + default: + return true; + } +} + +const struct regmap_config cs42xx8_regmap_config = { + .reg_bits = 8, + .val_bits = 8, + + .max_register = CS42XX8_LASTREG, + .reg_defaults = cs42xx8_reg, + .num_reg_defaults = ARRAY_SIZE(cs42xx8_reg), + .volatile_reg = cs42xx8_volatile_register, + .writeable_reg = cs42xx8_writeable_register, + .cache_type = REGCACHE_RBTREE, +}; +EXPORT_SYMBOL_GPL(cs42xx8_regmap_config); + +static int cs42xx8_codec_probe(struct snd_soc_codec *codec) +{ + struct cs42xx8_priv *cs42xx8 = snd_soc_codec_get_drvdata(codec); + struct snd_soc_dapm_context *dapm = &codec->dapm; + + switch (cs42xx8->drvdata->num_adcs) { + case 3: + snd_soc_add_codec_controls(codec, cs42xx8_adc3_snd_controls, + ARRAY_SIZE(cs42xx8_adc3_snd_controls)); + snd_soc_dapm_new_controls(dapm, cs42xx8_adc3_dapm_widgets, + ARRAY_SIZE(cs42xx8_adc3_dapm_widgets)); + snd_soc_dapm_add_routes(dapm, cs42xx8_adc3_dapm_routes, + ARRAY_SIZE(cs42xx8_adc3_dapm_routes)); + break; + default: + break; + } + + /* Mute all DAC channels */ + regmap_write(cs42xx8->regmap, CS42XX8_DACMUTE, CS42XX8_DACMUTE_ALL); + + return 0; +} + +static const struct snd_soc_codec_driver cs42xx8_driver = { + .probe = cs42xx8_codec_probe, + .idle_bias_off = true, + + .controls = cs42xx8_snd_controls, + .num_controls = ARRAY_SIZE(cs42xx8_snd_controls), + .dapm_widgets = cs42xx8_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(cs42xx8_dapm_widgets), + .dapm_routes = cs42xx8_dapm_routes, + .num_dapm_routes = ARRAY_SIZE(cs42xx8_dapm_routes), +}; + +const struct cs42xx8_driver_data cs42448_data = { + .name = "cs42448", + .num_adcs = 3, +}; +EXPORT_SYMBOL_GPL(cs42448_data); + +const struct cs42xx8_driver_data cs42888_data = { + .name = "cs42888", + .num_adcs = 2, +}; +EXPORT_SYMBOL_GPL(cs42888_data); + +const struct of_device_id cs42xx8_of_match[] = { + { .compatible = "cirrus,cs42448", .data = &cs42448_data, }, + { .compatible = "cirrus,cs42888", .data = &cs42888_data, }, + { /* sentinel */ } +}; +MODULE_DEVICE_TABLE(of, cs42xx8_of_match); +EXPORT_SYMBOL_GPL(cs42xx8_of_match); + +int cs42xx8_probe(struct device *dev, struct regmap *regmap) +{ + const struct of_device_id *of_id = of_match_device(cs42xx8_of_match, dev); + struct cs42xx8_priv *cs42xx8; + int ret, val, i; + + cs42xx8 = devm_kzalloc(dev, sizeof(*cs42xx8), GFP_KERNEL); + if (cs42xx8 == NULL) + return -ENOMEM; + + dev_set_drvdata(dev, cs42xx8); + + if (of_id) + cs42xx8->drvdata = of_id->data; + + if (!cs42xx8->drvdata) { + dev_err(dev, "failed to find driver data\n"); + return -EINVAL; + } + + cs42xx8->clk = devm_clk_get(dev, "mclk"); + if (IS_ERR(cs42xx8->clk)) { + dev_err(dev, "failed to get the clock: %ld\n", + PTR_ERR(cs42xx8->clk)); + return -EINVAL; + } + + cs42xx8->sysclk = clk_get_rate(cs42xx8->clk); + + for (i = 0; i < ARRAY_SIZE(cs42xx8->supplies); i++) + cs42xx8->supplies[i].supply = cs42xx8_supply_names[i]; + + ret = devm_regulator_bulk_get(dev, + ARRAY_SIZE(cs42xx8->supplies), cs42xx8->supplies); + if (ret) { + dev_err(dev, "failed to request supplies: %d\n", ret); + return ret; + } + + ret = regulator_bulk_enable(ARRAY_SIZE(cs42xx8->supplies), + cs42xx8->supplies); + if (ret) { + dev_err(dev, "failed to enable supplies: %d\n", ret); + return ret; + } + + /* Make sure hardware reset done */ + msleep(5); + + cs42xx8->regmap = regmap; + if (IS_ERR(cs42xx8->regmap)) { + ret = PTR_ERR(cs42xx8->regmap); + dev_err(dev, "failed to allocate regmap: %d\n", ret); + goto err_enable; + } + + /* + * We haven't marked the chip revision as volatile due to + * sharing a register with the right input volume; explicitly + * bypass the cache to read it. + */ + regcache_cache_bypass(cs42xx8->regmap, true); + + /* Validate the chip ID */ + regmap_read(cs42xx8->regmap, CS42XX8_CHIPID, &val); + if (val < 0) { + dev_err(dev, "failed to get device ID: %x", val); + ret = -EINVAL; + goto err_enable; + } + + /* The top four bits of the chip ID should be 0000 */ + if ((val & CS42XX8_CHIPID_CHIP_ID_MASK) != 0x00) { + dev_err(dev, "unmatched chip ID: %d\n", + val & CS42XX8_CHIPID_CHIP_ID_MASK); + ret = -EINVAL; + goto err_enable; + } + + dev_info(dev, "found device, revision %X\n", + val & CS42XX8_CHIPID_REV_ID_MASK); + + regcache_cache_bypass(cs42xx8->regmap, false); + + cs42xx8_dai.name = cs42xx8->drvdata->name; + + /* Each adc supports stereo input */ + cs42xx8_dai.capture.channels_max = cs42xx8->drvdata->num_adcs * 2; + + ret = snd_soc_register_codec(dev, &cs42xx8_driver, &cs42xx8_dai, 1); + if (ret) { + dev_err(dev, "failed to register codec:%d\n", ret); + goto err_enable; + } + + regcache_cache_only(cs42xx8->regmap, true); + +err_enable: + regulator_bulk_disable(ARRAY_SIZE(cs42xx8->supplies), + cs42xx8->supplies); + + return ret; +} +EXPORT_SYMBOL_GPL(cs42xx8_probe); + +#ifdef CONFIG_PM_RUNTIME +static int cs42xx8_runtime_resume(struct device *dev) +{ + struct cs42xx8_priv *cs42xx8 = dev_get_drvdata(dev); + int ret; + + ret = clk_prepare_enable(cs42xx8->clk); + if (ret) { + dev_err(dev, "failed to enable mclk: %d\n", ret); + return ret; + } + + ret = regulator_bulk_enable(ARRAY_SIZE(cs42xx8->supplies), + cs42xx8->supplies); + if (ret) { + dev_err(dev, "failed to enable supplies: %d\n", ret); + goto err_clk; + } + + /* Make sure hardware reset done */ + msleep(5); + + regcache_cache_only(cs42xx8->regmap, false); + + ret = regcache_sync(cs42xx8->regmap); + if (ret) { + dev_err(dev, "failed to sync regmap: %d\n", ret); + goto err_bulk; + } + + return 0; + +err_bulk: + regulator_bulk_disable(ARRAY_SIZE(cs42xx8->supplies), + cs42xx8->supplies); +err_clk: + clk_disable_unprepare(cs42xx8->clk); + + return ret; +} + +static int cs42xx8_runtime_suspend(struct device *dev) +{ + struct cs42xx8_priv *cs42xx8 = dev_get_drvdata(dev); + + regcache_cache_only(cs42xx8->regmap, true); + + regulator_bulk_disable(ARRAY_SIZE(cs42xx8->supplies), + cs42xx8->supplies); + + clk_disable_unprepare(cs42xx8->clk); + + return 0; +} +#endif + +const struct dev_pm_ops cs42xx8_pm = { + SET_RUNTIME_PM_OPS(cs42xx8_runtime_suspend, cs42xx8_runtime_resume, NULL) +}; +EXPORT_SYMBOL_GPL(cs42xx8_pm); + +MODULE_DESCRIPTION("Cirrus Logic CS42448/CS42888 ALSA SoC Codec Driver"); +MODULE_AUTHOR("Freescale Semiconductor, Inc."); +MODULE_LICENSE("GPL"); diff --git a/sound/soc/codecs/cs42xx8.h b/sound/soc/codecs/cs42xx8.h new file mode 100644 index 00000000000..da0b94aee41 --- /dev/null +++ b/sound/soc/codecs/cs42xx8.h @@ -0,0 +1,238 @@ +/* + * cs42xx8.h - Cirrus Logic CS42448/CS42888 Audio CODEC driver header file + * + * Copyright (C) 2014 Freescale Semiconductor, Inc. + * + * Author: Nicolin Chen <Guangyu.Chen@freescale.com> + * + * This file is licensed under the terms of the GNU General Public License + * version 2. This program is licensed "as is" without any warranty of any + * kind, whether express or implied. + */ + +#ifndef _CS42XX8_H +#define _CS42XX8_H + +struct cs42xx8_driver_data { + char name[32]; + int num_adcs; +}; + +extern const struct dev_pm_ops cs42xx8_pm; +extern const struct cs42xx8_driver_data cs42448_data; +extern const struct cs42xx8_driver_data cs42888_data; +extern const struct regmap_config cs42xx8_regmap_config; +int cs42xx8_probe(struct device *dev, struct regmap *regmap); + +/* CS42888 register map */ +#define CS42XX8_CHIPID 0x01 /* Chip ID */ +#define CS42XX8_PWRCTL 0x02 /* Power Control */ +#define CS42XX8_FUNCMOD 0x03 /* Functional Mode */ +#define CS42XX8_INTF 0x04 /* Interface Formats */ +#define CS42XX8_ADCCTL 0x05 /* ADC Control */ +#define CS42XX8_TXCTL 0x06 /* Transition Control */ +#define CS42XX8_DACMUTE 0x07 /* DAC Mute Control */ +#define CS42XX8_VOLAOUT1 0x08 /* Volume Control AOUT1 */ +#define CS42XX8_VOLAOUT2 0x09 /* Volume Control AOUT2 */ +#define CS42XX8_VOLAOUT3 0x0A /* Volume Control AOUT3 */ +#define CS42XX8_VOLAOUT4 0x0B /* Volume Control AOUT4 */ +#define CS42XX8_VOLAOUT5 0x0C /* Volume Control AOUT5 */ +#define CS42XX8_VOLAOUT6 0x0D /* Volume Control AOUT6 */ +#define CS42XX8_VOLAOUT7 0x0E /* Volume Control AOUT7 */ +#define CS42XX8_VOLAOUT8 0x0F /* Volume Control AOUT8 */ +#define CS42XX8_DACINV 0x10 /* DAC Channel Invert */ +#define CS42XX8_VOLAIN1 0x11 /* Volume Control AIN1 */ +#define CS42XX8_VOLAIN2 0x12 /* Volume Control AIN2 */ +#define CS42XX8_VOLAIN3 0x13 /* Volume Control AIN3 */ +#define CS42XX8_VOLAIN4 0x14 /* Volume Control AIN4 */ +#define CS42XX8_VOLAIN5 0x15 /* Volume Control AIN5 */ +#define CS42XX8_VOLAIN6 0x16 /* Volume Control AIN6 */ +#define CS42XX8_ADCINV 0x17 /* ADC Channel Invert */ +#define CS42XX8_STATUSCTL 0x18 /* Status Control */ +#define CS42XX8_STATUS 0x19 /* Status */ +#define CS42XX8_STATUSM 0x1A /* Status Mask */ +#define CS42XX8_MUTEC 0x1B /* MUTEC Pin Control */ + +#define CS42XX8_FIRSTREG CS42XX8_CHIPID +#define CS42XX8_LASTREG CS42XX8_MUTEC +#define CS42XX8_NUMREGS (CS42XX8_LASTREG - CS42XX8_FIRSTREG + 1) +#define CS42XX8_I2C_INCR 0x80 + +/* Chip I.D. and Revision Register (Address 01h) */ +#define CS42XX8_CHIPID_CHIP_ID_MASK 0xF0 +#define CS42XX8_CHIPID_REV_ID_MASK 0x0F + +/* Power Control (Address 02h) */ +#define CS42XX8_PWRCTL_PDN_ADC3_SHIFT 7 +#define CS42XX8_PWRCTL_PDN_ADC3_MASK (1 << CS42XX8_PWRCTL_PDN_ADC3_SHIFT) +#define CS42XX8_PWRCTL_PDN_ADC3 (1 << CS42XX8_PWRCTL_PDN_ADC3_SHIFT) +#define CS42XX8_PWRCTL_PDN_ADC2_SHIFT 6 +#define CS42XX8_PWRCTL_PDN_ADC2_MASK (1 << CS42XX8_PWRCTL_PDN_ADC2_SHIFT) +#define CS42XX8_PWRCTL_PDN_ADC2 (1 << CS42XX8_PWRCTL_PDN_ADC2_SHIFT) +#define CS42XX8_PWRCTL_PDN_ADC1_SHIFT 5 +#define CS42XX8_PWRCTL_PDN_ADC1_MASK (1 << CS42XX8_PWRCTL_PDN_ADC1_SHIFT) +#define CS42XX8_PWRCTL_PDN_ADC1 (1 << CS42XX8_PWRCTL_PDN_ADC1_SHIFT) +#define CS42XX8_PWRCTL_PDN_DAC4_SHIFT 4 +#define CS42XX8_PWRCTL_PDN_DAC4_MASK (1 << CS42XX8_PWRCTL_PDN_DAC4_SHIFT) +#define CS42XX8_PWRCTL_PDN_DAC4 (1 << CS42XX8_PWRCTL_PDN_DAC4_SHIFT) +#define CS42XX8_PWRCTL_PDN_DAC3_SHIFT 3 +#define CS42XX8_PWRCTL_PDN_DAC3_MASK (1 << CS42XX8_PWRCTL_PDN_DAC3_SHIFT) +#define CS42XX8_PWRCTL_PDN_DAC3 (1 << CS42XX8_PWRCTL_PDN_DAC3_SHIFT) +#define CS42XX8_PWRCTL_PDN_DAC2_SHIFT 2 +#define CS42XX8_PWRCTL_PDN_DAC2_MASK (1 << CS42XX8_PWRCTL_PDN_DAC2_SHIFT) +#define CS42XX8_PWRCTL_PDN_DAC2 (1 << CS42XX8_PWRCTL_PDN_DAC2_SHIFT) +#define CS42XX8_PWRCTL_PDN_DAC1_SHIFT 1 +#define CS42XX8_PWRCTL_PDN_DAC1_MASK (1 << CS42XX8_PWRCTL_PDN_DAC1_SHIFT) +#define CS42XX8_PWRCTL_PDN_DAC1 (1 << CS42XX8_PWRCTL_PDN_DAC1_SHIFT) +#define CS42XX8_PWRCTL_PDN_SHIFT 0 +#define CS42XX8_PWRCTL_PDN_MASK (1 << CS42XX8_PWRCTL_PDN_SHIFT) +#define CS42XX8_PWRCTL_PDN (1 << CS42XX8_PWRCTL_PDN_SHIFT) + +/* Functional Mode (Address 03h) */ +#define CS42XX8_FUNCMOD_DAC_FM_SHIFT 6 +#define CS42XX8_FUNCMOD_DAC_FM_WIDTH 2 +#define CS42XX8_FUNCMOD_DAC_FM_MASK (((1 << CS42XX8_FUNCMOD_DAC_FM_WIDTH) - 1) << CS42XX8_FUNCMOD_DAC_FM_SHIFT) +#define CS42XX8_FUNCMOD_DAC_FM(v) ((v) << CS42XX8_FUNCMOD_DAC_FM_SHIFT) +#define CS42XX8_FUNCMOD_ADC_FM_SHIFT 4 +#define CS42XX8_FUNCMOD_ADC_FM_WIDTH 2 +#define CS42XX8_FUNCMOD_ADC_FM_MASK (((1 << CS42XX8_FUNCMOD_ADC_FM_WIDTH) - 1) << CS42XX8_FUNCMOD_ADC_FM_SHIFT) +#define CS42XX8_FUNCMOD_ADC_FM(v) ((v) << CS42XX8_FUNCMOD_ADC_FM_SHIFT) +#define CS42XX8_FUNCMOD_xC_FM_MASK(x) ((x) ? CS42XX8_FUNCMOD_DAC_FM_MASK : CS42XX8_FUNCMOD_ADC_FM_MASK) +#define CS42XX8_FUNCMOD_xC_FM(x, v) ((x) ? CS42XX8_FUNCMOD_DAC_FM(v) : CS42XX8_FUNCMOD_ADC_FM(v)) +#define CS42XX8_FUNCMOD_MFREQ_SHIFT 1 +#define CS42XX8_FUNCMOD_MFREQ_WIDTH 3 +#define CS42XX8_FUNCMOD_MFREQ_MASK (((1 << CS42XX8_FUNCMOD_MFREQ_WIDTH) - 1) << CS42XX8_FUNCMOD_MFREQ_SHIFT) +#define CS42XX8_FUNCMOD_MFREQ_256(s) ((0 << CS42XX8_FUNCMOD_MFREQ_SHIFT) >> (s >> 1)) +#define CS42XX8_FUNCMOD_MFREQ_384(s) ((1 << CS42XX8_FUNCMOD_MFREQ_SHIFT) >> (s >> 1)) +#define CS42XX8_FUNCMOD_MFREQ_512(s) ((2 << CS42XX8_FUNCMOD_MFREQ_SHIFT) >> (s >> 1)) +#define CS42XX8_FUNCMOD_MFREQ_768(s) ((3 << CS42XX8_FUNCMOD_MFREQ_SHIFT) >> (s >> 1)) +#define CS42XX8_FUNCMOD_MFREQ_1024(s) ((4 << CS42XX8_FUNCMOD_MFREQ_SHIFT) >> (s >> 1)) + +#define CS42XX8_FM_SINGLE 0 +#define CS42XX8_FM_DOUBLE 1 +#define CS42XX8_FM_QUAD 2 +#define CS42XX8_FM_AUTO 3 + +/* Interface Formats (Address 04h) */ +#define CS42XX8_INTF_FREEZE_SHIFT 7 +#define CS42XX8_INTF_FREEZE_MASK (1 << CS42XX8_INTF_FREEZE_SHIFT) +#define CS42XX8_INTF_FREEZE (1 << CS42XX8_INTF_FREEZE_SHIFT) +#define CS42XX8_INTF_AUX_DIF_SHIFT 6 +#define CS42XX8_INTF_AUX_DIF_MASK (1 << CS42XX8_INTF_AUX_DIF_SHIFT) +#define CS42XX8_INTF_AUX_DIF (1 << CS42XX8_INTF_AUX_DIF_SHIFT) +#define CS42XX8_INTF_DAC_DIF_SHIFT 3 +#define CS42XX8_INTF_DAC_DIF_WIDTH 3 +#define CS42XX8_INTF_DAC_DIF_MASK (((1 << CS42XX8_INTF_DAC_DIF_WIDTH) - 1) << CS42XX8_INTF_DAC_DIF_SHIFT) +#define CS42XX8_INTF_DAC_DIF_LEFTJ (0 << CS42XX8_INTF_DAC_DIF_SHIFT) +#define CS42XX8_INTF_DAC_DIF_I2S (1 << CS42XX8_INTF_DAC_DIF_SHIFT) +#define CS42XX8_INTF_DAC_DIF_RIGHTJ (2 << CS42XX8_INTF_DAC_DIF_SHIFT) +#define CS42XX8_INTF_DAC_DIF_RIGHTJ_16 (3 << CS42XX8_INTF_DAC_DIF_SHIFT) +#define CS42XX8_INTF_DAC_DIF_ONELINE_20 (4 << CS42XX8_INTF_DAC_DIF_SHIFT) +#define CS42XX8_INTF_DAC_DIF_ONELINE_24 (6 << CS42XX8_INTF_DAC_DIF_SHIFT) +#define CS42XX8_INTF_DAC_DIF_TDM (7 << CS42XX8_INTF_DAC_DIF_SHIFT) +#define CS42XX8_INTF_ADC_DIF_SHIFT 0 +#define CS42XX8_INTF_ADC_DIF_WIDTH 3 +#define CS42XX8_INTF_ADC_DIF_MASK (((1 << CS42XX8_INTF_ADC_DIF_WIDTH) - 1) << CS42XX8_INTF_ADC_DIF_SHIFT) +#define CS42XX8_INTF_ADC_DIF_LEFTJ (0 << CS42XX8_INTF_ADC_DIF_SHIFT) +#define CS42XX8_INTF_ADC_DIF_I2S (1 << CS42XX8_INTF_ADC_DIF_SHIFT) +#define CS42XX8_INTF_ADC_DIF_RIGHTJ (2 << CS42XX8_INTF_ADC_DIF_SHIFT) +#define CS42XX8_INTF_ADC_DIF_RIGHTJ_16 (3 << CS42XX8_INTF_ADC_DIF_SHIFT) +#define CS42XX8_INTF_ADC_DIF_ONELINE_20 (4 << CS42XX8_INTF_ADC_DIF_SHIFT) +#define CS42XX8_INTF_ADC_DIF_ONELINE_24 (6 << CS42XX8_INTF_ADC_DIF_SHIFT) +#define CS42XX8_INTF_ADC_DIF_TDM (7 << CS42XX8_INTF_ADC_DIF_SHIFT) + +/* ADC Control & DAC De-Emphasis (Address 05h) */ +#define CS42XX8_ADCCTL_ADC_HPF_FREEZE_SHIFT 7 +#define CS42XX8_ADCCTL_ADC_HPF_FREEZE_MASK (1 << CS42XX8_ADCCTL_ADC_HPF_FREEZE_SHIFT) +#define CS42XX8_ADCCTL_ADC_HPF_FREEZE (1 << CS42XX8_ADCCTL_ADC_HPF_FREEZE_SHIFT) +#define CS42XX8_ADCCTL_DAC_DEM_SHIFT 5 +#define CS42XX8_ADCCTL_DAC_DEM_MASK (1 << CS42XX8_ADCCTL_DAC_DEM_SHIFT) +#define CS42XX8_ADCCTL_DAC_DEM (1 << CS42XX8_ADCCTL_DAC_DEM_SHIFT) +#define CS42XX8_ADCCTL_ADC1_SINGLE_SHIFT 4 +#define CS42XX8_ADCCTL_ADC1_SINGLE_MASK (1 << CS42XX8_ADCCTL_ADC1_SINGLE_SHIFT) +#define CS42XX8_ADCCTL_ADC1_SINGLE (1 << CS42XX8_ADCCTL_ADC1_SINGLE_SHIFT) +#define CS42XX8_ADCCTL_ADC2_SINGLE_SHIFT 3 +#define CS42XX8_ADCCTL_ADC2_SINGLE_MASK (1 << CS42XX8_ADCCTL_ADC2_SINGLE_SHIFT) +#define CS42XX8_ADCCTL_ADC2_SINGLE (1 << CS42XX8_ADCCTL_ADC2_SINGLE_SHIFT) +#define CS42XX8_ADCCTL_ADC3_SINGLE_SHIFT 2 +#define CS42XX8_ADCCTL_ADC3_SINGLE_MASK (1 << CS42XX8_ADCCTL_ADC3_SINGLE_SHIFT) +#define CS42XX8_ADCCTL_ADC3_SINGLE (1 << CS42XX8_ADCCTL_ADC3_SINGLE_SHIFT) +#define CS42XX8_ADCCTL_AIN5_MUX_SHIFT 1 +#define CS42XX8_ADCCTL_AIN5_MUX_MASK (1 << CS42XX8_ADCCTL_AIN5_MUX_SHIFT) +#define CS42XX8_ADCCTL_AIN5_MUX (1 << CS42XX8_ADCCTL_AIN5_MUX_SHIFT) +#define CS42XX8_ADCCTL_AIN6_MUX_SHIFT 0 +#define CS42XX8_ADCCTL_AIN6_MUX_MASK (1 << CS42XX8_ADCCTL_AIN6_MUX_SHIFT) +#define CS42XX8_ADCCTL_AIN6_MUX (1 << CS42XX8_ADCCTL_AIN6_MUX_SHIFT) + +/* Transition Control (Address 06h) */ +#define CS42XX8_TXCTL_DAC_SNGVOL_SHIFT 7 +#define CS42XX8_TXCTL_DAC_SNGVOL_MASK (1 << CS42XX8_TXCTL_DAC_SNGVOL_SHIFT) +#define CS42XX8_TXCTL_DAC_SNGVOL (1 << CS42XX8_TXCTL_DAC_SNGVOL_SHIFT) +#define CS42XX8_TXCTL_DAC_SZC_SHIFT 5 +#define CS42XX8_TXCTL_DAC_SZC_WIDTH 2 +#define CS42XX8_TXCTL_DAC_SZC_MASK (((1 << CS42XX8_TXCTL_DAC_SZC_WIDTH) - 1) << CS42XX8_TXCTL_DAC_SZC_SHIFT) +#define CS42XX8_TXCTL_DAC_SZC_IC (0 << CS42XX8_TXCTL_DAC_SZC_SHIFT) +#define CS42XX8_TXCTL_DAC_SZC_ZC (1 << CS42XX8_TXCTL_DAC_SZC_SHIFT) +#define CS42XX8_TXCTL_DAC_SZC_SR (2 << CS42XX8_TXCTL_DAC_SZC_SHIFT) +#define CS42XX8_TXCTL_DAC_SZC_SRZC (3 << CS42XX8_TXCTL_DAC_SZC_SHIFT) +#define CS42XX8_TXCTL_AMUTE_SHIFT 4 +#define CS42XX8_TXCTL_AMUTE_MASK (1 << CS42XX8_TXCTL_AMUTE_SHIFT) +#define CS42XX8_TXCTL_AMUTE (1 << CS42XX8_TXCTL_AMUTE_SHIFT) +#define CS42XX8_TXCTL_MUTE_ADC_SP_SHIFT 3 +#define CS42XX8_TXCTL_MUTE_ADC_SP_MASK (1 << CS42XX8_TXCTL_MUTE_ADC_SP_SHIFT) +#define CS42XX8_TXCTL_MUTE_ADC_SP (1 << CS42XX8_TXCTL_MUTE_ADC_SP_SHIFT) +#define CS42XX8_TXCTL_ADC_SNGVOL_SHIFT 2 +#define CS42XX8_TXCTL_ADC_SNGVOL_MASK (1 << CS42XX8_TXCTL_ADC_SNGVOL_SHIFT) +#define CS42XX8_TXCTL_ADC_SNGVOL (1 << CS42XX8_TXCTL_ADC_SNGVOL_SHIFT) +#define CS42XX8_TXCTL_ADC_SZC_SHIFT 0 +#define CS42XX8_TXCTL_ADC_SZC_MASK (((1 << CS42XX8_TXCTL_ADC_SZC_WIDTH) - 1) << CS42XX8_TXCTL_ADC_SZC_SHIFT) +#define CS42XX8_TXCTL_ADC_SZC_IC (0 << CS42XX8_TXCTL_ADC_SZC_SHIFT) +#define CS42XX8_TXCTL_ADC_SZC_ZC (1 << CS42XX8_TXCTL_ADC_SZC_SHIFT) +#define CS42XX8_TXCTL_ADC_SZC_SR (2 << CS42XX8_TXCTL_ADC_SZC_SHIFT) +#define CS42XX8_TXCTL_ADC_SZC_SRZC (3 << CS42XX8_TXCTL_ADC_SZC_SHIFT) + +/* DAC Channel Mute (Address 07h) */ +#define CS42XX8_DACMUTE_AOUT(n) (0x1 << n) +#define CS42XX8_DACMUTE_ALL 0xff + +/* Status Control (Address 18h)*/ +#define CS42XX8_STATUSCTL_INI_SHIFT 2 +#define CS42XX8_STATUSCTL_INI_WIDTH 2 +#define CS42XX8_STATUSCTL_INI_MASK (((1 << CS42XX8_STATUSCTL_INI_WIDTH) - 1) << CS42XX8_STATUSCTL_INI_SHIFT) +#define CS42XX8_STATUSCTL_INT_ACTIVE_HIGH (0 << CS42XX8_STATUSCTL_INI_SHIFT) +#define CS42XX8_STATUSCTL_INT_ACTIVE_LOW (1 << CS42XX8_STATUSCTL_INI_SHIFT) +#define CS42XX8_STATUSCTL_INT_OPEN_DRAIN (2 << CS42XX8_STATUSCTL_INI_SHIFT) + +/* Status (Address 19h)*/ +#define CS42XX8_STATUS_DAC_CLK_ERR_SHIFT 4 +#define CS42XX8_STATUS_DAC_CLK_ERR_MASK (1 << CS42XX8_STATUS_DAC_CLK_ERR_SHIFT) +#define CS42XX8_STATUS_ADC_CLK_ERR_SHIFT 3 +#define CS42XX8_STATUS_ADC_CLK_ERR_MASK (1 << CS42XX8_STATUS_ADC_CLK_ERR_SHIFT) +#define CS42XX8_STATUS_ADC3_OVFL_SHIFT 2 +#define CS42XX8_STATUS_ADC3_OVFL_MASK (1 << CS42XX8_STATUS_ADC3_OVFL_SHIFT) +#define CS42XX8_STATUS_ADC2_OVFL_SHIFT 1 +#define CS42XX8_STATUS_ADC2_OVFL_MASK (1 << CS42XX8_STATUS_ADC2_OVFL_SHIFT) +#define CS42XX8_STATUS_ADC1_OVFL_SHIFT 0 +#define CS42XX8_STATUS_ADC1_OVFL_MASK (1 << CS42XX8_STATUS_ADC1_OVFL_SHIFT) + +/* Status Mask (Address 1Ah) */ +#define CS42XX8_STATUS_DAC_CLK_ERR_M_SHIFT 4 +#define CS42XX8_STATUS_DAC_CLK_ERR_M_MASK (1 << CS42XX8_STATUS_DAC_CLK_ERR_M_SHIFT) +#define CS42XX8_STATUS_ADC_CLK_ERR_M_SHIFT 3 +#define CS42XX8_STATUS_ADC_CLK_ERR_M_MASK (1 << CS42XX8_STATUS_ADC_CLK_ERR_M_SHIFT) +#define CS42XX8_STATUS_ADC3_OVFL_M_SHIFT 2 +#define CS42XX8_STATUS_ADC3_OVFL_M_MASK (1 << CS42XX8_STATUS_ADC3_OVFL_M_SHIFT) +#define CS42XX8_STATUS_ADC2_OVFL_M_SHIFT 1 +#define CS42XX8_STATUS_ADC2_OVFL_M_MASK (1 << CS42XX8_STATUS_ADC2_OVFL_M_SHIFT) +#define CS42XX8_STATUS_ADC1_OVFL_M_SHIFT 0 +#define CS42XX8_STATUS_ADC1_OVFL_M_MASK (1 << CS42XX8_STATUS_ADC1_OVFL_M_SHIFT) + +/* MUTEC Pin Control (Address 1Bh) */ +#define CS42XX8_MUTEC_MCPOLARITY_SHIFT 1 +#define CS42XX8_MUTEC_MCPOLARITY_MASK (1 << CS42XX8_MUTEC_MCPOLARITY_SHIFT) +#define CS42XX8_MUTEC_MCPOLARITY_ACTIVE_LOW (0 << CS42XX8_MUTEC_MCPOLARITY_SHIFT) +#define CS42XX8_MUTEC_MCPOLARITY_ACTIVE_HIGH (1 << CS42XX8_MUTEC_MCPOLARITY_SHIFT) +#define CS42XX8_MUTEC_MUTEC_ACTIVE_SHIFT 0 +#define CS42XX8_MUTEC_MUTEC_ACTIVE_MASK (1 << CS42XX8_MUTEC_MUTEC_ACTIVE_SHIFT) +#define CS42XX8_MUTEC_MUTEC_ACTIVE (1 << CS42XX8_MUTEC_MUTEC_ACTIVE_SHIFT) +#endif /* _CS42XX8_H */ diff --git a/sound/soc/codecs/da7210.c b/sound/soc/codecs/da7210.c index e62e294a803..137e8ebc092 100644 --- a/sound/soc/codecs/da7210.c +++ b/sound/soc/codecs/da7210.c @@ -307,29 +307,29 @@ static const char * const da7210_hpf_cutoff_txt[] = { "Fs/8192*pi", "Fs/4096*pi", "Fs/2048*pi", "Fs/1024*pi" }; -static const struct soc_enum da7210_dac_hpf_cutoff = - SOC_ENUM_SINGLE(DA7210_DAC_HPF, 0, 4, da7210_hpf_cutoff_txt); +static SOC_ENUM_SINGLE_DECL(da7210_dac_hpf_cutoff, + DA7210_DAC_HPF, 0, da7210_hpf_cutoff_txt); -static const struct soc_enum da7210_adc_hpf_cutoff = - SOC_ENUM_SINGLE(DA7210_ADC_HPF, 0, 4, da7210_hpf_cutoff_txt); +static SOC_ENUM_SINGLE_DECL(da7210_adc_hpf_cutoff, + DA7210_ADC_HPF, 0, da7210_hpf_cutoff_txt); /* ADC and DAC voice (8kHz) high pass cutoff value */ static const char * const da7210_vf_cutoff_txt[] = { "2.5Hz", "25Hz", "50Hz", "100Hz", "150Hz", "200Hz", "300Hz", "400Hz" }; -static const struct soc_enum da7210_dac_vf_cutoff = - SOC_ENUM_SINGLE(DA7210_DAC_HPF, 4, 8, da7210_vf_cutoff_txt); +static SOC_ENUM_SINGLE_DECL(da7210_dac_vf_cutoff, + DA7210_DAC_HPF, 4, da7210_vf_cutoff_txt); -static const struct soc_enum da7210_adc_vf_cutoff = - SOC_ENUM_SINGLE(DA7210_ADC_HPF, 4, 8, da7210_vf_cutoff_txt); +static SOC_ENUM_SINGLE_DECL(da7210_adc_vf_cutoff, + DA7210_ADC_HPF, 4, da7210_vf_cutoff_txt); static const char *da7210_hp_mode_txt[] = { "Class H", "Class G" }; -static const struct soc_enum da7210_hp_mode_sel = - SOC_ENUM_SINGLE(DA7210_HP_CFG, 0, 2, da7210_hp_mode_txt); +static SOC_ENUM_SINGLE_DECL(da7210_hp_mode_sel, + DA7210_HP_CFG, 0, da7210_hp_mode_txt); /* ALC can be enabled only if noise suppression is disabled */ static int da7210_put_alc_sw(struct snd_kcontrol *kcontrol, @@ -1071,17 +1071,9 @@ static struct snd_soc_dai_driver da7210_dai = { static int da7210_probe(struct snd_soc_codec *codec) { struct da7210_priv *da7210 = snd_soc_codec_get_drvdata(codec); - int ret; dev_info(codec->dev, "DA7210 Audio Codec %s\n", DA7210_VERSION); - codec->control_data = da7210->regmap; - ret = snd_soc_codec_set_cache_io(codec, 8, 8, SND_SOC_REGMAP); - if (ret < 0) { - dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); - return ret; - } - da7210->mclk_rate = 0; /* This will be set from set_sysclk() */ da7210->master = 0; /* This will be set from set_fmt() */ diff --git a/sound/soc/codecs/da7213.c b/sound/soc/codecs/da7213.c index 0c77e7ad742..738fa18a50d 100644 --- a/sound/soc/codecs/da7213.c +++ b/sound/soc/codecs/da7213.c @@ -63,30 +63,30 @@ static const char * const da7213_voice_hpf_corner_txt[] = { "2.5Hz", "25Hz", "50Hz", "100Hz", "150Hz", "200Hz", "300Hz", "400Hz" }; -static const struct soc_enum da7213_dac_voice_hpf_corner = - SOC_ENUM_SINGLE(DA7213_DAC_FILTERS1, DA7213_VOICE_HPF_CORNER_SHIFT, - DA7213_VOICE_HPF_CORNER_MAX, - da7213_voice_hpf_corner_txt); +static SOC_ENUM_SINGLE_DECL(da7213_dac_voice_hpf_corner, + DA7213_DAC_FILTERS1, + DA7213_VOICE_HPF_CORNER_SHIFT, + da7213_voice_hpf_corner_txt); -static const struct soc_enum da7213_adc_voice_hpf_corner = - SOC_ENUM_SINGLE(DA7213_ADC_FILTERS1, DA7213_VOICE_HPF_CORNER_SHIFT, - DA7213_VOICE_HPF_CORNER_MAX, - da7213_voice_hpf_corner_txt); +static SOC_ENUM_SINGLE_DECL(da7213_adc_voice_hpf_corner, + DA7213_ADC_FILTERS1, + DA7213_VOICE_HPF_CORNER_SHIFT, + da7213_voice_hpf_corner_txt); /* ADC and DAC high pass filter cutoff value */ static const char * const da7213_audio_hpf_corner_txt[] = { "Fs/24000", "Fs/12000", "Fs/6000", "Fs/3000" }; -static const struct soc_enum da7213_dac_audio_hpf_corner = - SOC_ENUM_SINGLE(DA7213_DAC_FILTERS1, DA7213_AUDIO_HPF_CORNER_SHIFT, - DA7213_AUDIO_HPF_CORNER_MAX, - da7213_audio_hpf_corner_txt); +static SOC_ENUM_SINGLE_DECL(da7213_dac_audio_hpf_corner, + DA7213_DAC_FILTERS1 + , DA7213_AUDIO_HPF_CORNER_SHIFT, + da7213_audio_hpf_corner_txt); -static const struct soc_enum da7213_adc_audio_hpf_corner = - SOC_ENUM_SINGLE(DA7213_ADC_FILTERS1, DA7213_AUDIO_HPF_CORNER_SHIFT, - DA7213_AUDIO_HPF_CORNER_MAX, - da7213_audio_hpf_corner_txt); +static SOC_ENUM_SINGLE_DECL(da7213_adc_audio_hpf_corner, + DA7213_ADC_FILTERS1, + DA7213_AUDIO_HPF_CORNER_SHIFT, + da7213_audio_hpf_corner_txt); /* Gain ramping rate value */ static const char * const da7213_gain_ramp_rate_txt[] = { @@ -94,52 +94,50 @@ static const char * const da7213_gain_ramp_rate_txt[] = { "nominal rate / 32" }; -static const struct soc_enum da7213_gain_ramp_rate = - SOC_ENUM_SINGLE(DA7213_GAIN_RAMP_CTRL, DA7213_GAIN_RAMP_RATE_SHIFT, - DA7213_GAIN_RAMP_RATE_MAX, da7213_gain_ramp_rate_txt); +static SOC_ENUM_SINGLE_DECL(da7213_gain_ramp_rate, + DA7213_GAIN_RAMP_CTRL, + DA7213_GAIN_RAMP_RATE_SHIFT, + da7213_gain_ramp_rate_txt); /* DAC noise gate setup time value */ static const char * const da7213_dac_ng_setup_time_txt[] = { "256 samples", "512 samples", "1024 samples", "2048 samples" }; -static const struct soc_enum da7213_dac_ng_setup_time = - SOC_ENUM_SINGLE(DA7213_DAC_NG_SETUP_TIME, - DA7213_DAC_NG_SETUP_TIME_SHIFT, - DA7213_DAC_NG_SETUP_TIME_MAX, - da7213_dac_ng_setup_time_txt); +static SOC_ENUM_SINGLE_DECL(da7213_dac_ng_setup_time, + DA7213_DAC_NG_SETUP_TIME, + DA7213_DAC_NG_SETUP_TIME_SHIFT, + da7213_dac_ng_setup_time_txt); /* DAC noise gate rampup rate value */ static const char * const da7213_dac_ng_rampup_txt[] = { "0.02 ms/dB", "0.16 ms/dB" }; -static const struct soc_enum da7213_dac_ng_rampup_rate = - SOC_ENUM_SINGLE(DA7213_DAC_NG_SETUP_TIME, - DA7213_DAC_NG_RAMPUP_RATE_SHIFT, - DA7213_DAC_NG_RAMP_RATE_MAX, - da7213_dac_ng_rampup_txt); +static SOC_ENUM_SINGLE_DECL(da7213_dac_ng_rampup_rate, + DA7213_DAC_NG_SETUP_TIME, + DA7213_DAC_NG_RAMPUP_RATE_SHIFT, + da7213_dac_ng_rampup_txt); /* DAC noise gate rampdown rate value */ static const char * const da7213_dac_ng_rampdown_txt[] = { "0.64 ms/dB", "20.48 ms/dB" }; -static const struct soc_enum da7213_dac_ng_rampdown_rate = - SOC_ENUM_SINGLE(DA7213_DAC_NG_SETUP_TIME, - DA7213_DAC_NG_RAMPDN_RATE_SHIFT, - DA7213_DAC_NG_RAMP_RATE_MAX, - da7213_dac_ng_rampdown_txt); +static SOC_ENUM_SINGLE_DECL(da7213_dac_ng_rampdown_rate, + DA7213_DAC_NG_SETUP_TIME, + DA7213_DAC_NG_RAMPDN_RATE_SHIFT, + da7213_dac_ng_rampdown_txt); /* DAC soft mute rate value */ static const char * const da7213_dac_soft_mute_rate_txt[] = { "1", "2", "4", "8", "16", "32", "64" }; -static const struct soc_enum da7213_dac_soft_mute_rate = - SOC_ENUM_SINGLE(DA7213_DAC_FILTERS5, DA7213_DAC_SOFTMUTE_RATE_SHIFT, - DA7213_DAC_SOFTMUTE_RATE_MAX, - da7213_dac_soft_mute_rate_txt); +static SOC_ENUM_SINGLE_DECL(da7213_dac_soft_mute_rate, + DA7213_DAC_FILTERS5, + DA7213_DAC_SOFTMUTE_RATE_SHIFT, + da7213_dac_soft_mute_rate_txt); /* ALC Attack Rate select */ static const char * const da7213_alc_attack_rate_txt[] = { @@ -147,9 +145,10 @@ static const char * const da7213_alc_attack_rate_txt[] = { "5632/fs", "11264/fs", "22528/fs", "45056/fs", "90112/fs", "180224/fs" }; -static const struct soc_enum da7213_alc_attack_rate = - SOC_ENUM_SINGLE(DA7213_ALC_CTRL2, DA7213_ALC_ATTACK_SHIFT, - DA7213_ALC_ATTACK_MAX, da7213_alc_attack_rate_txt); +static SOC_ENUM_SINGLE_DECL(da7213_alc_attack_rate, + DA7213_ALC_CTRL2, + DA7213_ALC_ATTACK_SHIFT, + da7213_alc_attack_rate_txt); /* ALC Release Rate select */ static const char * const da7213_alc_release_rate_txt[] = { @@ -157,9 +156,10 @@ static const char * const da7213_alc_release_rate_txt[] = { "11264/fs", "22528/fs", "45056/fs", "90112/fs", "180224/fs" }; -static const struct soc_enum da7213_alc_release_rate = - SOC_ENUM_SINGLE(DA7213_ALC_CTRL2, DA7213_ALC_RELEASE_SHIFT, - DA7213_ALC_RELEASE_MAX, da7213_alc_release_rate_txt); +static SOC_ENUM_SINGLE_DECL(da7213_alc_release_rate, + DA7213_ALC_CTRL2, + DA7213_ALC_RELEASE_SHIFT, + da7213_alc_release_rate_txt); /* ALC Hold Time select */ static const char * const da7213_alc_hold_time_txt[] = { @@ -168,22 +168,25 @@ static const char * const da7213_alc_hold_time_txt[] = { "253952/fs", "507904/fs", "1015808/fs", "2031616/fs" }; -static const struct soc_enum da7213_alc_hold_time = - SOC_ENUM_SINGLE(DA7213_ALC_CTRL3, DA7213_ALC_HOLD_SHIFT, - DA7213_ALC_HOLD_MAX, da7213_alc_hold_time_txt); +static SOC_ENUM_SINGLE_DECL(da7213_alc_hold_time, + DA7213_ALC_CTRL3, + DA7213_ALC_HOLD_SHIFT, + da7213_alc_hold_time_txt); /* ALC Input Signal Tracking rate select */ static const char * const da7213_alc_integ_rate_txt[] = { "1/4", "1/16", "1/256", "1/65536" }; -static const struct soc_enum da7213_alc_integ_attack_rate = - SOC_ENUM_SINGLE(DA7213_ALC_CTRL3, DA7213_ALC_INTEG_ATTACK_SHIFT, - DA7213_ALC_INTEG_MAX, da7213_alc_integ_rate_txt); +static SOC_ENUM_SINGLE_DECL(da7213_alc_integ_attack_rate, + DA7213_ALC_CTRL3, + DA7213_ALC_INTEG_ATTACK_SHIFT, + da7213_alc_integ_rate_txt); -static const struct soc_enum da7213_alc_integ_release_rate = - SOC_ENUM_SINGLE(DA7213_ALC_CTRL3, DA7213_ALC_INTEG_RELEASE_SHIFT, - DA7213_ALC_INTEG_MAX, da7213_alc_integ_rate_txt); +static SOC_ENUM_SINGLE_DECL(da7213_alc_integ_release_rate, + DA7213_ALC_CTRL3, + DA7213_ALC_INTEG_RELEASE_SHIFT, + da7213_alc_integ_rate_txt); /* @@ -584,15 +587,17 @@ static const char * const da7213_mic_amp_in_sel_txt[] = { "Differential", "MIC_P", "MIC_N" }; -static const struct soc_enum da7213_mic_1_amp_in_sel = - SOC_ENUM_SINGLE(DA7213_MIC_1_CTRL, DA7213_MIC_AMP_IN_SEL_SHIFT, - DA7213_MIC_AMP_IN_SEL_MAX, da7213_mic_amp_in_sel_txt); +static SOC_ENUM_SINGLE_DECL(da7213_mic_1_amp_in_sel, + DA7213_MIC_1_CTRL, + DA7213_MIC_AMP_IN_SEL_SHIFT, + da7213_mic_amp_in_sel_txt); static const struct snd_kcontrol_new da7213_mic_1_amp_in_sel_mux = SOC_DAPM_ENUM("Mic 1 Amp Source MUX", da7213_mic_1_amp_in_sel); -static const struct soc_enum da7213_mic_2_amp_in_sel = - SOC_ENUM_SINGLE(DA7213_MIC_2_CTRL, DA7213_MIC_AMP_IN_SEL_SHIFT, - DA7213_MIC_AMP_IN_SEL_MAX, da7213_mic_amp_in_sel_txt); +static SOC_ENUM_SINGLE_DECL(da7213_mic_2_amp_in_sel, + DA7213_MIC_2_CTRL, + DA7213_MIC_AMP_IN_SEL_SHIFT, + da7213_mic_amp_in_sel_txt); static const struct snd_kcontrol_new da7213_mic_2_amp_in_sel_mux = SOC_DAPM_ENUM("Mic 2 Amp Source MUX", da7213_mic_2_amp_in_sel); @@ -601,15 +606,17 @@ static const char * const da7213_dai_src_txt[] = { "ADC Left", "ADC Right", "DAI Input Left", "DAI Input Right" }; -static const struct soc_enum da7213_dai_l_src = - SOC_ENUM_SINGLE(DA7213_DIG_ROUTING_DAI, DA7213_DAI_L_SRC_SHIFT, - DA7213_DAI_SRC_MAX, da7213_dai_src_txt); +static SOC_ENUM_SINGLE_DECL(da7213_dai_l_src, + DA7213_DIG_ROUTING_DAI, + DA7213_DAI_L_SRC_SHIFT, + da7213_dai_src_txt); static const struct snd_kcontrol_new da7213_dai_l_src_mux = SOC_DAPM_ENUM("DAI Left Source MUX", da7213_dai_l_src); -static const struct soc_enum da7213_dai_r_src = - SOC_ENUM_SINGLE(DA7213_DIG_ROUTING_DAI, DA7213_DAI_R_SRC_SHIFT, - DA7213_DAI_SRC_MAX, da7213_dai_src_txt); +static SOC_ENUM_SINGLE_DECL(da7213_dai_r_src, + DA7213_DIG_ROUTING_DAI, + DA7213_DAI_R_SRC_SHIFT, + da7213_dai_src_txt); static const struct snd_kcontrol_new da7213_dai_r_src_mux = SOC_DAPM_ENUM("DAI Right Source MUX", da7213_dai_r_src); @@ -619,15 +626,17 @@ static const char * const da7213_dac_src_txt[] = { "DAI Input Right" }; -static const struct soc_enum da7213_dac_l_src = - SOC_ENUM_SINGLE(DA7213_DIG_ROUTING_DAC, DA7213_DAC_L_SRC_SHIFT, - DA7213_DAC_SRC_MAX, da7213_dac_src_txt); +static SOC_ENUM_SINGLE_DECL(da7213_dac_l_src, + DA7213_DIG_ROUTING_DAC, + DA7213_DAC_L_SRC_SHIFT, + da7213_dac_src_txt); static const struct snd_kcontrol_new da7213_dac_l_src_mux = SOC_DAPM_ENUM("DAC Left Source MUX", da7213_dac_l_src); -static const struct soc_enum da7213_dac_r_src = - SOC_ENUM_SINGLE(DA7213_DIG_ROUTING_DAC, DA7213_DAC_R_SRC_SHIFT, - DA7213_DAC_SRC_MAX, da7213_dac_src_txt); +static SOC_ENUM_SINGLE_DECL(da7213_dac_r_src, + DA7213_DIG_ROUTING_DAC, + DA7213_DAC_R_SRC_SHIFT, + da7213_dac_src_txt); static const struct snd_kcontrol_new da7213_dac_r_src_mux = SOC_DAPM_ENUM("DAC Right Source MUX", da7213_dac_r_src); @@ -1384,17 +1393,9 @@ static int da7213_set_bias_level(struct snd_soc_codec *codec, static int da7213_probe(struct snd_soc_codec *codec) { - int ret; struct da7213_priv *da7213 = snd_soc_codec_get_drvdata(codec); struct da7213_platform_data *pdata = da7213->pdata; - codec->control_data = da7213->regmap; - ret = snd_soc_codec_set_cache_io(codec, 8, 8, SND_SOC_REGMAP); - if (ret < 0) { - dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); - return ret; - } - /* Default to using ALC auto offset calibration mode. */ snd_soc_update_bits(codec, DA7213_ALC_CTRL1, DA7213_ALC_CALIB_MODE_MAN, 0); diff --git a/sound/soc/codecs/da732x.c b/sound/soc/codecs/da732x.c index f4d965ebc29..7d168ec71cd 100644 --- a/sound/soc/codecs/da732x.c +++ b/sound/soc/codecs/da732x.c @@ -269,81 +269,65 @@ static const char *da732x_hpf_voice[] = { "150Hz", "200Hz", "300Hz", "400Hz" }; -static const struct soc_enum da732x_dac1_hpf_mode_enum[] = { - SOC_ENUM_SINGLE(DA732X_REG_DAC1_HPF, DA732X_HPF_MODE_SHIFT, - DA732X_HPF_MODE_MAX, da732x_hpf_mode) -}; - -static const struct soc_enum da732x_dac2_hpf_mode_enum[] = { - SOC_ENUM_SINGLE(DA732X_REG_DAC2_HPF, DA732X_HPF_MODE_SHIFT, - DA732X_HPF_MODE_MAX, da732x_hpf_mode) -}; +static SOC_ENUM_SINGLE_DECL(da732x_dac1_hpf_mode_enum, + DA732X_REG_DAC1_HPF, DA732X_HPF_MODE_SHIFT, + da732x_hpf_mode); -static const struct soc_enum da732x_dac3_hpf_mode_enum[] = { - SOC_ENUM_SINGLE(DA732X_REG_DAC3_HPF, DA732X_HPF_MODE_SHIFT, - DA732X_HPF_MODE_MAX, da732x_hpf_mode) -}; +static SOC_ENUM_SINGLE_DECL(da732x_dac2_hpf_mode_enum, + DA732X_REG_DAC2_HPF, DA732X_HPF_MODE_SHIFT, + da732x_hpf_mode); -static const struct soc_enum da732x_adc1_hpf_mode_enum[] = { - SOC_ENUM_SINGLE(DA732X_REG_ADC1_HPF, DA732X_HPF_MODE_SHIFT, - DA732X_HPF_MODE_MAX, da732x_hpf_mode) -}; +static SOC_ENUM_SINGLE_DECL(da732x_dac3_hpf_mode_enum, + DA732X_REG_DAC3_HPF, DA732X_HPF_MODE_SHIFT, + da732x_hpf_mode); -static const struct soc_enum da732x_adc2_hpf_mode_enum[] = { - SOC_ENUM_SINGLE(DA732X_REG_ADC2_HPF, DA732X_HPF_MODE_SHIFT, - DA732X_HPF_MODE_MAX, da732x_hpf_mode) -}; +static SOC_ENUM_SINGLE_DECL(da732x_adc1_hpf_mode_enum, + DA732X_REG_ADC1_HPF, DA732X_HPF_MODE_SHIFT, + da732x_hpf_mode); -static const struct soc_enum da732x_dac1_hp_filter_enum[] = { - SOC_ENUM_SINGLE(DA732X_REG_DAC1_HPF, DA732X_HPF_MUSIC_SHIFT, - DA732X_HPF_MUSIC_MAX, da732x_hpf_music) -}; +static SOC_ENUM_SINGLE_DECL(da732x_adc2_hpf_mode_enum, + DA732X_REG_ADC2_HPF, DA732X_HPF_MODE_SHIFT, + da732x_hpf_mode); -static const struct soc_enum da732x_dac2_hp_filter_enum[] = { - SOC_ENUM_SINGLE(DA732X_REG_DAC2_HPF, DA732X_HPF_MUSIC_SHIFT, - DA732X_HPF_MUSIC_MAX, da732x_hpf_music) -}; +static SOC_ENUM_SINGLE_DECL(da732x_dac1_hp_filter_enum, + DA732X_REG_DAC1_HPF, DA732X_HPF_MUSIC_SHIFT, + da732x_hpf_music); -static const struct soc_enum da732x_dac3_hp_filter_enum[] = { - SOC_ENUM_SINGLE(DA732X_REG_DAC3_HPF, DA732X_HPF_MUSIC_SHIFT, - DA732X_HPF_MUSIC_MAX, da732x_hpf_music) -}; +static SOC_ENUM_SINGLE_DECL(da732x_dac2_hp_filter_enum, + DA732X_REG_DAC2_HPF, DA732X_HPF_MUSIC_SHIFT, + da732x_hpf_music); -static const struct soc_enum da732x_adc1_hp_filter_enum[] = { - SOC_ENUM_SINGLE(DA732X_REG_ADC1_HPF, DA732X_HPF_MUSIC_SHIFT, - DA732X_HPF_MUSIC_MAX, da732x_hpf_music) -}; +static SOC_ENUM_SINGLE_DECL(da732x_dac3_hp_filter_enum, + DA732X_REG_DAC3_HPF, DA732X_HPF_MUSIC_SHIFT, + da732x_hpf_music); -static const struct soc_enum da732x_adc2_hp_filter_enum[] = { - SOC_ENUM_SINGLE(DA732X_REG_ADC2_HPF, DA732X_HPF_MUSIC_SHIFT, - DA732X_HPF_MUSIC_MAX, da732x_hpf_music) -}; +static SOC_ENUM_SINGLE_DECL(da732x_adc1_hp_filter_enum, + DA732X_REG_ADC1_HPF, DA732X_HPF_MUSIC_SHIFT, + da732x_hpf_music); -static const struct soc_enum da732x_dac1_voice_filter_enum[] = { - SOC_ENUM_SINGLE(DA732X_REG_DAC1_HPF, DA732X_HPF_VOICE_SHIFT, - DA732X_HPF_VOICE_MAX, da732x_hpf_voice) -}; +static SOC_ENUM_SINGLE_DECL(da732x_adc2_hp_filter_enum, + DA732X_REG_ADC2_HPF, DA732X_HPF_MUSIC_SHIFT, + da732x_hpf_music); -static const struct soc_enum da732x_dac2_voice_filter_enum[] = { - SOC_ENUM_SINGLE(DA732X_REG_DAC2_HPF, DA732X_HPF_VOICE_SHIFT, - DA732X_HPF_VOICE_MAX, da732x_hpf_voice) -}; +static SOC_ENUM_SINGLE_DECL(da732x_dac1_voice_filter_enum, + DA732X_REG_DAC1_HPF, DA732X_HPF_VOICE_SHIFT, + da732x_hpf_voice); -static const struct soc_enum da732x_dac3_voice_filter_enum[] = { - SOC_ENUM_SINGLE(DA732X_REG_DAC3_HPF, DA732X_HPF_VOICE_SHIFT, - DA732X_HPF_VOICE_MAX, da732x_hpf_voice) -}; +static SOC_ENUM_SINGLE_DECL(da732x_dac2_voice_filter_enum, + DA732X_REG_DAC2_HPF, DA732X_HPF_VOICE_SHIFT, + da732x_hpf_voice); -static const struct soc_enum da732x_adc1_voice_filter_enum[] = { - SOC_ENUM_SINGLE(DA732X_REG_ADC1_HPF, DA732X_HPF_VOICE_SHIFT, - DA732X_HPF_VOICE_MAX, da732x_hpf_voice) -}; +static SOC_ENUM_SINGLE_DECL(da732x_dac3_voice_filter_enum, + DA732X_REG_DAC3_HPF, DA732X_HPF_VOICE_SHIFT, + da732x_hpf_voice); -static const struct soc_enum da732x_adc2_voice_filter_enum[] = { - SOC_ENUM_SINGLE(DA732X_REG_ADC2_HPF, DA732X_HPF_VOICE_SHIFT, - DA732X_HPF_VOICE_MAX, da732x_hpf_voice) -}; +static SOC_ENUM_SINGLE_DECL(da732x_adc1_voice_filter_enum, + DA732X_REG_ADC1_HPF, DA732X_HPF_VOICE_SHIFT, + da732x_hpf_voice); +static SOC_ENUM_SINGLE_DECL(da732x_adc2_voice_filter_enum, + DA732X_REG_ADC2_HPF, DA732X_HPF_VOICE_SHIFT, + da732x_hpf_voice); static int da732x_hpf_set(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) @@ -714,65 +698,65 @@ static const char *enable_text[] = { }; /* ADC1LMUX */ -static const struct soc_enum adc1l_enum = - SOC_ENUM_SINGLE(DA732X_REG_INP_MUX, DA732X_ADC1L_MUX_SEL_SHIFT, - DA732X_ADCL_MUX_MAX, adcl_text); +static SOC_ENUM_SINGLE_DECL(adc1l_enum, + DA732X_REG_INP_MUX, DA732X_ADC1L_MUX_SEL_SHIFT, + adcl_text); static const struct snd_kcontrol_new adc1l_mux = SOC_DAPM_ENUM("ADC Route", adc1l_enum); /* ADC1RMUX */ -static const struct soc_enum adc1r_enum = - SOC_ENUM_SINGLE(DA732X_REG_INP_MUX, DA732X_ADC1R_MUX_SEL_SHIFT, - DA732X_ADCR_MUX_MAX, adcr_text); +static SOC_ENUM_SINGLE_DECL(adc1r_enum, + DA732X_REG_INP_MUX, DA732X_ADC1R_MUX_SEL_SHIFT, + adcr_text); static const struct snd_kcontrol_new adc1r_mux = SOC_DAPM_ENUM("ADC Route", adc1r_enum); /* ADC2LMUX */ -static const struct soc_enum adc2l_enum = - SOC_ENUM_SINGLE(DA732X_REG_INP_MUX, DA732X_ADC2L_MUX_SEL_SHIFT, - DA732X_ADCL_MUX_MAX, adcl_text); +static SOC_ENUM_SINGLE_DECL(adc2l_enum, + DA732X_REG_INP_MUX, DA732X_ADC2L_MUX_SEL_SHIFT, + adcl_text); static const struct snd_kcontrol_new adc2l_mux = SOC_DAPM_ENUM("ADC Route", adc2l_enum); /* ADC2RMUX */ -static const struct soc_enum adc2r_enum = - SOC_ENUM_SINGLE(DA732X_REG_INP_MUX, DA732X_ADC2R_MUX_SEL_SHIFT, - DA732X_ADCR_MUX_MAX, adcr_text); +static SOC_ENUM_SINGLE_DECL(adc2r_enum, + DA732X_REG_INP_MUX, DA732X_ADC2R_MUX_SEL_SHIFT, + adcr_text); static const struct snd_kcontrol_new adc2r_mux = SOC_DAPM_ENUM("ADC Route", adc2r_enum); -static const struct soc_enum da732x_hp_left_output = - SOC_ENUM_SINGLE(DA732X_REG_HPL, DA732X_HP_OUT_DAC_EN_SHIFT, - DA732X_DAC_EN_MAX, enable_text); +static SOC_ENUM_SINGLE_DECL(da732x_hp_left_output, + DA732X_REG_HPL, DA732X_HP_OUT_DAC_EN_SHIFT, + enable_text); static const struct snd_kcontrol_new hpl_mux = SOC_DAPM_ENUM("HPL Switch", da732x_hp_left_output); -static const struct soc_enum da732x_hp_right_output = - SOC_ENUM_SINGLE(DA732X_REG_HPR, DA732X_HP_OUT_DAC_EN_SHIFT, - DA732X_DAC_EN_MAX, enable_text); +static SOC_ENUM_SINGLE_DECL(da732x_hp_right_output, + DA732X_REG_HPR, DA732X_HP_OUT_DAC_EN_SHIFT, + enable_text); static const struct snd_kcontrol_new hpr_mux = SOC_DAPM_ENUM("HPR Switch", da732x_hp_right_output); -static const struct soc_enum da732x_speaker_output = - SOC_ENUM_SINGLE(DA732X_REG_LIN3, DA732X_LOUT_DAC_EN_SHIFT, - DA732X_DAC_EN_MAX, enable_text); +static SOC_ENUM_SINGLE_DECL(da732x_speaker_output, + DA732X_REG_LIN3, DA732X_LOUT_DAC_EN_SHIFT, + enable_text); static const struct snd_kcontrol_new spk_mux = SOC_DAPM_ENUM("SPK Switch", da732x_speaker_output); -static const struct soc_enum da732x_lout4_output = - SOC_ENUM_SINGLE(DA732X_REG_LIN4, DA732X_LOUT_DAC_EN_SHIFT, - DA732X_DAC_EN_MAX, enable_text); +static SOC_ENUM_SINGLE_DECL(da732x_lout4_output, + DA732X_REG_LIN4, DA732X_LOUT_DAC_EN_SHIFT, + enable_text); static const struct snd_kcontrol_new lout4_mux = SOC_DAPM_ENUM("LOUT4 Switch", da732x_lout4_output); -static const struct soc_enum da732x_lout2_output = - SOC_ENUM_SINGLE(DA732X_REG_LIN2, DA732X_LOUT_DAC_EN_SHIFT, - DA732X_DAC_EN_MAX, enable_text); +static SOC_ENUM_SINGLE_DECL(da732x_lout2_output, + DA732X_REG_LIN2, DA732X_LOUT_DAC_EN_SHIFT, + enable_text); static const struct snd_kcontrol_new lout2_mux = SOC_DAPM_ENUM("LOUT2 Switch", da732x_lout2_output); @@ -1313,9 +1297,9 @@ static void da732x_dac_offset_adjust(struct snd_soc_codec *codec) msleep(DA732X_WAIT_FOR_STABILIZATION); /* Check DAC offset sign */ - sign[DA732X_HPL_DAC] = (codec->hw_read(codec, DA732X_REG_HPL_DAC_OFF_CNTL) & + sign[DA732X_HPL_DAC] = (snd_soc_read(codec, DA732X_REG_HPL_DAC_OFF_CNTL) & DA732X_HP_DAC_OFF_CNTL_COMPO); - sign[DA732X_HPR_DAC] = (codec->hw_read(codec, DA732X_REG_HPR_DAC_OFF_CNTL) & + sign[DA732X_HPR_DAC] = (snd_soc_read(codec, DA732X_REG_HPR_DAC_OFF_CNTL) & DA732X_HP_DAC_OFF_CNTL_COMPO); /* Binary search DAC offset values (both channels at once) */ @@ -1332,10 +1316,10 @@ static void da732x_dac_offset_adjust(struct snd_soc_codec *codec) msleep(DA732X_WAIT_FOR_STABILIZATION); - if ((codec->hw_read(codec, DA732X_REG_HPL_DAC_OFF_CNTL) & + if ((snd_soc_read(codec, DA732X_REG_HPL_DAC_OFF_CNTL) & DA732X_HP_DAC_OFF_CNTL_COMPO) ^ sign[DA732X_HPL_DAC]) offset[DA732X_HPL_DAC] &= ~step; - if ((codec->hw_read(codec, DA732X_REG_HPR_DAC_OFF_CNTL) & + if ((snd_soc_read(codec, DA732X_REG_HPR_DAC_OFF_CNTL) & DA732X_HP_DAC_OFF_CNTL_COMPO) ^ sign[DA732X_HPR_DAC]) offset[DA732X_HPR_DAC] &= ~step; @@ -1376,9 +1360,9 @@ static void da732x_output_offset_adjust(struct snd_soc_codec *codec) msleep(DA732X_WAIT_FOR_STABILIZATION); /* Check output offset sign */ - sign[DA732X_HPL_AMP] = codec->hw_read(codec, DA732X_REG_HPL) & + sign[DA732X_HPL_AMP] = snd_soc_read(codec, DA732X_REG_HPL) & DA732X_HP_OUT_COMPO; - sign[DA732X_HPR_AMP] = codec->hw_read(codec, DA732X_REG_HPR) & + sign[DA732X_HPR_AMP] = snd_soc_read(codec, DA732X_REG_HPR) & DA732X_HP_OUT_COMPO; snd_soc_write(codec, DA732X_REG_HPL, DA732X_HP_OUT_COMP | @@ -1399,10 +1383,10 @@ static void da732x_output_offset_adjust(struct snd_soc_codec *codec) msleep(DA732X_WAIT_FOR_STABILIZATION); - if ((codec->hw_read(codec, DA732X_REG_HPL) & + if ((snd_soc_read(codec, DA732X_REG_HPL) & DA732X_HP_OUT_COMPO) ^ sign[DA732X_HPL_AMP]) offset[DA732X_HPL_AMP] &= ~step; - if ((codec->hw_read(codec, DA732X_REG_HPR) & + if ((snd_soc_read(codec, DA732X_REG_HPR) & DA732X_HP_OUT_COMPO) ^ sign[DA732X_HPR_AMP]) offset[DA732X_HPR_AMP] &= ~step; @@ -1499,8 +1483,8 @@ static int da732x_set_bias_level(struct snd_soc_codec *codec, da732x_hp_dc_offset_cancellation(codec); - regcache_cache_only(codec->control_data, false); - regcache_sync(codec->control_data); + regcache_cache_only(da732x->regmap, false); + regcache_sync(da732x->regmap); } else { snd_soc_update_bits(codec, DA732X_REG_BIAS_EN, DA732X_BIAS_BOOST_MASK, @@ -1511,7 +1495,7 @@ static int da732x_set_bias_level(struct snd_soc_codec *codec, } break; case SND_SOC_BIAS_OFF: - regcache_cache_only(codec->control_data, true); + regcache_cache_only(da732x->regmap, true); da732x_set_charge_pump(codec, DA732X_DISABLE_CP); snd_soc_update_bits(codec, DA732X_REG_BIAS_EN, DA732X_BIAS_EN, DA732X_BIAS_DIS); @@ -1528,23 +1512,14 @@ static int da732x_probe(struct snd_soc_codec *codec) { struct da732x_priv *da732x = snd_soc_codec_get_drvdata(codec); struct snd_soc_dapm_context *dapm = &codec->dapm; - int ret = 0; da732x->codec = codec; dapm->idle_bias_off = false; - codec->control_data = da732x->regmap; - - ret = snd_soc_codec_set_cache_io(codec, 8, 8, SND_SOC_REGMAP); - if (ret != 0) { - dev_err(codec->dev, "Failed to register codec.\n"); - goto err; - } - da732x_set_bias_level(codec, SND_SOC_BIAS_STANDBY); -err: - return ret; + + return 0; } static int da732x_remove(struct snd_soc_codec *codec) @@ -1566,7 +1541,6 @@ static struct snd_soc_codec_driver soc_codec_dev_da732x = { .dapm_routes = da732x_dapm_routes, .num_dapm_routes = ARRAY_SIZE(da732x_dapm_routes), .set_pll = da732x_set_dai_pll, - .reg_cache_size = ARRAY_SIZE(da732x_reg_cache), }; static int da732x_i2c_probe(struct i2c_client *i2c, diff --git a/sound/soc/codecs/da732x.h b/sound/soc/codecs/da732x.h index c8ce5475de2..1dceafeec41 100644 --- a/sound/soc/codecs/da732x.h +++ b/sound/soc/codecs/da732x.h @@ -113,9 +113,6 @@ #define DA732X_EQ_OVERALL_VOL_DB_MIN -1800 #define DA732X_EQ_OVERALL_VOL_DB_INC 600 -#define DA732X_SOC_ENUM_DOUBLE_R(xreg, xrreg, xmax, xtext) \ - {.reg = xreg, .reg2 = xrreg, .max = xmax, .texts = xtext} - enum da732x_sysctl { DA732X_SR_8KHZ = 0x1, DA732X_SR_11_025KHZ = 0x2, diff --git a/sound/soc/codecs/da9055.c b/sound/soc/codecs/da9055.c index 422812613a2..4ff06b50fbb 100644 --- a/sound/soc/codecs/da9055.c +++ b/sound/soc/codecs/da9055.c @@ -18,6 +18,8 @@ #include <linux/regmap.h> #include <linux/slab.h> #include <linux/module.h> +#include <linux/of.h> +#include <linux/of_device.h> #include <sound/pcm.h> #include <sound/pcm_params.h> #include <sound/soc.h> @@ -321,22 +323,22 @@ static const char * const da9055_hpf_cutoff_txt[] = { "Fs/24000", "Fs/12000", "Fs/6000", "Fs/3000" }; -static const struct soc_enum da9055_dac_hpf_cutoff = - SOC_ENUM_SINGLE(DA9055_DAC_FILTERS1, 4, 4, da9055_hpf_cutoff_txt); +static SOC_ENUM_SINGLE_DECL(da9055_dac_hpf_cutoff, + DA9055_DAC_FILTERS1, 4, da9055_hpf_cutoff_txt); -static const struct soc_enum da9055_adc_hpf_cutoff = - SOC_ENUM_SINGLE(DA9055_ADC_FILTERS1, 4, 4, da9055_hpf_cutoff_txt); +static SOC_ENUM_SINGLE_DECL(da9055_adc_hpf_cutoff, + DA9055_ADC_FILTERS1, 4, da9055_hpf_cutoff_txt); /* ADC and DAC voice mode (8kHz) high pass cutoff value */ static const char * const da9055_vf_cutoff_txt[] = { "2.5Hz", "25Hz", "50Hz", "100Hz", "150Hz", "200Hz", "300Hz", "400Hz" }; -static const struct soc_enum da9055_dac_vf_cutoff = - SOC_ENUM_SINGLE(DA9055_DAC_FILTERS1, 0, 8, da9055_vf_cutoff_txt); +static SOC_ENUM_SINGLE_DECL(da9055_dac_vf_cutoff, + DA9055_DAC_FILTERS1, 0, da9055_vf_cutoff_txt); -static const struct soc_enum da9055_adc_vf_cutoff = - SOC_ENUM_SINGLE(DA9055_ADC_FILTERS1, 0, 8, da9055_vf_cutoff_txt); +static SOC_ENUM_SINGLE_DECL(da9055_adc_vf_cutoff, + DA9055_ADC_FILTERS1, 0, da9055_vf_cutoff_txt); /* Gain ramping rate value */ static const char * const da9055_gain_ramping_txt[] = { @@ -344,44 +346,44 @@ static const char * const da9055_gain_ramping_txt[] = { "nominal rate / 8" }; -static const struct soc_enum da9055_gain_ramping_rate = - SOC_ENUM_SINGLE(DA9055_GAIN_RAMP_CTRL, 0, 4, da9055_gain_ramping_txt); +static SOC_ENUM_SINGLE_DECL(da9055_gain_ramping_rate, + DA9055_GAIN_RAMP_CTRL, 0, da9055_gain_ramping_txt); /* DAC noise gate setup time value */ static const char * const da9055_dac_ng_setup_time_txt[] = { "256 samples", "512 samples", "1024 samples", "2048 samples" }; -static const struct soc_enum da9055_dac_ng_setup_time = - SOC_ENUM_SINGLE(DA9055_DAC_NG_SETUP_TIME, 0, 4, - da9055_dac_ng_setup_time_txt); +static SOC_ENUM_SINGLE_DECL(da9055_dac_ng_setup_time, + DA9055_DAC_NG_SETUP_TIME, 0, + da9055_dac_ng_setup_time_txt); /* DAC noise gate rampup rate value */ static const char * const da9055_dac_ng_rampup_txt[] = { "0.02 ms/dB", "0.16 ms/dB" }; -static const struct soc_enum da9055_dac_ng_rampup_rate = - SOC_ENUM_SINGLE(DA9055_DAC_NG_SETUP_TIME, 2, 2, - da9055_dac_ng_rampup_txt); +static SOC_ENUM_SINGLE_DECL(da9055_dac_ng_rampup_rate, + DA9055_DAC_NG_SETUP_TIME, 2, + da9055_dac_ng_rampup_txt); /* DAC noise gate rampdown rate value */ static const char * const da9055_dac_ng_rampdown_txt[] = { "0.64 ms/dB", "20.48 ms/dB" }; -static const struct soc_enum da9055_dac_ng_rampdown_rate = - SOC_ENUM_SINGLE(DA9055_DAC_NG_SETUP_TIME, 3, 2, - da9055_dac_ng_rampdown_txt); +static SOC_ENUM_SINGLE_DECL(da9055_dac_ng_rampdown_rate, + DA9055_DAC_NG_SETUP_TIME, 3, + da9055_dac_ng_rampdown_txt); /* DAC soft mute rate value */ static const char * const da9055_dac_soft_mute_rate_txt[] = { "1", "2", "4", "8", "16", "32", "64" }; -static const struct soc_enum da9055_dac_soft_mute_rate = - SOC_ENUM_SINGLE(DA9055_DAC_FILTERS5, 4, 7, - da9055_dac_soft_mute_rate_txt); +static SOC_ENUM_SINGLE_DECL(da9055_dac_soft_mute_rate, + DA9055_DAC_FILTERS5, 4, + da9055_dac_soft_mute_rate_txt); /* DAC routing select */ static const char * const da9055_dac_src_txt[] = { @@ -389,40 +391,40 @@ static const char * const da9055_dac_src_txt[] = { "AIF input right" }; -static const struct soc_enum da9055_dac_l_src = - SOC_ENUM_SINGLE(DA9055_DIG_ROUTING_DAC, 0, 4, da9055_dac_src_txt); +static SOC_ENUM_SINGLE_DECL(da9055_dac_l_src, + DA9055_DIG_ROUTING_DAC, 0, da9055_dac_src_txt); -static const struct soc_enum da9055_dac_r_src = - SOC_ENUM_SINGLE(DA9055_DIG_ROUTING_DAC, 4, 4, da9055_dac_src_txt); +static SOC_ENUM_SINGLE_DECL(da9055_dac_r_src, + DA9055_DIG_ROUTING_DAC, 4, da9055_dac_src_txt); /* MIC PGA Left source select */ static const char * const da9055_mic_l_src_txt[] = { "MIC1_P_N", "MIC1_P", "MIC1_N", "MIC2_L" }; -static const struct soc_enum da9055_mic_l_src = - SOC_ENUM_SINGLE(DA9055_MIXIN_L_SELECT, 4, 4, da9055_mic_l_src_txt); +static SOC_ENUM_SINGLE_DECL(da9055_mic_l_src, + DA9055_MIXIN_L_SELECT, 4, da9055_mic_l_src_txt); /* MIC PGA Right source select */ static const char * const da9055_mic_r_src_txt[] = { "MIC2_R_L", "MIC2_R", "MIC2_L" }; -static const struct soc_enum da9055_mic_r_src = - SOC_ENUM_SINGLE(DA9055_MIXIN_R_SELECT, 4, 3, da9055_mic_r_src_txt); +static SOC_ENUM_SINGLE_DECL(da9055_mic_r_src, + DA9055_MIXIN_R_SELECT, 4, da9055_mic_r_src_txt); /* ALC Input Signal Tracking rate select */ static const char * const da9055_signal_tracking_rate_txt[] = { "1/4", "1/16", "1/256", "1/65536" }; -static const struct soc_enum da9055_integ_attack_rate = - SOC_ENUM_SINGLE(DA9055_ALC_CTRL3, 4, 4, - da9055_signal_tracking_rate_txt); +static SOC_ENUM_SINGLE_DECL(da9055_integ_attack_rate, + DA9055_ALC_CTRL3, 4, + da9055_signal_tracking_rate_txt); -static const struct soc_enum da9055_integ_release_rate = - SOC_ENUM_SINGLE(DA9055_ALC_CTRL3, 6, 4, - da9055_signal_tracking_rate_txt); +static SOC_ENUM_SINGLE_DECL(da9055_integ_release_rate, + DA9055_ALC_CTRL3, 6, + da9055_signal_tracking_rate_txt); /* ALC Attack Rate select */ static const char * const da9055_attack_rate_txt[] = { @@ -430,8 +432,8 @@ static const char * const da9055_attack_rate_txt[] = { "5632/fs", "11264/fs", "22528/fs", "45056/fs", "90112/fs", "180224/fs" }; -static const struct soc_enum da9055_attack_rate = - SOC_ENUM_SINGLE(DA9055_ALC_CTRL2, 0, 13, da9055_attack_rate_txt); +static SOC_ENUM_SINGLE_DECL(da9055_attack_rate, + DA9055_ALC_CTRL2, 0, da9055_attack_rate_txt); /* ALC Release Rate select */ static const char * const da9055_release_rate_txt[] = { @@ -439,8 +441,8 @@ static const char * const da9055_release_rate_txt[] = { "11264/fs", "22528/fs", "45056/fs", "90112/fs", "180224/fs" }; -static const struct soc_enum da9055_release_rate = - SOC_ENUM_SINGLE(DA9055_ALC_CTRL2, 4, 11, da9055_release_rate_txt); +static SOC_ENUM_SINGLE_DECL(da9055_release_rate, + DA9055_ALC_CTRL2, 4, da9055_release_rate_txt); /* ALC Hold Time select */ static const char * const da9055_hold_time_txt[] = { @@ -449,8 +451,8 @@ static const char * const da9055_hold_time_txt[] = { "253952/fs", "507904/fs", "1015808/fs", "2031616/fs" }; -static const struct soc_enum da9055_hold_time = - SOC_ENUM_SINGLE(DA9055_ALC_CTRL3, 0, 16, da9055_hold_time_txt); +static SOC_ENUM_SINGLE_DECL(da9055_hold_time, + DA9055_ALC_CTRL3, 0, da9055_hold_time_txt); static int da9055_get_alc_data(struct snd_soc_codec *codec, u8 reg_val) { @@ -1381,16 +1383,8 @@ static int da9055_set_bias_level(struct snd_soc_codec *codec, static int da9055_probe(struct snd_soc_codec *codec) { - int ret; struct da9055_priv *da9055 = snd_soc_codec_get_drvdata(codec); - codec->control_data = da9055->regmap; - ret = snd_soc_codec_set_cache_io(codec, 8, 8, SND_SOC_REGMAP); - if (ret < 0) { - dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); - return ret; - } - /* Enable all Gain Ramps */ snd_soc_update_bits(codec, DA9055_AUX_L_CTRL, DA9055_GAIN_RAMPING_EN, DA9055_GAIN_RAMPING_EN); @@ -1536,11 +1530,17 @@ static const struct i2c_device_id da9055_i2c_id[] = { }; MODULE_DEVICE_TABLE(i2c, da9055_i2c_id); +static const struct of_device_id da9055_of_match[] = { + { .compatible = "dlg,da9055-codec", }, + { } +}; + /* I2C codec control layer */ static struct i2c_driver da9055_i2c_driver = { .driver = { .name = "da9055-codec", .owner = THIS_MODULE, + .of_match_table = of_match_ptr(da9055_of_match), }, .probe = da9055_i2c_probe, .remove = da9055_remove, diff --git a/sound/soc/codecs/isabelle.c b/sound/soc/codecs/isabelle.c index cb736ddc446..3a89ce66d51 100644 --- a/sound/soc/codecs/isabelle.c +++ b/sound/soc/codecs/isabelle.c @@ -918,8 +918,7 @@ static int isabelle_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params, struct snd_soc_dai *dai) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_codec *codec = rtd->codec; + struct snd_soc_codec *codec = dai->codec; u16 aif = 0; unsigned int fs_val = 0; @@ -1090,23 +1089,7 @@ static struct snd_soc_dai_driver isabelle_dai[] = { }, }; -static int isabelle_probe(struct snd_soc_codec *codec) -{ - int ret = 0; - - codec->control_data = dev_get_regmap(codec->dev, NULL); - - ret = snd_soc_codec_set_cache_io(codec, 8, 8, SND_SOC_REGMAP); - if (ret < 0) { - dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); - return ret; - } - - return 0; -} - static struct snd_soc_codec_driver soc_codec_dev_isabelle = { - .probe = isabelle_probe, .set_bias_level = isabelle_set_bias_level, .controls = isabelle_snd_controls, .num_controls = ARRAY_SIZE(isabelle_snd_controls), diff --git a/sound/soc/codecs/lm4857.c b/sound/soc/codecs/lm4857.c index 0e5743ea79d..4f048db9f55 100644 --- a/sound/soc/codecs/lm4857.c +++ b/sound/soc/codecs/lm4857.c @@ -101,8 +101,7 @@ static const char *lm4857_mode[] = { "Headphone", }; -static const struct soc_enum lm4857_mode_enum = - SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(lm4857_mode), lm4857_mode); +static SOC_ENUM_SINGLE_EXT_DECL(lm4857_mode_enum, lm4857_mode); static const struct snd_soc_dapm_widget lm4857_dapm_widgets[] = { SND_SOC_DAPM_INPUT("IN"), diff --git a/sound/soc/codecs/lm49453.c b/sound/soc/codecs/lm49453.c index e19490cfb3a..275b3f72f3f 100644 --- a/sound/soc/codecs/lm49453.c +++ b/sound/soc/codecs/lm49453.c @@ -195,33 +195,31 @@ struct lm49453_priv { static const char *lm49453_mic2mode_text[] = {"Single Ended", "Differential"}; -static const SOC_ENUM_SINGLE_DECL(lm49453_mic2mode_enum, LM49453_P0_MICR_REG, 5, - lm49453_mic2mode_text); +static SOC_ENUM_SINGLE_DECL(lm49453_mic2mode_enum, LM49453_P0_MICR_REG, 5, + lm49453_mic2mode_text); static const char *lm49453_dmic_cfg_text[] = {"DMICDAT1", "DMICDAT2"}; -static const SOC_ENUM_SINGLE_DECL(lm49453_dmic12_cfg_enum, - LM49453_P0_DIGITAL_MIC1_CONFIG_REG, - 7, lm49453_dmic_cfg_text); +static SOC_ENUM_SINGLE_DECL(lm49453_dmic12_cfg_enum, + LM49453_P0_DIGITAL_MIC1_CONFIG_REG, 7, + lm49453_dmic_cfg_text); -static const SOC_ENUM_SINGLE_DECL(lm49453_dmic34_cfg_enum, - LM49453_P0_DIGITAL_MIC2_CONFIG_REG, - 7, lm49453_dmic_cfg_text); +static SOC_ENUM_SINGLE_DECL(lm49453_dmic34_cfg_enum, + LM49453_P0_DIGITAL_MIC2_CONFIG_REG, 7, + lm49453_dmic_cfg_text); /* MUX Controls */ static const char *lm49453_adcl_mux_text[] = { "MIC1", "Aux_L" }; static const char *lm49453_adcr_mux_text[] = { "MIC2", "Aux_R" }; -static const struct soc_enum lm49453_adcl_enum = - SOC_ENUM_SINGLE(LM49453_P0_ANALOG_MIXER_ADC_REG, 0, - ARRAY_SIZE(lm49453_adcl_mux_text), - lm49453_adcl_mux_text); +static SOC_ENUM_SINGLE_DECL(lm49453_adcl_enum, + LM49453_P0_ANALOG_MIXER_ADC_REG, 0, + lm49453_adcl_mux_text); -static const struct soc_enum lm49453_adcr_enum = - SOC_ENUM_SINGLE(LM49453_P0_ANALOG_MIXER_ADC_REG, 1, - ARRAY_SIZE(lm49453_adcr_mux_text), - lm49453_adcr_mux_text); +static SOC_ENUM_SINGLE_DECL(lm49453_adcr_enum, + LM49453_P0_ANALOG_MIXER_ADC_REG, 1, + lm49453_adcr_mux_text); static const struct snd_kcontrol_new lm49453_adcl_mux_control = SOC_DAPM_ENUM("ADC Left Mux", lm49453_adcl_enum); @@ -1409,22 +1407,6 @@ static int lm49453_resume(struct snd_soc_codec *codec) return 0; } -static int lm49453_probe(struct snd_soc_codec *codec) -{ - struct lm49453_priv *lm49453 = snd_soc_codec_get_drvdata(codec); - int ret = 0; - - codec->control_data = lm49453->regmap; - - ret = snd_soc_codec_set_cache_io(codec, 8, 8, SND_SOC_REGMAP); - if (ret < 0) { - dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); - return ret; - } - - return 0; -} - /* power down chip */ static int lm49453_remove(struct snd_soc_codec *codec) { @@ -1433,7 +1415,6 @@ static int lm49453_remove(struct snd_soc_codec *codec) } static struct snd_soc_codec_driver soc_codec_dev_lm49453 = { - .probe = lm49453_probe, .remove = lm49453_remove, .suspend = lm49453_suspend, .resume = lm49453_resume, diff --git a/sound/soc/codecs/max9768.c b/sound/soc/codecs/max9768.c index 31f91560e9f..ec481fc428c 100644 --- a/sound/soc/codecs/max9768.c +++ b/sound/soc/codecs/max9768.c @@ -135,11 +135,6 @@ static int max9768_probe(struct snd_soc_codec *codec) struct max9768 *max9768 = snd_soc_codec_get_drvdata(codec); int ret; - codec->control_data = max9768->regmap; - ret = snd_soc_codec_set_cache_io(codec, 2, 6, SND_SOC_REGMAP); - if (ret) - return ret; - if (max9768->flags & MAX9768_FLAG_CLASSIC_PWM) { ret = snd_soc_write(codec, MAX9768_CTRL, MAX9768_CTRL_PWM); if (ret) diff --git a/sound/soc/codecs/max98088.c b/sound/soc/codecs/max98088.c index ee660e2d3df..ef7cf89f562 100644 --- a/sound/soc/codecs/max98088.c +++ b/sound/soc/codecs/max98088.c @@ -597,28 +597,27 @@ static const unsigned int max98088_exmode_values[] = { 0x00, 0x43, 0x10, 0x20, 0x30, 0x40, 0x11, 0x22, 0x32 }; -static const struct soc_enum max98088_exmode_enum = - SOC_VALUE_ENUM_SINGLE(M98088_REG_41_SPKDHP, 0, 127, - ARRAY_SIZE(max98088_exmode_texts), - max98088_exmode_texts, - max98088_exmode_values); +static SOC_VALUE_ENUM_SINGLE_DECL(max98088_exmode_enum, + M98088_REG_41_SPKDHP, 0, 127, + max98088_exmode_texts, + max98088_exmode_values); static const char *max98088_ex_thresh[] = { /* volts PP */ "0.6", "1.2", "1.8", "2.4", "3.0", "3.6", "4.2", "4.8"}; -static const struct soc_enum max98088_ex_thresh_enum[] = { - SOC_ENUM_SINGLE(M98088_REG_42_SPKDHP_THRESH, 0, 8, - max98088_ex_thresh), -}; +static SOC_ENUM_SINGLE_DECL(max98088_ex_thresh_enum, + M98088_REG_42_SPKDHP_THRESH, 0, + max98088_ex_thresh); static const char *max98088_fltr_mode[] = {"Voice", "Music" }; -static const struct soc_enum max98088_filter_mode_enum[] = { - SOC_ENUM_SINGLE(M98088_REG_18_DAI1_FILTERS, 7, 2, max98088_fltr_mode), -}; +static SOC_ENUM_SINGLE_DECL(max98088_filter_mode_enum, + M98088_REG_18_DAI1_FILTERS, 7, + max98088_fltr_mode); static const char *max98088_extmic_text[] = { "None", "MIC1", "MIC2" }; -static const struct soc_enum max98088_extmic_enum = - SOC_ENUM_SINGLE(M98088_REG_48_CFG_MIC, 0, 3, max98088_extmic_text); +static SOC_ENUM_SINGLE_DECL(max98088_extmic_enum, + M98088_REG_48_CFG_MIC, 0, + max98088_extmic_text); static const struct snd_kcontrol_new max98088_extmic_mux = SOC_DAPM_ENUM("External MIC Mux", max98088_extmic_enum); @@ -626,12 +625,12 @@ static const struct snd_kcontrol_new max98088_extmic_mux = static const char *max98088_dai1_fltr[] = { "Off", "fc=258/fs=16k", "fc=500/fs=16k", "fc=258/fs=8k", "fc=500/fs=8k", "fc=200"}; -static const struct soc_enum max98088_dai1_dac_filter_enum[] = { - SOC_ENUM_SINGLE(M98088_REG_18_DAI1_FILTERS, 0, 6, max98088_dai1_fltr), -}; -static const struct soc_enum max98088_dai1_adc_filter_enum[] = { - SOC_ENUM_SINGLE(M98088_REG_18_DAI1_FILTERS, 4, 6, max98088_dai1_fltr), -}; +static SOC_ENUM_SINGLE_DECL(max98088_dai1_dac_filter_enum, + M98088_REG_18_DAI1_FILTERS, 0, + max98088_dai1_fltr); +static SOC_ENUM_SINGLE_DECL(max98088_dai1_adc_filter_enum, + M98088_REG_18_DAI1_FILTERS, 4, + max98088_dai1_fltr); static int max98088_mic1pre_set(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) @@ -1849,7 +1848,7 @@ static void max98088_handle_eq_pdata(struct snd_soc_codec *codec) /* Now point the soc_enum to .texts array items */ max98088->eq_enum.texts = max98088->eq_texts; - max98088->eq_enum.max = max98088->eq_textcnt; + max98088->eq_enum.items = max98088->eq_textcnt; ret = snd_soc_add_codec_controls(codec, controls, ARRAY_SIZE(controls)); if (ret != 0) @@ -1915,12 +1914,6 @@ static int max98088_probe(struct snd_soc_codec *codec) regcache_mark_dirty(max98088->regmap); - ret = snd_soc_codec_set_cache_io(codec, 8, 8, SND_SOC_REGMAP); - if (ret != 0) { - dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); - return ret; - } - /* initialize private data */ max98088->sysclk = (unsigned)-1; diff --git a/sound/soc/codecs/max98090.c b/sound/soc/codecs/max98090.c index 9f714ea8661..98c6e104357 100644 --- a/sound/soc/codecs/max98090.c +++ b/sound/soc/codecs/max98090.c @@ -513,65 +513,75 @@ static const char *max98090_perf_pwr_text[] = static const char *max98090_pwr_perf_text[] = { "Low Power", "High Performance" }; -static const struct soc_enum max98090_vcmbandgap_enum = - SOC_ENUM_SINGLE(M98090_REG_BIAS_CONTROL, M98090_VCM_MODE_SHIFT, - ARRAY_SIZE(max98090_pwr_perf_text), max98090_pwr_perf_text); +static SOC_ENUM_SINGLE_DECL(max98090_vcmbandgap_enum, + M98090_REG_BIAS_CONTROL, + M98090_VCM_MODE_SHIFT, + max98090_pwr_perf_text); static const char *max98090_osr128_text[] = { "64*fs", "128*fs" }; -static const struct soc_enum max98090_osr128_enum = - SOC_ENUM_SINGLE(M98090_REG_ADC_CONTROL, M98090_OSR128_SHIFT, - ARRAY_SIZE(max98090_osr128_text), max98090_osr128_text); +static SOC_ENUM_SINGLE_DECL(max98090_osr128_enum, + M98090_REG_ADC_CONTROL, + M98090_OSR128_SHIFT, + max98090_osr128_text); static const char *max98090_mode_text[] = { "Voice", "Music" }; -static const struct soc_enum max98090_mode_enum = - SOC_ENUM_SINGLE(M98090_REG_FILTER_CONFIG, M98090_MODE_SHIFT, - ARRAY_SIZE(max98090_mode_text), max98090_mode_text); +static SOC_ENUM_SINGLE_DECL(max98090_mode_enum, + M98090_REG_FILTER_CONFIG, + M98090_MODE_SHIFT, + max98090_mode_text); -static const struct soc_enum max98090_filter_dmic34mode_enum = - SOC_ENUM_SINGLE(M98090_REG_FILTER_CONFIG, - M98090_FLT_DMIC34MODE_SHIFT, - ARRAY_SIZE(max98090_mode_text), max98090_mode_text); +static SOC_ENUM_SINGLE_DECL(max98090_filter_dmic34mode_enum, + M98090_REG_FILTER_CONFIG, + M98090_FLT_DMIC34MODE_SHIFT, + max98090_mode_text); static const char *max98090_drcatk_text[] = { "0.5ms", "1ms", "5ms", "10ms", "25ms", "50ms", "100ms", "200ms" }; -static const struct soc_enum max98090_drcatk_enum = - SOC_ENUM_SINGLE(M98090_REG_DRC_TIMING, M98090_DRCATK_SHIFT, - ARRAY_SIZE(max98090_drcatk_text), max98090_drcatk_text); +static SOC_ENUM_SINGLE_DECL(max98090_drcatk_enum, + M98090_REG_DRC_TIMING, + M98090_DRCATK_SHIFT, + max98090_drcatk_text); static const char *max98090_drcrls_text[] = { "8s", "4s", "2s", "1s", "0.5s", "0.25s", "0.125s", "0.0625s" }; -static const struct soc_enum max98090_drcrls_enum = - SOC_ENUM_SINGLE(M98090_REG_DRC_TIMING, M98090_DRCRLS_SHIFT, - ARRAY_SIZE(max98090_drcrls_text), max98090_drcrls_text); +static SOC_ENUM_SINGLE_DECL(max98090_drcrls_enum, + M98090_REG_DRC_TIMING, + M98090_DRCRLS_SHIFT, + max98090_drcrls_text); static const char *max98090_alccmp_text[] = { "1:1", "1:1.5", "1:2", "1:4", "1:INF" }; -static const struct soc_enum max98090_alccmp_enum = - SOC_ENUM_SINGLE(M98090_REG_DRC_COMPRESSOR, M98090_DRCCMP_SHIFT, - ARRAY_SIZE(max98090_alccmp_text), max98090_alccmp_text); +static SOC_ENUM_SINGLE_DECL(max98090_alccmp_enum, + M98090_REG_DRC_COMPRESSOR, + M98090_DRCCMP_SHIFT, + max98090_alccmp_text); static const char *max98090_drcexp_text[] = { "1:1", "2:1", "3:1" }; -static const struct soc_enum max98090_drcexp_enum = - SOC_ENUM_SINGLE(M98090_REG_DRC_EXPANDER, M98090_DRCEXP_SHIFT, - ARRAY_SIZE(max98090_drcexp_text), max98090_drcexp_text); +static SOC_ENUM_SINGLE_DECL(max98090_drcexp_enum, + M98090_REG_DRC_EXPANDER, + M98090_DRCEXP_SHIFT, + max98090_drcexp_text); -static const struct soc_enum max98090_dac_perfmode_enum = - SOC_ENUM_SINGLE(M98090_REG_DAC_CONTROL, M98090_PERFMODE_SHIFT, - ARRAY_SIZE(max98090_perf_pwr_text), max98090_perf_pwr_text); +static SOC_ENUM_SINGLE_DECL(max98090_dac_perfmode_enum, + M98090_REG_DAC_CONTROL, + M98090_PERFMODE_SHIFT, + max98090_perf_pwr_text); -static const struct soc_enum max98090_dachp_enum = - SOC_ENUM_SINGLE(M98090_REG_DAC_CONTROL, M98090_DACHP_SHIFT, - ARRAY_SIZE(max98090_pwr_perf_text), max98090_pwr_perf_text); +static SOC_ENUM_SINGLE_DECL(max98090_dachp_enum, + M98090_REG_DAC_CONTROL, + M98090_DACHP_SHIFT, + max98090_pwr_perf_text); -static const struct soc_enum max98090_adchp_enum = - SOC_ENUM_SINGLE(M98090_REG_ADC_CONTROL, M98090_ADCHP_SHIFT, - ARRAY_SIZE(max98090_pwr_perf_text), max98090_pwr_perf_text); +static SOC_ENUM_SINGLE_DECL(max98090_adchp_enum, + M98090_REG_ADC_CONTROL, + M98090_ADCHP_SHIFT, + max98090_pwr_perf_text); static const struct snd_kcontrol_new max98090_snd_controls[] = { SOC_ENUM("MIC Bias VCM Bandgap", max98090_vcmbandgap_enum), @@ -842,39 +852,42 @@ static int max98090_micinput_event(struct snd_soc_dapm_widget *w, static const char *mic1_mux_text[] = { "IN12", "IN56" }; -static const struct soc_enum mic1_mux_enum = - SOC_ENUM_SINGLE(M98090_REG_INPUT_MODE, M98090_EXTMIC1_SHIFT, - ARRAY_SIZE(mic1_mux_text), mic1_mux_text); +static SOC_ENUM_SINGLE_DECL(mic1_mux_enum, + M98090_REG_INPUT_MODE, + M98090_EXTMIC1_SHIFT, + mic1_mux_text); static const struct snd_kcontrol_new max98090_mic1_mux = SOC_DAPM_ENUM("MIC1 Mux", mic1_mux_enum); static const char *mic2_mux_text[] = { "IN34", "IN56" }; -static const struct soc_enum mic2_mux_enum = - SOC_ENUM_SINGLE(M98090_REG_INPUT_MODE, M98090_EXTMIC2_SHIFT, - ARRAY_SIZE(mic2_mux_text), mic2_mux_text); +static SOC_ENUM_SINGLE_DECL(mic2_mux_enum, + M98090_REG_INPUT_MODE, + M98090_EXTMIC2_SHIFT, + mic2_mux_text); static const struct snd_kcontrol_new max98090_mic2_mux = SOC_DAPM_ENUM("MIC2 Mux", mic2_mux_enum); static const char *dmic_mux_text[] = { "ADC", "DMIC" }; -static const struct soc_enum dmic_mux_enum = - SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(dmic_mux_text), dmic_mux_text); +static SOC_ENUM_SINGLE_VIRT_DECL(dmic_mux_enum, dmic_mux_text); static const struct snd_kcontrol_new max98090_dmic_mux = SOC_DAPM_ENUM_VIRT("DMIC Mux", dmic_mux_enum); static const char *max98090_micpre_text[] = { "Off", "On" }; -static const struct soc_enum max98090_pa1en_enum = - SOC_ENUM_SINGLE(M98090_REG_MIC1_INPUT_LEVEL, M98090_MIC_PA1EN_SHIFT, - ARRAY_SIZE(max98090_micpre_text), max98090_micpre_text); +static SOC_ENUM_SINGLE_DECL(max98090_pa1en_enum, + M98090_REG_MIC1_INPUT_LEVEL, + M98090_MIC_PA1EN_SHIFT, + max98090_micpre_text); -static const struct soc_enum max98090_pa2en_enum = - SOC_ENUM_SINGLE(M98090_REG_MIC2_INPUT_LEVEL, M98090_MIC_PA2EN_SHIFT, - ARRAY_SIZE(max98090_micpre_text), max98090_micpre_text); +static SOC_ENUM_SINGLE_DECL(max98090_pa2en_enum, + M98090_REG_MIC2_INPUT_LEVEL, + M98090_MIC_PA2EN_SHIFT, + max98090_micpre_text); /* LINEA mixer switch */ static const struct snd_kcontrol_new max98090_linea_mixer_controls[] = { @@ -938,13 +951,15 @@ static const struct snd_kcontrol_new max98090_right_adc_mixer_controls[] = { static const char *lten_mux_text[] = { "Normal", "Loopthrough" }; -static const struct soc_enum ltenl_mux_enum = - SOC_ENUM_SINGLE(M98090_REG_IO_CONFIGURATION, M98090_LTEN_SHIFT, - ARRAY_SIZE(lten_mux_text), lten_mux_text); +static SOC_ENUM_SINGLE_DECL(ltenl_mux_enum, + M98090_REG_IO_CONFIGURATION, + M98090_LTEN_SHIFT, + lten_mux_text); -static const struct soc_enum ltenr_mux_enum = - SOC_ENUM_SINGLE(M98090_REG_IO_CONFIGURATION, M98090_LTEN_SHIFT, - ARRAY_SIZE(lten_mux_text), lten_mux_text); +static SOC_ENUM_SINGLE_DECL(ltenr_mux_enum, + M98090_REG_IO_CONFIGURATION, + M98090_LTEN_SHIFT, + lten_mux_text); static const struct snd_kcontrol_new max98090_ltenl_mux = SOC_DAPM_ENUM("LTENL Mux", ltenl_mux_enum); @@ -954,13 +969,15 @@ static const struct snd_kcontrol_new max98090_ltenr_mux = static const char *lben_mux_text[] = { "Normal", "Loopback" }; -static const struct soc_enum lbenl_mux_enum = - SOC_ENUM_SINGLE(M98090_REG_IO_CONFIGURATION, M98090_LBEN_SHIFT, - ARRAY_SIZE(lben_mux_text), lben_mux_text); +static SOC_ENUM_SINGLE_DECL(lbenl_mux_enum, + M98090_REG_IO_CONFIGURATION, + M98090_LBEN_SHIFT, + lben_mux_text); -static const struct soc_enum lbenr_mux_enum = - SOC_ENUM_SINGLE(M98090_REG_IO_CONFIGURATION, M98090_LBEN_SHIFT, - ARRAY_SIZE(lben_mux_text), lben_mux_text); +static SOC_ENUM_SINGLE_DECL(lbenr_mux_enum, + M98090_REG_IO_CONFIGURATION, + M98090_LBEN_SHIFT, + lben_mux_text); static const struct snd_kcontrol_new max98090_lbenl_mux = SOC_DAPM_ENUM("LBENL Mux", lbenl_mux_enum); @@ -972,13 +989,15 @@ static const char *stenl_mux_text[] = { "Normal", "Sidetone Left" }; static const char *stenr_mux_text[] = { "Normal", "Sidetone Right" }; -static const struct soc_enum stenl_mux_enum = - SOC_ENUM_SINGLE(M98090_REG_ADC_SIDETONE, M98090_DSTSL_SHIFT, - ARRAY_SIZE(stenl_mux_text), stenl_mux_text); +static SOC_ENUM_SINGLE_DECL(stenl_mux_enum, + M98090_REG_ADC_SIDETONE, + M98090_DSTSL_SHIFT, + stenl_mux_text); -static const struct soc_enum stenr_mux_enum = - SOC_ENUM_SINGLE(M98090_REG_ADC_SIDETONE, M98090_DSTSR_SHIFT, - ARRAY_SIZE(stenr_mux_text), stenr_mux_text); +static SOC_ENUM_SINGLE_DECL(stenr_mux_enum, + M98090_REG_ADC_SIDETONE, + M98090_DSTSR_SHIFT, + stenr_mux_text); static const struct snd_kcontrol_new max98090_stenl_mux = SOC_DAPM_ENUM("STENL Mux", stenl_mux_enum); @@ -1086,9 +1105,10 @@ static const struct snd_kcontrol_new max98090_right_rcv_mixer_controls[] = { static const char *linmod_mux_text[] = { "Left Only", "Left and Right" }; -static const struct soc_enum linmod_mux_enum = - SOC_ENUM_SINGLE(M98090_REG_LOUTR_MIXER, M98090_LINMOD_SHIFT, - ARRAY_SIZE(linmod_mux_text), linmod_mux_text); +static SOC_ENUM_SINGLE_DECL(linmod_mux_enum, + M98090_REG_LOUTR_MIXER, + M98090_LINMOD_SHIFT, + linmod_mux_text); static const struct snd_kcontrol_new max98090_linmod_mux = SOC_DAPM_ENUM("LINMOD Mux", linmod_mux_enum); @@ -1098,16 +1118,18 @@ static const char *mixhpsel_mux_text[] = { "DAC Only", "HP Mixer" }; /* * This is a mux as it selects the HP output, but to DAPM it is a Mixer enable */ -static const struct soc_enum mixhplsel_mux_enum = - SOC_ENUM_SINGLE(M98090_REG_HP_CONTROL, M98090_MIXHPLSEL_SHIFT, - ARRAY_SIZE(mixhpsel_mux_text), mixhpsel_mux_text); +static SOC_ENUM_SINGLE_DECL(mixhplsel_mux_enum, + M98090_REG_HP_CONTROL, + M98090_MIXHPLSEL_SHIFT, + mixhpsel_mux_text); static const struct snd_kcontrol_new max98090_mixhplsel_mux = SOC_DAPM_ENUM("MIXHPLSEL Mux", mixhplsel_mux_enum); -static const struct soc_enum mixhprsel_mux_enum = - SOC_ENUM_SINGLE(M98090_REG_HP_CONTROL, M98090_MIXHPRSEL_SHIFT, - ARRAY_SIZE(mixhpsel_mux_text), mixhpsel_mux_text); +static SOC_ENUM_SINGLE_DECL(mixhprsel_mux_enum, + M98090_REG_HP_CONTROL, + M98090_MIXHPRSEL_SHIFT, + mixhpsel_mux_text); static const struct snd_kcontrol_new max98090_mixhprsel_mux = SOC_DAPM_ENUM("MIXHPRSEL Mux", mixhprsel_mux_enum); @@ -2196,14 +2218,6 @@ static int max98090_probe(struct snd_soc_codec *codec) max98090->codec = codec; - codec->control_data = max98090->regmap; - - ret = snd_soc_codec_set_cache_io(codec, 8, 8, SND_SOC_REGMAP); - if (ret != 0) { - dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); - return ret; - } - /* Reset the codec, the DSP core, and disable all interrupts */ max98090_reset(max98090); @@ -2329,7 +2343,6 @@ static int max98090_i2c_probe(struct i2c_client *i2c, max98090->devtype = id->driver_data; i2c_set_clientdata(i2c, max98090); - max98090->control_data = i2c; max98090->pdata = i2c->dev.platform_data; max98090->irq = i2c->irq; diff --git a/sound/soc/codecs/max98090.h b/sound/soc/codecs/max98090.h index 7e103f24905..1a4e2334a7b 100644 --- a/sound/soc/codecs/max98090.h +++ b/sound/soc/codecs/max98090.h @@ -1523,7 +1523,6 @@ struct max98090_priv { struct regmap *regmap; struct snd_soc_codec *codec; enum max98090_type devtype; - void *control_data; struct max98090_pdata *pdata; unsigned int sysclk; unsigned int bclk; diff --git a/sound/soc/codecs/max98095.c b/sound/soc/codecs/max98095.c index 3ba1170ebb5..03f0536e6f6 100644 --- a/sound/soc/codecs/max98095.c +++ b/sound/soc/codecs/max98095.c @@ -560,25 +560,27 @@ static void m98095_biquad_band(struct snd_soc_codec *codec, unsigned int dai, } static const char * const max98095_fltr_mode[] = { "Voice", "Music" }; -static const struct soc_enum max98095_dai1_filter_mode_enum[] = { - SOC_ENUM_SINGLE(M98095_02E_DAI1_FILTERS, 7, 2, max98095_fltr_mode), -}; -static const struct soc_enum max98095_dai2_filter_mode_enum[] = { - SOC_ENUM_SINGLE(M98095_038_DAI2_FILTERS, 7, 2, max98095_fltr_mode), -}; +static SOC_ENUM_SINGLE_DECL(max98095_dai1_filter_mode_enum, + M98095_02E_DAI1_FILTERS, 7, + max98095_fltr_mode); +static SOC_ENUM_SINGLE_DECL(max98095_dai2_filter_mode_enum, + M98095_038_DAI2_FILTERS, 7, + max98095_fltr_mode); static const char * const max98095_extmic_text[] = { "None", "MIC1", "MIC2" }; -static const struct soc_enum max98095_extmic_enum = - SOC_ENUM_SINGLE(M98095_087_CFG_MIC, 0, 3, max98095_extmic_text); +static SOC_ENUM_SINGLE_DECL(max98095_extmic_enum, + M98095_087_CFG_MIC, 0, + max98095_extmic_text); static const struct snd_kcontrol_new max98095_extmic_mux = SOC_DAPM_ENUM("External MIC Mux", max98095_extmic_enum); static const char * const max98095_linein_text[] = { "INA", "INB" }; -static const struct soc_enum max98095_linein_enum = - SOC_ENUM_SINGLE(M98095_086_CFG_LINE, 6, 2, max98095_linein_text); +static SOC_ENUM_SINGLE_DECL(max98095_linein_enum, + M98095_086_CFG_LINE, 6, + max98095_linein_text); static const struct snd_kcontrol_new max98095_linein_mux = SOC_DAPM_ENUM("Linein Input Mux", max98095_linein_enum); @@ -586,24 +588,26 @@ static const struct snd_kcontrol_new max98095_linein_mux = static const char * const max98095_line_mode_text[] = { "Stereo", "Differential"}; -static const struct soc_enum max98095_linein_mode_enum = - SOC_ENUM_SINGLE(M98095_086_CFG_LINE, 7, 2, max98095_line_mode_text); +static SOC_ENUM_SINGLE_DECL(max98095_linein_mode_enum, + M98095_086_CFG_LINE, 7, + max98095_line_mode_text); -static const struct soc_enum max98095_lineout_mode_enum = - SOC_ENUM_SINGLE(M98095_086_CFG_LINE, 4, 2, max98095_line_mode_text); +static SOC_ENUM_SINGLE_DECL(max98095_lineout_mode_enum, + M98095_086_CFG_LINE, 4, + max98095_line_mode_text); static const char * const max98095_dai_fltr[] = { "Off", "Elliptical-HPF-16k", "Butterworth-HPF-16k", "Elliptical-HPF-8k", "Butterworth-HPF-8k", "Butterworth-HPF-Fs/240"}; -static const struct soc_enum max98095_dai1_dac_filter_enum[] = { - SOC_ENUM_SINGLE(M98095_02E_DAI1_FILTERS, 0, 6, max98095_dai_fltr), -}; -static const struct soc_enum max98095_dai2_dac_filter_enum[] = { - SOC_ENUM_SINGLE(M98095_038_DAI2_FILTERS, 0, 6, max98095_dai_fltr), -}; -static const struct soc_enum max98095_dai3_dac_filter_enum[] = { - SOC_ENUM_SINGLE(M98095_042_DAI3_FILTERS, 0, 6, max98095_dai_fltr), -}; +static SOC_ENUM_SINGLE_DECL(max98095_dai1_dac_filter_enum, + M98095_02E_DAI1_FILTERS, 0, + max98095_dai_fltr); +static SOC_ENUM_SINGLE_DECL(max98095_dai2_dac_filter_enum, + M98095_038_DAI2_FILTERS, 0, + max98095_dai_fltr); +static SOC_ENUM_SINGLE_DECL(max98095_dai3_dac_filter_enum, + M98095_042_DAI3_FILTERS, 0, + max98095_dai_fltr); static int max98095_mic1pre_set(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) @@ -1861,7 +1865,7 @@ static void max98095_handle_eq_pdata(struct snd_soc_codec *codec) /* Now point the soc_enum to .texts array items */ max98095->eq_enum.texts = max98095->eq_texts; - max98095->eq_enum.max = max98095->eq_textcnt; + max98095->eq_enum.items = max98095->eq_textcnt; ret = snd_soc_add_codec_controls(codec, controls, ARRAY_SIZE(controls)); if (ret != 0) @@ -2016,7 +2020,7 @@ static void max98095_handle_bq_pdata(struct snd_soc_codec *codec) /* Now point the soc_enum to .texts array items */ max98095->bq_enum.texts = max98095->bq_texts; - max98095->bq_enum.max = max98095->bq_textcnt; + max98095->bq_enum.items = max98095->bq_textcnt; ret = snd_soc_add_codec_controls(codec, controls, ARRAY_SIZE(controls)); if (ret != 0) @@ -2234,12 +2238,6 @@ static int max98095_probe(struct snd_soc_codec *codec) struct i2c_client *client; int ret = 0; - ret = snd_soc_codec_set_cache_io(codec, 8, 8, SND_SOC_REGMAP); - if (ret != 0) { - dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); - return ret; - } - /* reset the codec, the DSP core, and disable all interrupts */ max98095_reset(codec); diff --git a/sound/soc/codecs/max9850.c b/sound/soc/codecs/max9850.c index 82757ebf030..4fdf5aaa236 100644 --- a/sound/soc/codecs/max9850.c +++ b/sound/soc/codecs/max9850.c @@ -312,14 +312,6 @@ static int max9850_resume(struct snd_soc_codec *codec) static int max9850_probe(struct snd_soc_codec *codec) { - int ret; - - ret = snd_soc_codec_set_cache_io(codec, 8, 8, SND_SOC_REGMAP); - if (ret < 0) { - dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); - return ret; - } - /* enable zero-detect */ snd_soc_update_bits(codec, MAX9850_GENERAL_PURPOSE, 1, 1); /* enable slew-rate control */ diff --git a/sound/soc/codecs/mc13783.c b/sound/soc/codecs/mc13783.c index 582c2bbd42c..2c59b1fb69d 100644 --- a/sound/soc/codecs/mc13783.c +++ b/sound/soc/codecs/mc13783.c @@ -106,8 +106,7 @@ static int mc13783_pcm_hw_params_dac(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params, struct snd_soc_dai *dai) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_codec *codec = rtd->codec; + struct snd_soc_codec *codec = dai->codec; unsigned int rate = params_rate(params); int i; @@ -126,8 +125,7 @@ static int mc13783_pcm_hw_params_codec(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params, struct snd_soc_dai *dai) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_codec *codec = rtd->codec; + struct snd_soc_codec *codec = dai->codec; unsigned int rate = params_rate(params); unsigned int val; @@ -408,8 +406,7 @@ static const char * const adcl_enum_text[] = { "MC1L", "RXINL", }; -static const struct soc_enum adcl_enum = - SOC_ENUM_SINGLE(0, 0, ARRAY_SIZE(adcl_enum_text), adcl_enum_text); +static SOC_ENUM_SINGLE_VIRT_DECL(adcl_enum, adcl_enum_text); static const struct snd_kcontrol_new left_input_mux = SOC_DAPM_ENUM_VIRT("Route", adcl_enum); @@ -418,8 +415,7 @@ static const char * const adcr_enum_text[] = { "MC1R", "MC2", "RXINR", "TXIN", }; -static const struct soc_enum adcr_enum = - SOC_ENUM_SINGLE(0, 0, ARRAY_SIZE(adcr_enum_text), adcr_enum_text); +static SOC_ENUM_SINGLE_VIRT_DECL(adcr_enum, adcr_enum_text); static const struct snd_kcontrol_new right_input_mux = SOC_DAPM_ENUM_VIRT("Route", adcr_enum); @@ -430,8 +426,8 @@ static const struct snd_kcontrol_new samp_ctl = static const char * const speaker_amp_source_text[] = { "CODEC", "Right" }; -static const SOC_ENUM_SINGLE_DECL(speaker_amp_source, MC13783_AUDIO_RX0, 4, - speaker_amp_source_text); +static SOC_ENUM_SINGLE_DECL(speaker_amp_source, MC13783_AUDIO_RX0, 4, + speaker_amp_source_text); static const struct snd_kcontrol_new speaker_amp_source_mux = SOC_DAPM_ENUM("Speaker Amp Source MUX", speaker_amp_source); @@ -439,8 +435,8 @@ static const char * const headset_amp_source_text[] = { "CODEC", "Mixer" }; -static const SOC_ENUM_SINGLE_DECL(headset_amp_source, MC13783_AUDIO_RX0, 11, - headset_amp_source_text); +static SOC_ENUM_SINGLE_DECL(headset_amp_source, MC13783_AUDIO_RX0, 11, + headset_amp_source_text); static const struct snd_kcontrol_new headset_amp_source_mux = SOC_DAPM_ENUM("Headset Amp Source MUX", headset_amp_source); @@ -580,9 +576,9 @@ static struct snd_soc_dapm_route mc13783_routes[] = { static const char * const mc13783_3d_mixer[] = {"Stereo", "Phase Mix", "Mono", "Mono Mix"}; -static const struct soc_enum mc13783_enum_3d_mixer = - SOC_ENUM_SINGLE(MC13783_AUDIO_RX1, 16, ARRAY_SIZE(mc13783_3d_mixer), - mc13783_3d_mixer); +static SOC_ENUM_SINGLE_DECL(mc13783_enum_3d_mixer, + MC13783_AUDIO_RX1, 16, + mc13783_3d_mixer); static struct snd_kcontrol_new mc13783_control_list[] = { SOC_SINGLE("Loudspeaker enable", MC13783_AUDIO_RX0, 5, 1, 0), @@ -614,8 +610,8 @@ static int mc13783_probe(struct snd_soc_codec *codec) struct mc13783_priv *priv = snd_soc_codec_get_drvdata(codec); int ret; - codec->control_data = dev_get_regmap(codec->dev->parent, NULL); - ret = snd_soc_codec_set_cache_io(codec, 8, 24, SND_SOC_REGMAP); + ret = snd_soc_codec_set_cache_io(codec, + dev_get_regmap(codec->dev->parent, NULL)); if (ret != 0) { dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); return ret; diff --git a/sound/soc/codecs/ml26124.c b/sound/soc/codecs/ml26124.c index 185fa3bc305..e661e8420e3 100644 --- a/sound/soc/codecs/ml26124.c +++ b/sound/soc/codecs/ml26124.c @@ -73,11 +73,11 @@ static const DECLARE_TLV_DB_SCALE(ngth, -7650, 150, 0); static const char * const ml26124_companding[] = {"16bit PCM", "u-law", "A-law"}; -static const struct soc_enum ml26124_adc_companding_enum - = SOC_ENUM_SINGLE(ML26124_SAI_TRANS_CTL, 6, 3, ml26124_companding); +static SOC_ENUM_SINGLE_DECL(ml26124_adc_companding_enum, + ML26124_SAI_TRANS_CTL, 6, ml26124_companding); -static const struct soc_enum ml26124_dac_companding_enum - = SOC_ENUM_SINGLE(ML26124_SAI_RCV_CTL, 6, 3, ml26124_companding); +static SOC_ENUM_SINGLE_DECL(ml26124_dac_companding_enum, + ML26124_SAI_RCV_CTL, 6, ml26124_companding); static const struct snd_kcontrol_new ml26124_snd_controls[] = { SOC_SINGLE_TLV("Capture Digital Volume", ML26124_RECORD_DIG_VOL, 0, @@ -136,8 +136,8 @@ static const struct snd_kcontrol_new ml26124_output_mixer_controls[] = { static const char * const ml26124_input_select[] = {"Analog MIC SingleEnded in", "Digital MIC in", "Analog MIC Differential in"}; -static const struct soc_enum ml26124_insel_enum = - SOC_ENUM_SINGLE(ML26124_MIC_IF_CTL, 0, 3, ml26124_input_select); +static SOC_ENUM_SINGLE_DECL(ml26124_insel_enum, + ML26124_MIC_IF_CTL, 0, ml26124_input_select); static const struct snd_kcontrol_new ml26124_input_mux_controls = SOC_DAPM_ENUM("Input Select", ml26124_insel_enum); @@ -586,16 +586,6 @@ static int ml26124_resume(struct snd_soc_codec *codec) static int ml26124_probe(struct snd_soc_codec *codec) { - int ret; - struct ml26124_priv *priv = snd_soc_codec_get_drvdata(codec); - codec->control_data = priv->regmap; - - ret = snd_soc_codec_set_cache_io(codec, 7, 9, SND_SOC_REGMAP); - if (ret < 0) { - dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); - return ret; - } - /* Software Reset */ snd_soc_update_bits(codec, ML26124_SW_RST, 0x01, 1); snd_soc_update_bits(codec, ML26124_SW_RST, 0x01, 0); diff --git a/sound/soc/codecs/pcm1681.c b/sound/soc/codecs/pcm1681.c index 73f9c3630e2..e427544183d 100644 --- a/sound/soc/codecs/pcm1681.c +++ b/sound/soc/codecs/pcm1681.c @@ -172,16 +172,21 @@ static int pcm1681_hw_params(struct snd_pcm_substream *substream, struct snd_soc_codec *codec = dai->codec; struct pcm1681_private *priv = snd_soc_codec_get_drvdata(codec); int val = 0, ret; - int pcm_format = params_format(params); priv->rate = params_rate(params); switch (priv->format & SND_SOC_DAIFMT_FORMAT_MASK) { case SND_SOC_DAIFMT_RIGHT_J: - if (pcm_format == SNDRV_PCM_FORMAT_S24_LE) - val = 0x00; - else if (pcm_format == SNDRV_PCM_FORMAT_S16_LE) - val = 0x03; + switch (params_width(params)) { + case 24: + val = 0; + break; + case 16: + val = 3; + break; + default: + return -EINVAL; + } break; case SND_SOC_DAIFMT_I2S: val = 0x04; diff --git a/sound/soc/codecs/pcm1792a.c b/sound/soc/codecs/pcm1792a.c index 7146653a8e1..3a80ba4452d 100644 --- a/sound/soc/codecs/pcm1792a.c +++ b/sound/soc/codecs/pcm1792a.c @@ -107,24 +107,35 @@ static int pcm1792a_hw_params(struct snd_pcm_substream *substream, struct snd_soc_codec *codec = dai->codec; struct pcm1792a_private *priv = snd_soc_codec_get_drvdata(codec); int val = 0, ret; - int pcm_format = params_format(params); priv->rate = params_rate(params); switch (priv->format & SND_SOC_DAIFMT_FORMAT_MASK) { case SND_SOC_DAIFMT_RIGHT_J: - if (pcm_format == SNDRV_PCM_FORMAT_S24_LE || - pcm_format == SNDRV_PCM_FORMAT_S32_LE) - val = 0x02; - else if (pcm_format == SNDRV_PCM_FORMAT_S16_LE) - val = 0x00; + switch (params_width(params)) { + case 24: + case 32: + val = 2; + break; + case 16: + val = 0; + break; + default: + return -EINVAL; + } break; case SND_SOC_DAIFMT_I2S: - if (pcm_format == SNDRV_PCM_FORMAT_S24_LE || - pcm_format == SNDRV_PCM_FORMAT_S32_LE) - val = 0x05; - else if (pcm_format == SNDRV_PCM_FORMAT_S16_LE) - val = 0x04; + switch (params_width(params)) { + case 24: + case 32: + val = 5; + break; + case 16: + val = 4; + break; + default: + return -EINVAL; + } break; default: dev_err(codec->dev, "Invalid DAI format\n"); diff --git a/sound/soc/codecs/pcm512x-i2c.c b/sound/soc/codecs/pcm512x-i2c.c new file mode 100644 index 00000000000..4d62230bd37 --- /dev/null +++ b/sound/soc/codecs/pcm512x-i2c.c @@ -0,0 +1,71 @@ +/* + * Driver for the PCM512x CODECs + * + * Author: Mark Brown <broonie@linaro.org> + * Copyright 2014 Linaro Ltd + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + */ + +#include <linux/init.h> +#include <linux/module.h> +#include <linux/i2c.h> + +#include "pcm512x.h" + +static int pcm512x_i2c_probe(struct i2c_client *i2c, + const struct i2c_device_id *id) +{ + struct regmap *regmap; + + regmap = devm_regmap_init_i2c(i2c, &pcm512x_regmap); + if (IS_ERR(regmap)) + return PTR_ERR(regmap); + + return pcm512x_probe(&i2c->dev, regmap); +} + +static int pcm512x_i2c_remove(struct i2c_client *i2c) +{ + pcm512x_remove(&i2c->dev); + return 0; +} + +static const struct i2c_device_id pcm512x_i2c_id[] = { + { "pcm5121", }, + { "pcm5122", }, + { } +}; +MODULE_DEVICE_TABLE(i2c, pcm512x_i2c_id); + +static const struct of_device_id pcm512x_of_match[] = { + { .compatible = "ti,pcm5121", }, + { .compatible = "ti,pcm5122", }, + { } +}; +MODULE_DEVICE_TABLE(of, pcm512x_of_match); + +static struct i2c_driver pcm512x_i2c_driver = { + .probe = pcm512x_i2c_probe, + .remove = pcm512x_i2c_remove, + .id_table = pcm512x_i2c_id, + .driver = { + .name = "pcm512x", + .owner = THIS_MODULE, + .of_match_table = pcm512x_of_match, + .pm = &pcm512x_pm_ops, + }, +}; + +module_i2c_driver(pcm512x_i2c_driver); + +MODULE_DESCRIPTION("ASoC PCM512x codec driver - I2C"); +MODULE_AUTHOR("Mark Brown <broonie@linaro.org>"); +MODULE_LICENSE("GPL v2"); diff --git a/sound/soc/codecs/pcm512x-spi.c b/sound/soc/codecs/pcm512x-spi.c new file mode 100644 index 00000000000..f297058c003 --- /dev/null +++ b/sound/soc/codecs/pcm512x-spi.c @@ -0,0 +1,69 @@ +/* + * Driver for the PCM512x CODECs + * + * Author: Mark Brown <broonie@linaro.org> + * Copyright 2014 Linaro Ltd + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + */ + +#include <linux/init.h> +#include <linux/module.h> +#include <linux/spi/spi.h> + +#include "pcm512x.h" + +static int pcm512x_spi_probe(struct spi_device *spi) +{ + struct regmap *regmap; + int ret; + + regmap = devm_regmap_init_spi(spi, &pcm512x_regmap); + if (IS_ERR(regmap)) { + ret = PTR_ERR(regmap); + return ret; + } + + return pcm512x_probe(&spi->dev, regmap); +} + +static int pcm512x_spi_remove(struct spi_device *spi) +{ + pcm512x_remove(&spi->dev); + return 0; +} + +static const struct spi_device_id pcm512x_spi_id[] = { + { "pcm5121", }, + { "pcm5122", }, + { }, +}; +MODULE_DEVICE_TABLE(spi, pcm512x_spi_id); + +static const struct of_device_id pcm512x_of_match[] = { + { .compatible = "ti,pcm5121", }, + { .compatible = "ti,pcm5122", }, + { } +}; +MODULE_DEVICE_TABLE(of, pcm512x_of_match); + +static struct spi_driver pcm512x_spi_driver = { + .probe = pcm512x_spi_probe, + .remove = pcm512x_spi_remove, + .id_table = pcm512x_spi_id, + .driver = { + .name = "pcm512x", + .owner = THIS_MODULE, + .of_match_table = pcm512x_of_match, + .pm = &pcm512x_pm_ops, + }, +}; + +module_spi_driver(pcm512x_spi_driver); diff --git a/sound/soc/codecs/pcm512x.c b/sound/soc/codecs/pcm512x.c new file mode 100644 index 00000000000..4b4c0c7bb91 --- /dev/null +++ b/sound/soc/codecs/pcm512x.c @@ -0,0 +1,589 @@ +/* + * Driver for the PCM512x CODECs + * + * Author: Mark Brown <broonie@linaro.org> + * Copyright 2014 Linaro Ltd + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + */ + + +#include <linux/init.h> +#include <linux/module.h> +#include <linux/clk.h> +#include <linux/pm_runtime.h> +#include <linux/regmap.h> +#include <linux/regulator/consumer.h> +#include <sound/soc.h> +#include <sound/soc-dapm.h> +#include <sound/tlv.h> + +#include "pcm512x.h" + +#define PCM512x_NUM_SUPPLIES 3 +static const char * const pcm512x_supply_names[PCM512x_NUM_SUPPLIES] = { + "AVDD", + "DVDD", + "CPVDD", +}; + +struct pcm512x_priv { + struct regmap *regmap; + struct clk *sclk; + struct regulator_bulk_data supplies[PCM512x_NUM_SUPPLIES]; + struct notifier_block supply_nb[PCM512x_NUM_SUPPLIES]; +}; + +/* + * We can't use the same notifier block for more than one supply and + * there's no way I can see to get from a callback to the caller + * except container_of(). + */ +#define PCM512x_REGULATOR_EVENT(n) \ +static int pcm512x_regulator_event_##n(struct notifier_block *nb, \ + unsigned long event, void *data) \ +{ \ + struct pcm512x_priv *pcm512x = container_of(nb, struct pcm512x_priv, \ + supply_nb[n]); \ + if (event & REGULATOR_EVENT_DISABLE) { \ + regcache_mark_dirty(pcm512x->regmap); \ + regcache_cache_only(pcm512x->regmap, true); \ + } \ + return 0; \ +} + +PCM512x_REGULATOR_EVENT(0) +PCM512x_REGULATOR_EVENT(1) +PCM512x_REGULATOR_EVENT(2) + +static const struct reg_default pcm512x_reg_defaults[] = { + { PCM512x_RESET, 0x00 }, + { PCM512x_POWER, 0x00 }, + { PCM512x_MUTE, 0x00 }, + { PCM512x_DSP, 0x00 }, + { PCM512x_PLL_REF, 0x00 }, + { PCM512x_DAC_ROUTING, 0x11 }, + { PCM512x_DSP_PROGRAM, 0x01 }, + { PCM512x_CLKDET, 0x00 }, + { PCM512x_AUTO_MUTE, 0x00 }, + { PCM512x_ERROR_DETECT, 0x00 }, + { PCM512x_DIGITAL_VOLUME_1, 0x00 }, + { PCM512x_DIGITAL_VOLUME_2, 0x30 }, + { PCM512x_DIGITAL_VOLUME_3, 0x30 }, + { PCM512x_DIGITAL_MUTE_1, 0x22 }, + { PCM512x_DIGITAL_MUTE_2, 0x00 }, + { PCM512x_DIGITAL_MUTE_3, 0x07 }, + { PCM512x_OUTPUT_AMPLITUDE, 0x00 }, + { PCM512x_ANALOG_GAIN_CTRL, 0x00 }, + { PCM512x_UNDERVOLTAGE_PROT, 0x00 }, + { PCM512x_ANALOG_MUTE_CTRL, 0x00 }, + { PCM512x_ANALOG_GAIN_BOOST, 0x00 }, + { PCM512x_VCOM_CTRL_1, 0x00 }, + { PCM512x_VCOM_CTRL_2, 0x01 }, +}; + +static bool pcm512x_readable(struct device *dev, unsigned int reg) +{ + switch (reg) { + case PCM512x_RESET: + case PCM512x_POWER: + case PCM512x_MUTE: + case PCM512x_PLL_EN: + case PCM512x_SPI_MISO_FUNCTION: + case PCM512x_DSP: + case PCM512x_GPIO_EN: + case PCM512x_BCLK_LRCLK_CFG: + case PCM512x_DSP_GPIO_INPUT: + case PCM512x_MASTER_MODE: + case PCM512x_PLL_REF: + case PCM512x_PLL_COEFF_0: + case PCM512x_PLL_COEFF_1: + case PCM512x_PLL_COEFF_2: + case PCM512x_PLL_COEFF_3: + case PCM512x_PLL_COEFF_4: + case PCM512x_DSP_CLKDIV: + case PCM512x_DAC_CLKDIV: + case PCM512x_NCP_CLKDIV: + case PCM512x_OSR_CLKDIV: + case PCM512x_MASTER_CLKDIV_1: + case PCM512x_MASTER_CLKDIV_2: + case PCM512x_FS_SPEED_MODE: + case PCM512x_IDAC_1: + case PCM512x_IDAC_2: + case PCM512x_ERROR_DETECT: + case PCM512x_I2S_1: + case PCM512x_I2S_2: + case PCM512x_DAC_ROUTING: + case PCM512x_DSP_PROGRAM: + case PCM512x_CLKDET: + case PCM512x_AUTO_MUTE: + case PCM512x_DIGITAL_VOLUME_1: + case PCM512x_DIGITAL_VOLUME_2: + case PCM512x_DIGITAL_VOLUME_3: + case PCM512x_DIGITAL_MUTE_1: + case PCM512x_DIGITAL_MUTE_2: + case PCM512x_DIGITAL_MUTE_3: + case PCM512x_GPIO_OUTPUT_1: + case PCM512x_GPIO_OUTPUT_2: + case PCM512x_GPIO_OUTPUT_3: + case PCM512x_GPIO_OUTPUT_4: + case PCM512x_GPIO_OUTPUT_5: + case PCM512x_GPIO_OUTPUT_6: + case PCM512x_GPIO_CONTROL_1: + case PCM512x_GPIO_CONTROL_2: + case PCM512x_OVERFLOW: + case PCM512x_RATE_DET_1: + case PCM512x_RATE_DET_2: + case PCM512x_RATE_DET_3: + case PCM512x_RATE_DET_4: + case PCM512x_ANALOG_MUTE_DET: + case PCM512x_GPIN: + case PCM512x_DIGITAL_MUTE_DET: + case PCM512x_OUTPUT_AMPLITUDE: + case PCM512x_ANALOG_GAIN_CTRL: + case PCM512x_UNDERVOLTAGE_PROT: + case PCM512x_ANALOG_MUTE_CTRL: + case PCM512x_ANALOG_GAIN_BOOST: + case PCM512x_VCOM_CTRL_1: + case PCM512x_VCOM_CTRL_2: + case PCM512x_CRAM_CTRL: + return true; + default: + /* There are 256 raw register addresses */ + return reg < 0xff; + } +} + +static bool pcm512x_volatile(struct device *dev, unsigned int reg) +{ + switch (reg) { + case PCM512x_PLL_EN: + case PCM512x_OVERFLOW: + case PCM512x_RATE_DET_1: + case PCM512x_RATE_DET_2: + case PCM512x_RATE_DET_3: + case PCM512x_RATE_DET_4: + case PCM512x_ANALOG_MUTE_DET: + case PCM512x_GPIN: + case PCM512x_DIGITAL_MUTE_DET: + case PCM512x_CRAM_CTRL: + return true; + default: + /* There are 256 raw register addresses */ + return reg < 0xff; + } +} + +static const DECLARE_TLV_DB_SCALE(digital_tlv, -10350, 50, 1); +static const DECLARE_TLV_DB_SCALE(analog_tlv, -600, 600, 0); +static const DECLARE_TLV_DB_SCALE(boost_tlv, 0, 80, 0); + +static const char * const pcm512x_dsp_program_texts[] = { + "FIR interpolation with de-emphasis", + "Low latency IIR with de-emphasis", + "Fixed process flow", + "High attenuation with de-emphasis", + "Ringing-less low latency FIR", +}; + +static const unsigned int pcm512x_dsp_program_values[] = { + 1, + 2, + 3, + 5, + 7, +}; + +static SOC_VALUE_ENUM_SINGLE_DECL(pcm512x_dsp_program, + PCM512x_DSP_PROGRAM, 0, 0x1f, + pcm512x_dsp_program_texts, + pcm512x_dsp_program_values); + +static const char * const pcm512x_clk_missing_text[] = { + "1s", "2s", "3s", "4s", "5s", "6s", "7s", "8s" +}; + +static const struct soc_enum pcm512x_clk_missing = + SOC_ENUM_SINGLE(PCM512x_CLKDET, 0, 8, pcm512x_clk_missing_text); + +static const char * const pcm512x_autom_text[] = { + "21ms", "106ms", "213ms", "533ms", "1.07s", "2.13s", "5.33s", "10.66s" +}; + +static const struct soc_enum pcm512x_autom_l = + SOC_ENUM_SINGLE(PCM512x_AUTO_MUTE, PCM512x_ATML_SHIFT, 8, + pcm512x_autom_text); + +static const struct soc_enum pcm512x_autom_r = + SOC_ENUM_SINGLE(PCM512x_AUTO_MUTE, PCM512x_ATMR_SHIFT, 8, + pcm512x_autom_text); + +static const char * const pcm512x_ramp_rate_text[] = { + "1 sample/update", "2 samples/update", "4 samples/update", + "Immediate" +}; + +static const struct soc_enum pcm512x_vndf = + SOC_ENUM_SINGLE(PCM512x_DIGITAL_MUTE_1, PCM512x_VNDF_SHIFT, 4, + pcm512x_ramp_rate_text); + +static const struct soc_enum pcm512x_vnuf = + SOC_ENUM_SINGLE(PCM512x_DIGITAL_MUTE_1, PCM512x_VNUF_SHIFT, 4, + pcm512x_ramp_rate_text); + +static const struct soc_enum pcm512x_vedf = + SOC_ENUM_SINGLE(PCM512x_DIGITAL_MUTE_2, PCM512x_VEDF_SHIFT, 4, + pcm512x_ramp_rate_text); + +static const char * const pcm512x_ramp_step_text[] = { + "4dB/step", "2dB/step", "1dB/step", "0.5dB/step" +}; + +static const struct soc_enum pcm512x_vnds = + SOC_ENUM_SINGLE(PCM512x_DIGITAL_MUTE_1, PCM512x_VNDS_SHIFT, 4, + pcm512x_ramp_step_text); + +static const struct soc_enum pcm512x_vnus = + SOC_ENUM_SINGLE(PCM512x_DIGITAL_MUTE_1, PCM512x_VNUS_SHIFT, 4, + pcm512x_ramp_step_text); + +static const struct soc_enum pcm512x_veds = + SOC_ENUM_SINGLE(PCM512x_DIGITAL_MUTE_2, PCM512x_VEDS_SHIFT, 4, + pcm512x_ramp_step_text); + +static const struct snd_kcontrol_new pcm512x_controls[] = { +SOC_DOUBLE_R_TLV("Playback Digital Volume", PCM512x_DIGITAL_VOLUME_2, + PCM512x_DIGITAL_VOLUME_3, 0, 255, 1, digital_tlv), +SOC_DOUBLE_TLV("Playback Volume", PCM512x_ANALOG_GAIN_CTRL, + PCM512x_LAGN_SHIFT, PCM512x_RAGN_SHIFT, 1, 1, analog_tlv), +SOC_DOUBLE_TLV("Playback Boost Volume", PCM512x_ANALOG_GAIN_BOOST, + PCM512x_AGBL_SHIFT, PCM512x_AGBR_SHIFT, 1, 0, boost_tlv), +SOC_DOUBLE("Playback Digital Switch", PCM512x_MUTE, PCM512x_RQML_SHIFT, + PCM512x_RQMR_SHIFT, 1, 1), + +SOC_SINGLE("Deemphasis Switch", PCM512x_DSP, PCM512x_DEMP_SHIFT, 1, 1), +SOC_VALUE_ENUM("DSP Program", pcm512x_dsp_program), + +SOC_ENUM("Clock Missing Period", pcm512x_clk_missing), +SOC_ENUM("Auto Mute Time Left", pcm512x_autom_l), +SOC_ENUM("Auto Mute Time Right", pcm512x_autom_r), +SOC_SINGLE("Auto Mute Mono Switch", PCM512x_DIGITAL_MUTE_3, + PCM512x_ACTL_SHIFT, 1, 0), +SOC_DOUBLE("Auto Mute Switch", PCM512x_DIGITAL_MUTE_3, PCM512x_AMLE_SHIFT, + PCM512x_AMLR_SHIFT, 1, 0), + +SOC_ENUM("Volume Ramp Down Rate", pcm512x_vndf), +SOC_ENUM("Volume Ramp Down Step", pcm512x_vnds), +SOC_ENUM("Volume Ramp Up Rate", pcm512x_vnuf), +SOC_ENUM("Volume Ramp Up Step", pcm512x_vnus), +SOC_ENUM("Volume Ramp Down Emergency Rate", pcm512x_vedf), +SOC_ENUM("Volume Ramp Down Emergency Step", pcm512x_veds), +}; + +static const struct snd_soc_dapm_widget pcm512x_dapm_widgets[] = { +SND_SOC_DAPM_DAC("DACL", NULL, SND_SOC_NOPM, 0, 0), +SND_SOC_DAPM_DAC("DACR", NULL, SND_SOC_NOPM, 0, 0), + +SND_SOC_DAPM_OUTPUT("OUTL"), +SND_SOC_DAPM_OUTPUT("OUTR"), +}; + +static const struct snd_soc_dapm_route pcm512x_dapm_routes[] = { + { "DACL", NULL, "Playback" }, + { "DACR", NULL, "Playback" }, + + { "OUTL", NULL, "DACL" }, + { "OUTR", NULL, "DACR" }, +}; + +static int pcm512x_set_bias_level(struct snd_soc_codec *codec, + enum snd_soc_bias_level level) +{ + struct pcm512x_priv *pcm512x = dev_get_drvdata(codec->dev); + int ret; + + switch (level) { + case SND_SOC_BIAS_ON: + case SND_SOC_BIAS_PREPARE: + break; + + case SND_SOC_BIAS_STANDBY: + ret = regmap_update_bits(pcm512x->regmap, PCM512x_POWER, + PCM512x_RQST, 0); + if (ret != 0) { + dev_err(codec->dev, "Failed to remove standby: %d\n", + ret); + return ret; + } + break; + + case SND_SOC_BIAS_OFF: + ret = regmap_update_bits(pcm512x->regmap, PCM512x_POWER, + PCM512x_RQST, PCM512x_RQST); + if (ret != 0) { + dev_err(codec->dev, "Failed to request standby: %d\n", + ret); + return ret; + } + break; + } + + codec->dapm.bias_level = level; + + return 0; +} + +static struct snd_soc_dai_driver pcm512x_dai = { + .name = "pcm512x-hifi", + .playback = { + .stream_name = "Playback", + .channels_min = 2, + .channels_max = 2, + .rates = SNDRV_PCM_RATE_8000_192000, + .formats = SNDRV_PCM_FMTBIT_S16_LE | + SNDRV_PCM_FMTBIT_S24_LE | + SNDRV_PCM_FMTBIT_S32_LE + }, +}; + +static struct snd_soc_codec_driver pcm512x_codec_driver = { + .set_bias_level = pcm512x_set_bias_level, + .idle_bias_off = true, + + .controls = pcm512x_controls, + .num_controls = ARRAY_SIZE(pcm512x_controls), + .dapm_widgets = pcm512x_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(pcm512x_dapm_widgets), + .dapm_routes = pcm512x_dapm_routes, + .num_dapm_routes = ARRAY_SIZE(pcm512x_dapm_routes), +}; + +static const struct regmap_range_cfg pcm512x_range = { + .name = "Pages", .range_min = PCM512x_VIRT_BASE, + .range_max = PCM512x_MAX_REGISTER, + .selector_reg = PCM512x_PAGE, + .selector_mask = 0xff, + .window_start = 0, .window_len = 0x100, +}; + +const struct regmap_config pcm512x_regmap = { + .reg_bits = 8, + .val_bits = 8, + + .readable_reg = pcm512x_readable, + .volatile_reg = pcm512x_volatile, + + .ranges = &pcm512x_range, + .num_ranges = 1, + + .max_register = PCM512x_MAX_REGISTER, + .reg_defaults = pcm512x_reg_defaults, + .num_reg_defaults = ARRAY_SIZE(pcm512x_reg_defaults), + .cache_type = REGCACHE_RBTREE, +}; +EXPORT_SYMBOL_GPL(pcm512x_regmap); + +int pcm512x_probe(struct device *dev, struct regmap *regmap) +{ + struct pcm512x_priv *pcm512x; + int i, ret; + + pcm512x = devm_kzalloc(dev, sizeof(struct pcm512x_priv), GFP_KERNEL); + if (!pcm512x) + return -ENOMEM; + + dev_set_drvdata(dev, pcm512x); + pcm512x->regmap = regmap; + + for (i = 0; i < ARRAY_SIZE(pcm512x->supplies); i++) + pcm512x->supplies[i].supply = pcm512x_supply_names[i]; + + ret = devm_regulator_bulk_get(dev, ARRAY_SIZE(pcm512x->supplies), + pcm512x->supplies); + if (ret != 0) { + dev_err(dev, "Failed to get supplies: %d\n", ret); + return ret; + } + + pcm512x->supply_nb[0].notifier_call = pcm512x_regulator_event_0; + pcm512x->supply_nb[1].notifier_call = pcm512x_regulator_event_1; + pcm512x->supply_nb[2].notifier_call = pcm512x_regulator_event_2; + + for (i = 0; i < ARRAY_SIZE(pcm512x->supplies); i++) { + ret = regulator_register_notifier(pcm512x->supplies[i].consumer, + &pcm512x->supply_nb[i]); + if (ret != 0) { + dev_err(dev, + "Failed to register regulator notifier: %d\n", + ret); + } + } + + ret = regulator_bulk_enable(ARRAY_SIZE(pcm512x->supplies), + pcm512x->supplies); + if (ret != 0) { + dev_err(dev, "Failed to enable supplies: %d\n", ret); + return ret; + } + + /* Reset the device, verifying I/O in the process for I2C */ + ret = regmap_write(regmap, PCM512x_RESET, + PCM512x_RSTM | PCM512x_RSTR); + if (ret != 0) { + dev_err(dev, "Failed to reset device: %d\n", ret); + goto err; + } + + ret = regmap_write(regmap, PCM512x_RESET, 0); + if (ret != 0) { + dev_err(dev, "Failed to reset device: %d\n", ret); + goto err; + } + + pcm512x->sclk = devm_clk_get(dev, NULL); + if (IS_ERR(pcm512x->sclk)) { + if (PTR_ERR(pcm512x->sclk) == -EPROBE_DEFER) + return -EPROBE_DEFER; + + dev_info(dev, "No SCLK, using BCLK: %ld\n", + PTR_ERR(pcm512x->sclk)); + + /* Disable reporting of missing SCLK as an error */ + regmap_update_bits(regmap, PCM512x_ERROR_DETECT, + PCM512x_IDCH, PCM512x_IDCH); + + /* Switch PLL input to BCLK */ + regmap_update_bits(regmap, PCM512x_PLL_REF, + PCM512x_SREF, PCM512x_SREF); + } else { + ret = clk_prepare_enable(pcm512x->sclk); + if (ret != 0) { + dev_err(dev, "Failed to enable SCLK: %d\n", ret); + return ret; + } + } + + /* Default to standby mode */ + ret = regmap_update_bits(pcm512x->regmap, PCM512x_POWER, + PCM512x_RQST, PCM512x_RQST); + if (ret != 0) { + dev_err(dev, "Failed to request standby: %d\n", + ret); + goto err_clk; + } + + pm_runtime_set_active(dev); + pm_runtime_enable(dev); + pm_runtime_idle(dev); + + ret = snd_soc_register_codec(dev, &pcm512x_codec_driver, + &pcm512x_dai, 1); + if (ret != 0) { + dev_err(dev, "Failed to register CODEC: %d\n", ret); + goto err_pm; + } + + return 0; + +err_pm: + pm_runtime_disable(dev); +err_clk: + if (!IS_ERR(pcm512x->sclk)) + clk_disable_unprepare(pcm512x->sclk); +err: + regulator_bulk_disable(ARRAY_SIZE(pcm512x->supplies), + pcm512x->supplies); + return ret; +} +EXPORT_SYMBOL_GPL(pcm512x_probe); + +void pcm512x_remove(struct device *dev) +{ + struct pcm512x_priv *pcm512x = dev_get_drvdata(dev); + + snd_soc_unregister_codec(dev); + pm_runtime_disable(dev); + if (!IS_ERR(pcm512x->sclk)) + clk_disable_unprepare(pcm512x->sclk); + regulator_bulk_disable(ARRAY_SIZE(pcm512x->supplies), + pcm512x->supplies); +} +EXPORT_SYMBOL_GPL(pcm512x_remove); + +static int pcm512x_suspend(struct device *dev) +{ + struct pcm512x_priv *pcm512x = dev_get_drvdata(dev); + int ret; + + ret = regmap_update_bits(pcm512x->regmap, PCM512x_POWER, + PCM512x_RQPD, PCM512x_RQPD); + if (ret != 0) { + dev_err(dev, "Failed to request power down: %d\n", ret); + return ret; + } + + ret = regulator_bulk_disable(ARRAY_SIZE(pcm512x->supplies), + pcm512x->supplies); + if (ret != 0) { + dev_err(dev, "Failed to disable supplies: %d\n", ret); + return ret; + } + + if (!IS_ERR(pcm512x->sclk)) + clk_disable_unprepare(pcm512x->sclk); + + return 0; +} + +static int pcm512x_resume(struct device *dev) +{ + struct pcm512x_priv *pcm512x = dev_get_drvdata(dev); + int ret; + + if (!IS_ERR(pcm512x->sclk)) { + ret = clk_prepare_enable(pcm512x->sclk); + if (ret != 0) { + dev_err(dev, "Failed to enable SCLK: %d\n", ret); + return ret; + } + } + + ret = regulator_bulk_enable(ARRAY_SIZE(pcm512x->supplies), + pcm512x->supplies); + if (ret != 0) { + dev_err(dev, "Failed to enable supplies: %d\n", ret); + return ret; + } + + regcache_cache_only(pcm512x->regmap, false); + ret = regcache_sync(pcm512x->regmap); + if (ret != 0) { + dev_err(dev, "Failed to sync cache: %d\n", ret); + return ret; + } + + ret = regmap_update_bits(pcm512x->regmap, PCM512x_POWER, + PCM512x_RQPD, 0); + if (ret != 0) { + dev_err(dev, "Failed to remove power down: %d\n", ret); + return ret; + } + + return 0; +} + +const struct dev_pm_ops pcm512x_pm_ops = { + SET_RUNTIME_PM_OPS(pcm512x_suspend, pcm512x_resume, NULL) +}; +EXPORT_SYMBOL_GPL(pcm512x_pm_ops); + +MODULE_DESCRIPTION("ASoC PCM512x codec driver"); +MODULE_AUTHOR("Mark Brown <broonie@linaro.org>"); +MODULE_LICENSE("GPL v2"); diff --git a/sound/soc/codecs/pcm512x.h b/sound/soc/codecs/pcm512x.h new file mode 100644 index 00000000000..6ee76aaca09 --- /dev/null +++ b/sound/soc/codecs/pcm512x.h @@ -0,0 +1,171 @@ +/* + * Driver for the PCM512x CODECs + * + * Author: Mark Brown <broonie@linaro.org> + * Copyright 2014 Linaro Ltd + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + */ + +#ifndef _SND_SOC_PCM512X +#define _SND_SOC_PCM512X + +#include <linux/pm.h> +#include <linux/regmap.h> + +#define PCM512x_VIRT_BASE 0x100 +#define PCM512x_PAGE_LEN 0x100 +#define PCM512x_PAGE_BASE(n) (PCM512x_VIRT_BASE + (PCM512x_PAGE_LEN * n)) + +#define PCM512x_PAGE 0 + +#define PCM512x_RESET (PCM512x_PAGE_BASE(0) + 1) +#define PCM512x_POWER (PCM512x_PAGE_BASE(0) + 2) +#define PCM512x_MUTE (PCM512x_PAGE_BASE(0) + 3) +#define PCM512x_PLL_EN (PCM512x_PAGE_BASE(0) + 4) +#define PCM512x_SPI_MISO_FUNCTION (PCM512x_PAGE_BASE(0) + 6) +#define PCM512x_DSP (PCM512x_PAGE_BASE(0) + 7) +#define PCM512x_GPIO_EN (PCM512x_PAGE_BASE(0) + 8) +#define PCM512x_BCLK_LRCLK_CFG (PCM512x_PAGE_BASE(0) + 9) +#define PCM512x_DSP_GPIO_INPUT (PCM512x_PAGE_BASE(0) + 10) +#define PCM512x_MASTER_MODE (PCM512x_PAGE_BASE(0) + 12) +#define PCM512x_PLL_REF (PCM512x_PAGE_BASE(0) + 13) +#define PCM512x_PLL_COEFF_0 (PCM512x_PAGE_BASE(0) + 20) +#define PCM512x_PLL_COEFF_1 (PCM512x_PAGE_BASE(0) + 21) +#define PCM512x_PLL_COEFF_2 (PCM512x_PAGE_BASE(0) + 22) +#define PCM512x_PLL_COEFF_3 (PCM512x_PAGE_BASE(0) + 23) +#define PCM512x_PLL_COEFF_4 (PCM512x_PAGE_BASE(0) + 24) +#define PCM512x_DSP_CLKDIV (PCM512x_PAGE_BASE(0) + 27) +#define PCM512x_DAC_CLKDIV (PCM512x_PAGE_BASE(0) + 28) +#define PCM512x_NCP_CLKDIV (PCM512x_PAGE_BASE(0) + 29) +#define PCM512x_OSR_CLKDIV (PCM512x_PAGE_BASE(0) + 30) +#define PCM512x_MASTER_CLKDIV_1 (PCM512x_PAGE_BASE(0) + 32) +#define PCM512x_MASTER_CLKDIV_2 (PCM512x_PAGE_BASE(0) + 33) +#define PCM512x_FS_SPEED_MODE (PCM512x_PAGE_BASE(0) + 34) +#define PCM512x_IDAC_1 (PCM512x_PAGE_BASE(0) + 35) +#define PCM512x_IDAC_2 (PCM512x_PAGE_BASE(0) + 36) +#define PCM512x_ERROR_DETECT (PCM512x_PAGE_BASE(0) + 37) +#define PCM512x_I2S_1 (PCM512x_PAGE_BASE(0) + 40) +#define PCM512x_I2S_2 (PCM512x_PAGE_BASE(0) + 41) +#define PCM512x_DAC_ROUTING (PCM512x_PAGE_BASE(0) + 42) +#define PCM512x_DSP_PROGRAM (PCM512x_PAGE_BASE(0) + 43) +#define PCM512x_CLKDET (PCM512x_PAGE_BASE(0) + 44) +#define PCM512x_AUTO_MUTE (PCM512x_PAGE_BASE(0) + 59) +#define PCM512x_DIGITAL_VOLUME_1 (PCM512x_PAGE_BASE(0) + 60) +#define PCM512x_DIGITAL_VOLUME_2 (PCM512x_PAGE_BASE(0) + 61) +#define PCM512x_DIGITAL_VOLUME_3 (PCM512x_PAGE_BASE(0) + 62) +#define PCM512x_DIGITAL_MUTE_1 (PCM512x_PAGE_BASE(0) + 63) +#define PCM512x_DIGITAL_MUTE_2 (PCM512x_PAGE_BASE(0) + 64) +#define PCM512x_DIGITAL_MUTE_3 (PCM512x_PAGE_BASE(0) + 65) +#define PCM512x_GPIO_OUTPUT_1 (PCM512x_PAGE_BASE(0) + 80) +#define PCM512x_GPIO_OUTPUT_2 (PCM512x_PAGE_BASE(0) + 81) +#define PCM512x_GPIO_OUTPUT_3 (PCM512x_PAGE_BASE(0) + 82) +#define PCM512x_GPIO_OUTPUT_4 (PCM512x_PAGE_BASE(0) + 83) +#define PCM512x_GPIO_OUTPUT_5 (PCM512x_PAGE_BASE(0) + 84) +#define PCM512x_GPIO_OUTPUT_6 (PCM512x_PAGE_BASE(0) + 85) +#define PCM512x_GPIO_CONTROL_1 (PCM512x_PAGE_BASE(0) + 86) +#define PCM512x_GPIO_CONTROL_2 (PCM512x_PAGE_BASE(0) + 87) +#define PCM512x_OVERFLOW (PCM512x_PAGE_BASE(0) + 90) +#define PCM512x_RATE_DET_1 (PCM512x_PAGE_BASE(0) + 91) +#define PCM512x_RATE_DET_2 (PCM512x_PAGE_BASE(0) + 92) +#define PCM512x_RATE_DET_3 (PCM512x_PAGE_BASE(0) + 93) +#define PCM512x_RATE_DET_4 (PCM512x_PAGE_BASE(0) + 94) +#define PCM512x_ANALOG_MUTE_DET (PCM512x_PAGE_BASE(0) + 108) +#define PCM512x_GPIN (PCM512x_PAGE_BASE(0) + 119) +#define PCM512x_DIGITAL_MUTE_DET (PCM512x_PAGE_BASE(0) + 120) + +#define PCM512x_OUTPUT_AMPLITUDE (PCM512x_PAGE_BASE(1) + 1) +#define PCM512x_ANALOG_GAIN_CTRL (PCM512x_PAGE_BASE(1) + 2) +#define PCM512x_UNDERVOLTAGE_PROT (PCM512x_PAGE_BASE(1) + 5) +#define PCM512x_ANALOG_MUTE_CTRL (PCM512x_PAGE_BASE(1) + 6) +#define PCM512x_ANALOG_GAIN_BOOST (PCM512x_PAGE_BASE(1) + 7) +#define PCM512x_VCOM_CTRL_1 (PCM512x_PAGE_BASE(1) + 8) +#define PCM512x_VCOM_CTRL_2 (PCM512x_PAGE_BASE(1) + 9) + +#define PCM512x_CRAM_CTRL (PCM512x_PAGE_BASE(44) + 1) + +#define PCM512x_MAX_REGISTER (PCM512x_PAGE_BASE(44) + 1) + +/* Page 0, Register 1 - reset */ +#define PCM512x_RSTR (1 << 0) +#define PCM512x_RSTM (1 << 4) + +/* Page 0, Register 2 - power */ +#define PCM512x_RQPD (1 << 0) +#define PCM512x_RQPD_SHIFT 0 +#define PCM512x_RQST (1 << 4) +#define PCM512x_RQST_SHIFT 4 + +/* Page 0, Register 3 - mute */ +#define PCM512x_RQMR_SHIFT 0 +#define PCM512x_RQML_SHIFT 4 + +/* Page 0, Register 4 - PLL */ +#define PCM512x_PLCE (1 << 0) +#define PCM512x_RLCE_SHIFT 0 +#define PCM512x_PLCK (1 << 4) +#define PCM512x_PLCK_SHIFT 4 + +/* Page 0, Register 7 - DSP */ +#define PCM512x_SDSL (1 << 0) +#define PCM512x_SDSL_SHIFT 0 +#define PCM512x_DEMP (1 << 4) +#define PCM512x_DEMP_SHIFT 4 + +/* Page 0, Register 13 - PLL reference */ +#define PCM512x_SREF (1 << 4) + +/* Page 0, Register 37 - Error detection */ +#define PCM512x_IPLK (1 << 0) +#define PCM512x_DCAS (1 << 1) +#define PCM512x_IDCM (1 << 2) +#define PCM512x_IDCH (1 << 3) +#define PCM512x_IDSK (1 << 4) +#define PCM512x_IDBK (1 << 5) +#define PCM512x_IDFS (1 << 6) + +/* Page 0, Register 42 - DAC routing */ +#define PCM512x_AUPR_SHIFT 0 +#define PCM512x_AUPL_SHIFT 4 + +/* Page 0, Register 59 - auto mute */ +#define PCM512x_ATMR_SHIFT 0 +#define PCM512x_ATML_SHIFT 4 + +/* Page 0, Register 63 - ramp rates */ +#define PCM512x_VNDF_SHIFT 6 +#define PCM512x_VNDS_SHIFT 4 +#define PCM512x_VNUF_SHIFT 2 +#define PCM512x_VNUS_SHIFT 0 + +/* Page 0, Register 64 - emergency ramp rates */ +#define PCM512x_VEDF_SHIFT 6 +#define PCM512x_VEDS_SHIFT 4 + +/* Page 0, Register 65 - Digital mute enables */ +#define PCM512x_ACTL_SHIFT 2 +#define PCM512x_AMLE_SHIFT 1 +#define PCM512x_AMLR_SHIFT 0 + +/* Page 1, Register 2 - analog volume control */ +#define PCM512x_RAGN_SHIFT 0 +#define PCM512x_LAGN_SHIFT 4 + +/* Page 1, Register 7 - analog boost control */ +#define PCM512x_AGBR_SHIFT 0 +#define PCM512x_AGBL_SHIFT 4 + +extern const struct dev_pm_ops pcm512x_pm_ops; +extern const struct regmap_config pcm512x_regmap; + +int pcm512x_probe(struct device *dev, struct regmap *regmap); +void pcm512x_remove(struct device *dev); + +#endif diff --git a/sound/soc/codecs/rt5631.c b/sound/soc/codecs/rt5631.c index 912c9cbc272..d4c229f0233 100644 --- a/sound/soc/codecs/rt5631.c +++ b/sound/soc/codecs/rt5631.c @@ -210,26 +210,22 @@ static int rt5631_dmic_put(struct snd_kcontrol *kcontrol, static const char *rt5631_input_mode[] = { "Single ended", "Differential"}; -static const SOC_ENUM_SINGLE_DECL( - rt5631_mic1_mode_enum, RT5631_MIC_CTRL_1, - RT5631_MIC1_DIFF_INPUT_SHIFT, rt5631_input_mode); +static SOC_ENUM_SINGLE_DECL(rt5631_mic1_mode_enum, RT5631_MIC_CTRL_1, + RT5631_MIC1_DIFF_INPUT_SHIFT, rt5631_input_mode); -static const SOC_ENUM_SINGLE_DECL( - rt5631_mic2_mode_enum, RT5631_MIC_CTRL_1, - RT5631_MIC2_DIFF_INPUT_SHIFT, rt5631_input_mode); +static SOC_ENUM_SINGLE_DECL(rt5631_mic2_mode_enum, RT5631_MIC_CTRL_1, + RT5631_MIC2_DIFF_INPUT_SHIFT, rt5631_input_mode); /* MONO Input Type */ -static const SOC_ENUM_SINGLE_DECL( - rt5631_monoin_mode_enum, RT5631_MONO_INPUT_VOL, - RT5631_MONO_DIFF_INPUT_SHIFT, rt5631_input_mode); +static SOC_ENUM_SINGLE_DECL(rt5631_monoin_mode_enum, RT5631_MONO_INPUT_VOL, + RT5631_MONO_DIFF_INPUT_SHIFT, rt5631_input_mode); /* SPK Ratio Gain Control */ static const char *rt5631_spk_ratio[] = {"1.00x", "1.09x", "1.27x", "1.44x", "1.56x", "1.68x", "1.99x", "2.34x"}; -static const SOC_ENUM_SINGLE_DECL( - rt5631_spk_ratio_enum, RT5631_GEN_PUR_CTRL_REG, - RT5631_SPK_AMP_RATIO_CTRL_SHIFT, rt5631_spk_ratio); +static SOC_ENUM_SINGLE_DECL(rt5631_spk_ratio_enum, RT5631_GEN_PUR_CTRL_REG, + RT5631_SPK_AMP_RATIO_CTRL_SHIFT, rt5631_spk_ratio); static const struct snd_kcontrol_new rt5631_snd_controls[] = { /* MIC */ @@ -759,9 +755,8 @@ static const struct snd_kcontrol_new rt5631_monomix_mixer_controls[] = { /* Left SPK Volume Input */ static const char *rt5631_spkvoll_sel[] = {"Vmid", "SPKMIXL"}; -static const SOC_ENUM_SINGLE_DECL( - rt5631_spkvoll_enum, RT5631_SPK_OUT_VOL, - RT5631_L_EN_SHIFT, rt5631_spkvoll_sel); +static SOC_ENUM_SINGLE_DECL(rt5631_spkvoll_enum, RT5631_SPK_OUT_VOL, + RT5631_L_EN_SHIFT, rt5631_spkvoll_sel); static const struct snd_kcontrol_new rt5631_spkvoll_mux_control = SOC_DAPM_ENUM("Left SPKVOL SRC", rt5631_spkvoll_enum); @@ -769,9 +764,8 @@ static const struct snd_kcontrol_new rt5631_spkvoll_mux_control = /* Left HP Volume Input */ static const char *rt5631_hpvoll_sel[] = {"Vmid", "OUTMIXL"}; -static const SOC_ENUM_SINGLE_DECL( - rt5631_hpvoll_enum, RT5631_HP_OUT_VOL, - RT5631_L_EN_SHIFT, rt5631_hpvoll_sel); +static SOC_ENUM_SINGLE_DECL(rt5631_hpvoll_enum, RT5631_HP_OUT_VOL, + RT5631_L_EN_SHIFT, rt5631_hpvoll_sel); static const struct snd_kcontrol_new rt5631_hpvoll_mux_control = SOC_DAPM_ENUM("Left HPVOL SRC", rt5631_hpvoll_enum); @@ -779,9 +773,8 @@ static const struct snd_kcontrol_new rt5631_hpvoll_mux_control = /* Left Out Volume Input */ static const char *rt5631_outvoll_sel[] = {"Vmid", "OUTMIXL"}; -static const SOC_ENUM_SINGLE_DECL( - rt5631_outvoll_enum, RT5631_MONO_AXO_1_2_VOL, - RT5631_L_EN_SHIFT, rt5631_outvoll_sel); +static SOC_ENUM_SINGLE_DECL(rt5631_outvoll_enum, RT5631_MONO_AXO_1_2_VOL, + RT5631_L_EN_SHIFT, rt5631_outvoll_sel); static const struct snd_kcontrol_new rt5631_outvoll_mux_control = SOC_DAPM_ENUM("Left OUTVOL SRC", rt5631_outvoll_enum); @@ -789,9 +782,8 @@ static const struct snd_kcontrol_new rt5631_outvoll_mux_control = /* Right Out Volume Input */ static const char *rt5631_outvolr_sel[] = {"Vmid", "OUTMIXR"}; -static const SOC_ENUM_SINGLE_DECL( - rt5631_outvolr_enum, RT5631_MONO_AXO_1_2_VOL, - RT5631_R_EN_SHIFT, rt5631_outvolr_sel); +static SOC_ENUM_SINGLE_DECL(rt5631_outvolr_enum, RT5631_MONO_AXO_1_2_VOL, + RT5631_R_EN_SHIFT, rt5631_outvolr_sel); static const struct snd_kcontrol_new rt5631_outvolr_mux_control = SOC_DAPM_ENUM("Right OUTVOL SRC", rt5631_outvolr_enum); @@ -799,9 +791,8 @@ static const struct snd_kcontrol_new rt5631_outvolr_mux_control = /* Right HP Volume Input */ static const char *rt5631_hpvolr_sel[] = {"Vmid", "OUTMIXR"}; -static const SOC_ENUM_SINGLE_DECL( - rt5631_hpvolr_enum, RT5631_HP_OUT_VOL, - RT5631_R_EN_SHIFT, rt5631_hpvolr_sel); +static SOC_ENUM_SINGLE_DECL(rt5631_hpvolr_enum, RT5631_HP_OUT_VOL, + RT5631_R_EN_SHIFT, rt5631_hpvolr_sel); static const struct snd_kcontrol_new rt5631_hpvolr_mux_control = SOC_DAPM_ENUM("Right HPVOL SRC", rt5631_hpvolr_enum); @@ -809,9 +800,8 @@ static const struct snd_kcontrol_new rt5631_hpvolr_mux_control = /* Right SPK Volume Input */ static const char *rt5631_spkvolr_sel[] = {"Vmid", "SPKMIXR"}; -static const SOC_ENUM_SINGLE_DECL( - rt5631_spkvolr_enum, RT5631_SPK_OUT_VOL, - RT5631_R_EN_SHIFT, rt5631_spkvolr_sel); +static SOC_ENUM_SINGLE_DECL(rt5631_spkvolr_enum, RT5631_SPK_OUT_VOL, + RT5631_R_EN_SHIFT, rt5631_spkvolr_sel); static const struct snd_kcontrol_new rt5631_spkvolr_mux_control = SOC_DAPM_ENUM("Right SPKVOL SRC", rt5631_spkvolr_enum); @@ -820,9 +810,8 @@ static const struct snd_kcontrol_new rt5631_spkvolr_mux_control = static const char *rt5631_spol_src_sel[] = { "SPOLMIX", "MONOIN_RX", "VDAC", "DACL"}; -static const SOC_ENUM_SINGLE_DECL( - rt5631_spol_src_enum, RT5631_SPK_MONO_HP_OUT_CTRL, - RT5631_SPK_L_MUX_SEL_SHIFT, rt5631_spol_src_sel); +static SOC_ENUM_SINGLE_DECL(rt5631_spol_src_enum, RT5631_SPK_MONO_HP_OUT_CTRL, + RT5631_SPK_L_MUX_SEL_SHIFT, rt5631_spol_src_sel); static const struct snd_kcontrol_new rt5631_spol_mux_control = SOC_DAPM_ENUM("SPOL SRC", rt5631_spol_src_enum); @@ -831,9 +820,8 @@ static const struct snd_kcontrol_new rt5631_spol_mux_control = static const char *rt5631_spor_src_sel[] = { "SPORMIX", "MONOIN_RX", "VDAC", "DACR"}; -static const SOC_ENUM_SINGLE_DECL( - rt5631_spor_src_enum, RT5631_SPK_MONO_HP_OUT_CTRL, - RT5631_SPK_R_MUX_SEL_SHIFT, rt5631_spor_src_sel); +static SOC_ENUM_SINGLE_DECL(rt5631_spor_src_enum, RT5631_SPK_MONO_HP_OUT_CTRL, + RT5631_SPK_R_MUX_SEL_SHIFT, rt5631_spor_src_sel); static const struct snd_kcontrol_new rt5631_spor_mux_control = SOC_DAPM_ENUM("SPOR SRC", rt5631_spor_src_enum); @@ -841,9 +829,8 @@ static const struct snd_kcontrol_new rt5631_spor_mux_control = /* MONO Input */ static const char *rt5631_mono_src_sel[] = {"MONOMIX", "MONOIN_RX", "VDAC"}; -static const SOC_ENUM_SINGLE_DECL( - rt5631_mono_src_enum, RT5631_SPK_MONO_HP_OUT_CTRL, - RT5631_MONO_MUX_SEL_SHIFT, rt5631_mono_src_sel); +static SOC_ENUM_SINGLE_DECL(rt5631_mono_src_enum, RT5631_SPK_MONO_HP_OUT_CTRL, + RT5631_MONO_MUX_SEL_SHIFT, rt5631_mono_src_sel); static const struct snd_kcontrol_new rt5631_mono_mux_control = SOC_DAPM_ENUM("MONO SRC", rt5631_mono_src_enum); @@ -851,9 +838,8 @@ static const struct snd_kcontrol_new rt5631_mono_mux_control = /* Left HPO Input */ static const char *rt5631_hpl_src_sel[] = {"Left HPVOL", "Left DAC"}; -static const SOC_ENUM_SINGLE_DECL( - rt5631_hpl_src_enum, RT5631_SPK_MONO_HP_OUT_CTRL, - RT5631_HP_L_MUX_SEL_SHIFT, rt5631_hpl_src_sel); +static SOC_ENUM_SINGLE_DECL(rt5631_hpl_src_enum, RT5631_SPK_MONO_HP_OUT_CTRL, + RT5631_HP_L_MUX_SEL_SHIFT, rt5631_hpl_src_sel); static const struct snd_kcontrol_new rt5631_hpl_mux_control = SOC_DAPM_ENUM("HPL SRC", rt5631_hpl_src_enum); @@ -861,9 +847,8 @@ static const struct snd_kcontrol_new rt5631_hpl_mux_control = /* Right HPO Input */ static const char *rt5631_hpr_src_sel[] = {"Right HPVOL", "Right DAC"}; -static const SOC_ENUM_SINGLE_DECL( - rt5631_hpr_src_enum, RT5631_SPK_MONO_HP_OUT_CTRL, - RT5631_HP_R_MUX_SEL_SHIFT, rt5631_hpr_src_sel); +static SOC_ENUM_SINGLE_DECL(rt5631_hpr_src_enum, RT5631_SPK_MONO_HP_OUT_CTRL, + RT5631_HP_R_MUX_SEL_SHIFT, rt5631_hpr_src_sel); static const struct snd_kcontrol_new rt5631_hpr_mux_control = SOC_DAPM_ENUM("HPR SRC", rt5631_hpr_src_enum); @@ -1585,15 +1570,6 @@ static int rt5631_probe(struct snd_soc_codec *codec) { struct rt5631_priv *rt5631 = snd_soc_codec_get_drvdata(codec); unsigned int val; - int ret; - - codec->control_data = rt5631->regmap; - - ret = snd_soc_codec_set_cache_io(codec, 8, 16, SND_SOC_REGMAP); - if (ret != 0) { - dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); - return ret; - } val = rt5631_read_index(codec, RT5631_ADDA_MIXER_INTL_REG3); if (val & 0x0002) diff --git a/sound/soc/codecs/rt5640.c b/sound/soc/codecs/rt5640.c index 886924934aa..0061ae6b671 100644 --- a/sound/soc/codecs/rt5640.c +++ b/sound/soc/codecs/rt5640.c @@ -361,25 +361,24 @@ static unsigned int bst_tlv[] = { static const char * const rt5640_data_select[] = { "Normal", "left copy to right", "right copy to left", "Swap"}; -static const SOC_ENUM_SINGLE_DECL(rt5640_if1_dac_enum, RT5640_DIG_INF_DATA, - RT5640_IF1_DAC_SEL_SFT, rt5640_data_select); +static SOC_ENUM_SINGLE_DECL(rt5640_if1_dac_enum, RT5640_DIG_INF_DATA, + RT5640_IF1_DAC_SEL_SFT, rt5640_data_select); -static const SOC_ENUM_SINGLE_DECL(rt5640_if1_adc_enum, RT5640_DIG_INF_DATA, - RT5640_IF1_ADC_SEL_SFT, rt5640_data_select); +static SOC_ENUM_SINGLE_DECL(rt5640_if1_adc_enum, RT5640_DIG_INF_DATA, + RT5640_IF1_ADC_SEL_SFT, rt5640_data_select); -static const SOC_ENUM_SINGLE_DECL(rt5640_if2_dac_enum, RT5640_DIG_INF_DATA, - RT5640_IF2_DAC_SEL_SFT, rt5640_data_select); +static SOC_ENUM_SINGLE_DECL(rt5640_if2_dac_enum, RT5640_DIG_INF_DATA, + RT5640_IF2_DAC_SEL_SFT, rt5640_data_select); -static const SOC_ENUM_SINGLE_DECL(rt5640_if2_adc_enum, RT5640_DIG_INF_DATA, - RT5640_IF2_ADC_SEL_SFT, rt5640_data_select); +static SOC_ENUM_SINGLE_DECL(rt5640_if2_adc_enum, RT5640_DIG_INF_DATA, + RT5640_IF2_ADC_SEL_SFT, rt5640_data_select); /* Class D speaker gain ratio */ static const char * const rt5640_clsd_spk_ratio[] = {"1.66x", "1.83x", "1.94x", "2x", "2.11x", "2.22x", "2.33x", "2.44x", "2.55x", "2.66x", "2.77x"}; -static const SOC_ENUM_SINGLE_DECL( - rt5640_clsd_spk_ratio_enum, RT5640_CLS_D_OUT, - RT5640_CLSD_RATIO_SFT, rt5640_clsd_spk_ratio); +static SOC_ENUM_SINGLE_DECL(rt5640_clsd_spk_ratio_enum, RT5640_CLS_D_OUT, + RT5640_CLSD_RATIO_SFT, rt5640_clsd_spk_ratio); static const struct snd_kcontrol_new rt5640_snd_controls[] = { /* Speaker Output Volume */ @@ -753,9 +752,8 @@ static const char * const rt5640_stereo_adc1_src[] = { "DIG MIX", "ADC" }; -static const SOC_ENUM_SINGLE_DECL( - rt5640_stereo_adc1_enum, RT5640_STO_ADC_MIXER, - RT5640_ADC_1_SRC_SFT, rt5640_stereo_adc1_src); +static SOC_ENUM_SINGLE_DECL(rt5640_stereo_adc1_enum, RT5640_STO_ADC_MIXER, + RT5640_ADC_1_SRC_SFT, rt5640_stereo_adc1_src); static const struct snd_kcontrol_new rt5640_sto_adc_1_mux = SOC_DAPM_ENUM("Stereo ADC1 Mux", rt5640_stereo_adc1_enum); @@ -764,9 +762,8 @@ static const char * const rt5640_stereo_adc2_src[] = { "DMIC1", "DMIC2", "DIG MIX" }; -static const SOC_ENUM_SINGLE_DECL( - rt5640_stereo_adc2_enum, RT5640_STO_ADC_MIXER, - RT5640_ADC_2_SRC_SFT, rt5640_stereo_adc2_src); +static SOC_ENUM_SINGLE_DECL(rt5640_stereo_adc2_enum, RT5640_STO_ADC_MIXER, + RT5640_ADC_2_SRC_SFT, rt5640_stereo_adc2_src); static const struct snd_kcontrol_new rt5640_sto_adc_2_mux = SOC_DAPM_ENUM("Stereo ADC2 Mux", rt5640_stereo_adc2_enum); @@ -776,9 +773,8 @@ static const char * const rt5640_mono_adc_l1_src[] = { "Mono DAC MIXL", "ADCL" }; -static const SOC_ENUM_SINGLE_DECL( - rt5640_mono_adc_l1_enum, RT5640_MONO_ADC_MIXER, - RT5640_MONO_ADC_L1_SRC_SFT, rt5640_mono_adc_l1_src); +static SOC_ENUM_SINGLE_DECL(rt5640_mono_adc_l1_enum, RT5640_MONO_ADC_MIXER, + RT5640_MONO_ADC_L1_SRC_SFT, rt5640_mono_adc_l1_src); static const struct snd_kcontrol_new rt5640_mono_adc_l1_mux = SOC_DAPM_ENUM("Mono ADC1 left source", rt5640_mono_adc_l1_enum); @@ -787,9 +783,8 @@ static const char * const rt5640_mono_adc_l2_src[] = { "DMIC L1", "DMIC L2", "Mono DAC MIXL" }; -static const SOC_ENUM_SINGLE_DECL( - rt5640_mono_adc_l2_enum, RT5640_MONO_ADC_MIXER, - RT5640_MONO_ADC_L2_SRC_SFT, rt5640_mono_adc_l2_src); +static SOC_ENUM_SINGLE_DECL(rt5640_mono_adc_l2_enum, RT5640_MONO_ADC_MIXER, + RT5640_MONO_ADC_L2_SRC_SFT, rt5640_mono_adc_l2_src); static const struct snd_kcontrol_new rt5640_mono_adc_l2_mux = SOC_DAPM_ENUM("Mono ADC2 left source", rt5640_mono_adc_l2_enum); @@ -798,9 +793,8 @@ static const char * const rt5640_mono_adc_r1_src[] = { "Mono DAC MIXR", "ADCR" }; -static const SOC_ENUM_SINGLE_DECL( - rt5640_mono_adc_r1_enum, RT5640_MONO_ADC_MIXER, - RT5640_MONO_ADC_R1_SRC_SFT, rt5640_mono_adc_r1_src); +static SOC_ENUM_SINGLE_DECL(rt5640_mono_adc_r1_enum, RT5640_MONO_ADC_MIXER, + RT5640_MONO_ADC_R1_SRC_SFT, rt5640_mono_adc_r1_src); static const struct snd_kcontrol_new rt5640_mono_adc_r1_mux = SOC_DAPM_ENUM("Mono ADC1 right source", rt5640_mono_adc_r1_enum); @@ -809,9 +803,8 @@ static const char * const rt5640_mono_adc_r2_src[] = { "DMIC R1", "DMIC R2", "Mono DAC MIXR" }; -static const SOC_ENUM_SINGLE_DECL( - rt5640_mono_adc_r2_enum, RT5640_MONO_ADC_MIXER, - RT5640_MONO_ADC_R2_SRC_SFT, rt5640_mono_adc_r2_src); +static SOC_ENUM_SINGLE_DECL(rt5640_mono_adc_r2_enum, RT5640_MONO_ADC_MIXER, + RT5640_MONO_ADC_R2_SRC_SFT, rt5640_mono_adc_r2_src); static const struct snd_kcontrol_new rt5640_mono_adc_r2_mux = SOC_DAPM_ENUM("Mono ADC2 right source", rt5640_mono_adc_r2_enum); @@ -826,9 +819,9 @@ static int rt5640_dac_l2_values[] = { 3, }; -static const SOC_VALUE_ENUM_SINGLE_DECL( - rt5640_dac_l2_enum, RT5640_DSP_PATH2, RT5640_DAC_L2_SEL_SFT, - 0x3, rt5640_dac_l2_src, rt5640_dac_l2_values); +static SOC_VALUE_ENUM_SINGLE_DECL(rt5640_dac_l2_enum, + RT5640_DSP_PATH2, RT5640_DAC_L2_SEL_SFT, + 0x3, rt5640_dac_l2_src, rt5640_dac_l2_values); static const struct snd_kcontrol_new rt5640_dac_l2_mux = SOC_DAPM_VALUE_ENUM("DAC2 left channel source", rt5640_dac_l2_enum); @@ -841,9 +834,9 @@ static int rt5640_dac_r2_values[] = { 0, }; -static const SOC_VALUE_ENUM_SINGLE_DECL( - rt5640_dac_r2_enum, RT5640_DSP_PATH2, RT5640_DAC_R2_SEL_SFT, - 0x3, rt5640_dac_r2_src, rt5640_dac_r2_values); +static SOC_VALUE_ENUM_SINGLE_DECL(rt5640_dac_r2_enum, + RT5640_DSP_PATH2, RT5640_DAC_R2_SEL_SFT, + 0x3, rt5640_dac_r2_src, rt5640_dac_r2_values); static const struct snd_kcontrol_new rt5640_dac_r2_mux = SOC_DAPM_ENUM("DAC2 right channel source", rt5640_dac_r2_enum); @@ -860,9 +853,10 @@ static int rt5640_dai_iis_map_values[] = { 7, }; -static const SOC_VALUE_ENUM_SINGLE_DECL( - rt5640_dai_iis_map_enum, RT5640_I2S1_SDP, RT5640_I2S_IF_SFT, - 0x7, rt5640_dai_iis_map, rt5640_dai_iis_map_values); +static SOC_VALUE_ENUM_SINGLE_DECL(rt5640_dai_iis_map_enum, + RT5640_I2S1_SDP, RT5640_I2S_IF_SFT, + 0x7, rt5640_dai_iis_map, + rt5640_dai_iis_map_values); static const struct snd_kcontrol_new rt5640_dai_mux = SOC_DAPM_VALUE_ENUM("DAI select", rt5640_dai_iis_map_enum); @@ -872,9 +866,8 @@ static const char * const rt5640_sdi_sel[] = { "IF1", "IF2" }; -static const SOC_ENUM_SINGLE_DECL( - rt5640_sdi_sel_enum, RT5640_I2S2_SDP, - RT5640_I2S2_SDI_SFT, rt5640_sdi_sel); +static SOC_ENUM_SINGLE_DECL(rt5640_sdi_sel_enum, RT5640_I2S2_SDP, + RT5640_I2S2_SDI_SFT, rt5640_sdi_sel); static const struct snd_kcontrol_new rt5640_sdi_mux = SOC_DAPM_ENUM("SDI select", rt5640_sdi_sel_enum); @@ -1601,8 +1594,7 @@ static int get_clk_info(int sclk, int rate) static int rt5640_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params, struct snd_soc_dai *dai) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_codec *codec = rtd->codec; + struct snd_soc_codec *codec = dai->codec; struct rt5640_priv *rt5640 = snd_soc_codec_get_drvdata(codec); unsigned int val_len = 0, val_clk, mask_clk; int dai_sel, pre_div, bclk_ms, frame_size; @@ -1943,16 +1935,8 @@ static int rt5640_set_bias_level(struct snd_soc_codec *codec, static int rt5640_probe(struct snd_soc_codec *codec) { struct rt5640_priv *rt5640 = snd_soc_codec_get_drvdata(codec); - int ret; rt5640->codec = codec; - codec->control_data = rt5640->regmap; - - ret = snd_soc_codec_set_cache_io(codec, 8, 16, SND_SOC_REGMAP); - if (ret != 0) { - dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); - return ret; - } codec->dapm.idle_bias_off = 1; rt5640_set_bias_level(codec, SND_SOC_BIAS_OFF); diff --git a/sound/soc/codecs/sgtl5000.c b/sound/soc/codecs/sgtl5000.c index 0fcbe90f3ef..d3ed1be5a18 100644 --- a/sound/soc/codecs/sgtl5000.c +++ b/sound/soc/codecs/sgtl5000.c @@ -187,8 +187,9 @@ static const char *adc_mux_text[] = { "MIC_IN", "LINE_IN" }; -static const struct soc_enum adc_enum = -SOC_ENUM_SINGLE(SGTL5000_CHIP_ANA_CTRL, 2, 2, adc_mux_text); +static SOC_ENUM_SINGLE_DECL(adc_enum, + SGTL5000_CHIP_ANA_CTRL, 2, + adc_mux_text); static const struct snd_kcontrol_new adc_mux = SOC_DAPM_ENUM("Capture Mux", adc_enum); @@ -198,8 +199,9 @@ static const char *dac_mux_text[] = { "DAC", "LINE_IN" }; -static const struct soc_enum dac_enum = -SOC_ENUM_SINGLE(SGTL5000_CHIP_ANA_CTRL, 6, 2, dac_mux_text); +static SOC_ENUM_SINGLE_DECL(dac_enum, + SGTL5000_CHIP_ANA_CTRL, 6, + dac_mux_text); static const struct snd_kcontrol_new dac_mux = SOC_DAPM_ENUM("Headphone Mux", dac_enum); @@ -1350,14 +1352,6 @@ static int sgtl5000_probe(struct snd_soc_codec *codec) int ret; struct sgtl5000_priv *sgtl5000 = snd_soc_codec_get_drvdata(codec); - /* setup i2c data ops */ - codec->control_data = sgtl5000->regmap; - ret = snd_soc_codec_set_cache_io(codec, 16, 16, SND_SOC_REGMAP); - if (ret < 0) { - dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); - return ret; - } - ret = sgtl5000_enable_regulators(codec); if (ret) return ret; diff --git a/sound/soc/codecs/si476x.c b/sound/soc/codecs/si476x.c index fa2b8e07f42..244c097cd90 100644 --- a/sound/soc/codecs/si476x.c +++ b/sound/soc/codecs/si476x.c @@ -21,6 +21,7 @@ #include <linux/slab.h> #include <sound/pcm.h> #include <sound/pcm_params.h> +#include <linux/regmap.h> #include <sound/soc.h> #include <sound/initval.h> @@ -209,8 +210,9 @@ out: static int si476x_codec_probe(struct snd_soc_codec *codec) { - codec->control_data = dev_get_regmap(codec->dev->parent, NULL); - return snd_soc_codec_set_cache_io(codec, 0, 0, SND_SOC_REGMAP); + struct regmap *regmap = dev_get_regmap(codec->dev->parent, NULL); + + return snd_soc_codec_set_cache_io(codec, regmap); } static struct snd_soc_dai_ops si476x_dai_ops = { diff --git a/sound/soc/codecs/sirf-audio-codec.c b/sound/soc/codecs/sirf-audio-codec.c new file mode 100644 index 00000000000..58e7c1f2377 --- /dev/null +++ b/sound/soc/codecs/sirf-audio-codec.c @@ -0,0 +1,524 @@ +/* + * SiRF audio codec driver + * + * Copyright (c) 2011 Cambridge Silicon Radio Limited, a CSR plc group company. + * + * Licensed under GPLv2 or later. + */ + +#include <linux/module.h> +#include <linux/platform_device.h> +#include <linux/pm_runtime.h> +#include <linux/of.h> +#include <linux/of_device.h> +#include <linux/clk.h> +#include <linux/delay.h> +#include <linux/io.h> +#include <linux/regmap.h> +#include <sound/core.h> +#include <sound/pcm.h> +#include <sound/pcm_params.h> +#include <sound/initval.h> +#include <sound/tlv.h> +#include <sound/soc.h> +#include <sound/dmaengine_pcm.h> + +#include "sirf-audio-codec.h" + +struct sirf_audio_codec { + struct clk *clk; + struct regmap *regmap; + u32 reg_ctrl0, reg_ctrl1; +}; + +static const char * const input_mode_mux[] = {"Single-ended", + "Differential"}; + +static const struct soc_enum input_mode_mux_enum = + SOC_ENUM_SINGLE(AUDIO_IC_CODEC_CTRL1, 4, 2, input_mode_mux); + +static const struct snd_kcontrol_new sirf_audio_codec_input_mode_control = + SOC_DAPM_ENUM("Route", input_mode_mux_enum); + +static const DECLARE_TLV_DB_SCALE(playback_vol_tlv, -12400, 100, 0); +static const DECLARE_TLV_DB_SCALE(capture_vol_tlv_prima2, 500, 100, 0); +static const DECLARE_TLV_DB_RANGE(capture_vol_tlv_atlas6, + 0, 7, TLV_DB_SCALE_ITEM(-100, 100, 0), + 0x22, 0x3F, TLV_DB_SCALE_ITEM(700, 100, 0), +); + +static struct snd_kcontrol_new volume_controls_atlas6[] = { + SOC_DOUBLE_TLV("Playback Volume", AUDIO_IC_CODEC_CTRL0, 21, 14, + 0x7F, 0, playback_vol_tlv), + SOC_DOUBLE_TLV("Capture Volume", AUDIO_IC_CODEC_CTRL1, 16, 10, + 0x3F, 0, capture_vol_tlv_atlas6), +}; + +static struct snd_kcontrol_new volume_controls_prima2[] = { + SOC_DOUBLE_TLV("Speaker Volume", AUDIO_IC_CODEC_CTRL0, 21, 14, + 0x7F, 0, playback_vol_tlv), + SOC_DOUBLE_TLV("Capture Volume", AUDIO_IC_CODEC_CTRL1, 15, 10, + 0x1F, 0, capture_vol_tlv_prima2), +}; + +static struct snd_kcontrol_new left_input_path_controls[] = { + SOC_DAPM_SINGLE("Line Left Switch", AUDIO_IC_CODEC_CTRL1, 6, 1, 0), + SOC_DAPM_SINGLE("Mic Left Switch", AUDIO_IC_CODEC_CTRL1, 3, 1, 0), +}; + +static struct snd_kcontrol_new right_input_path_controls[] = { + SOC_DAPM_SINGLE("Line Right Switch", AUDIO_IC_CODEC_CTRL1, 5, 1, 0), + SOC_DAPM_SINGLE("Mic Right Switch", AUDIO_IC_CODEC_CTRL1, 2, 1, 0), +}; + +static struct snd_kcontrol_new left_dac_to_hp_left_amp_switch_control = + SOC_DAPM_SINGLE("Switch", AUDIO_IC_CODEC_CTRL0, 9, 1, 0); + +static struct snd_kcontrol_new left_dac_to_hp_right_amp_switch_control = + SOC_DAPM_SINGLE("Switch", AUDIO_IC_CODEC_CTRL0, 8, 1, 0); + +static struct snd_kcontrol_new right_dac_to_hp_left_amp_switch_control = + SOC_DAPM_SINGLE("Switch", AUDIO_IC_CODEC_CTRL0, 7, 1, 0); + +static struct snd_kcontrol_new right_dac_to_hp_right_amp_switch_control = + SOC_DAPM_SINGLE("Switch", AUDIO_IC_CODEC_CTRL0, 6, 1, 0); + +static struct snd_kcontrol_new left_dac_to_speaker_lineout_switch_control = + SOC_DAPM_SINGLE("Switch", AUDIO_IC_CODEC_CTRL0, 11, 1, 0); + +static struct snd_kcontrol_new right_dac_to_speaker_lineout_switch_control = + SOC_DAPM_SINGLE("Switch", AUDIO_IC_CODEC_CTRL0, 10, 1, 0); + +/* After enable adc, Delay 200ms to avoid pop noise */ +static int adc_enable_delay_event(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, int event) +{ + switch (event) { + case SND_SOC_DAPM_POST_PMU: + msleep(200); + break; + default: + break; + } + + return 0; +} + +static void enable_and_reset_codec(struct regmap *regmap, + u32 codec_enable_bits, u32 codec_reset_bits) +{ + regmap_update_bits(regmap, AUDIO_IC_CODEC_CTRL1, + codec_enable_bits | codec_reset_bits, + codec_enable_bits | ~codec_reset_bits); + msleep(20); + regmap_update_bits(regmap, AUDIO_IC_CODEC_CTRL1, + codec_reset_bits, codec_reset_bits); +} + +static int atlas6_codec_enable_and_reset_event(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, int event) +{ +#define ATLAS6_CODEC_ENABLE_BITS (1 << 29) +#define ATLAS6_CODEC_RESET_BITS (1 << 28) + struct sirf_audio_codec *sirf_audio_codec = dev_get_drvdata(w->codec->dev); + switch (event) { + case SND_SOC_DAPM_PRE_PMU: + enable_and_reset_codec(sirf_audio_codec->regmap, + ATLAS6_CODEC_ENABLE_BITS, ATLAS6_CODEC_RESET_BITS); + break; + case SND_SOC_DAPM_POST_PMD: + regmap_update_bits(sirf_audio_codec->regmap, + AUDIO_IC_CODEC_CTRL1, ATLAS6_CODEC_ENABLE_BITS, + ~ATLAS6_CODEC_ENABLE_BITS); + break; + default: + break; + } + + return 0; +} + +static int prima2_codec_enable_and_reset_event(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, int event) +{ +#define PRIMA2_CODEC_ENABLE_BITS (1 << 27) +#define PRIMA2_CODEC_RESET_BITS (1 << 26) + struct sirf_audio_codec *sirf_audio_codec = dev_get_drvdata(w->codec->dev); + switch (event) { + case SND_SOC_DAPM_POST_PMU: + enable_and_reset_codec(sirf_audio_codec->regmap, + PRIMA2_CODEC_ENABLE_BITS, PRIMA2_CODEC_RESET_BITS); + break; + case SND_SOC_DAPM_POST_PMD: + regmap_update_bits(sirf_audio_codec->regmap, + AUDIO_IC_CODEC_CTRL1, PRIMA2_CODEC_ENABLE_BITS, + ~PRIMA2_CODEC_ENABLE_BITS); + break; + default: + break; + } + + return 0; +} + +static const struct snd_soc_dapm_widget atlas6_output_driver_dapm_widgets[] = { + SND_SOC_DAPM_OUT_DRV("HP Left Driver", AUDIO_IC_CODEC_CTRL1, + 25, 0, NULL, 0), + SND_SOC_DAPM_OUT_DRV("HP Right Driver", AUDIO_IC_CODEC_CTRL1, + 26, 0, NULL, 0), + SND_SOC_DAPM_OUT_DRV("Speaker Driver", AUDIO_IC_CODEC_CTRL1, + 27, 0, NULL, 0), +}; + +static const struct snd_soc_dapm_widget prima2_output_driver_dapm_widgets[] = { + SND_SOC_DAPM_OUT_DRV("HP Left Driver", AUDIO_IC_CODEC_CTRL1, + 23, 0, NULL, 0), + SND_SOC_DAPM_OUT_DRV("HP Right Driver", AUDIO_IC_CODEC_CTRL1, + 24, 0, NULL, 0), + SND_SOC_DAPM_OUT_DRV("Speaker Driver", AUDIO_IC_CODEC_CTRL1, + 25, 0, NULL, 0), +}; + +static const struct snd_soc_dapm_widget atlas6_codec_clock_dapm_widget = + SND_SOC_DAPM_SUPPLY("codecclk", SND_SOC_NOPM, 0, 0, + atlas6_codec_enable_and_reset_event, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD); + +static const struct snd_soc_dapm_widget prima2_codec_clock_dapm_widget = + SND_SOC_DAPM_SUPPLY("codecclk", SND_SOC_NOPM, 0, 0, + prima2_codec_enable_and_reset_event, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD); + +static const struct snd_soc_dapm_widget sirf_audio_codec_dapm_widgets[] = { + SND_SOC_DAPM_DAC("DAC left", NULL, AUDIO_IC_CODEC_CTRL0, 1, 0), + SND_SOC_DAPM_DAC("DAC right", NULL, AUDIO_IC_CODEC_CTRL0, 0, 0), + SND_SOC_DAPM_SWITCH("Left dac to hp left amp", SND_SOC_NOPM, 0, 0, + &left_dac_to_hp_left_amp_switch_control), + SND_SOC_DAPM_SWITCH("Left dac to hp right amp", SND_SOC_NOPM, 0, 0, + &left_dac_to_hp_right_amp_switch_control), + SND_SOC_DAPM_SWITCH("Right dac to hp left amp", SND_SOC_NOPM, 0, 0, + &right_dac_to_hp_left_amp_switch_control), + SND_SOC_DAPM_SWITCH("Right dac to hp right amp", SND_SOC_NOPM, 0, 0, + &right_dac_to_hp_right_amp_switch_control), + SND_SOC_DAPM_OUT_DRV("HP amp left driver", AUDIO_IC_CODEC_CTRL0, 3, 0, + NULL, 0), + SND_SOC_DAPM_OUT_DRV("HP amp right driver", AUDIO_IC_CODEC_CTRL0, 3, 0, + NULL, 0), + + SND_SOC_DAPM_SWITCH("Left dac to speaker lineout", SND_SOC_NOPM, 0, 0, + &left_dac_to_speaker_lineout_switch_control), + SND_SOC_DAPM_SWITCH("Right dac to speaker lineout", SND_SOC_NOPM, 0, 0, + &right_dac_to_speaker_lineout_switch_control), + SND_SOC_DAPM_OUT_DRV("Speaker amp driver", AUDIO_IC_CODEC_CTRL0, 4, 0, + NULL, 0), + + SND_SOC_DAPM_OUTPUT("HPOUTL"), + SND_SOC_DAPM_OUTPUT("HPOUTR"), + SND_SOC_DAPM_OUTPUT("SPKOUT"), + + SND_SOC_DAPM_ADC_E("ADC left", NULL, AUDIO_IC_CODEC_CTRL1, 8, 0, + adc_enable_delay_event, SND_SOC_DAPM_POST_PMU), + SND_SOC_DAPM_ADC_E("ADC right", NULL, AUDIO_IC_CODEC_CTRL1, 7, 0, + adc_enable_delay_event, SND_SOC_DAPM_POST_PMU), + SND_SOC_DAPM_MIXER("Left PGA mixer", AUDIO_IC_CODEC_CTRL1, 1, 0, + &left_input_path_controls[0], + ARRAY_SIZE(left_input_path_controls)), + SND_SOC_DAPM_MIXER("Right PGA mixer", AUDIO_IC_CODEC_CTRL1, 0, 0, + &right_input_path_controls[0], + ARRAY_SIZE(right_input_path_controls)), + + SND_SOC_DAPM_MUX("Mic input mode mux", SND_SOC_NOPM, 0, 0, + &sirf_audio_codec_input_mode_control), + SND_SOC_DAPM_MICBIAS("Mic Bias", AUDIO_IC_CODEC_PWR, 3, 0), + SND_SOC_DAPM_INPUT("MICIN1"), + SND_SOC_DAPM_INPUT("MICIN2"), + SND_SOC_DAPM_INPUT("LINEIN1"), + SND_SOC_DAPM_INPUT("LINEIN2"), + + SND_SOC_DAPM_SUPPLY("HSL Phase Opposite", AUDIO_IC_CODEC_CTRL0, + 30, 0, NULL, 0), +}; + +static const struct snd_soc_dapm_route sirf_audio_codec_map[] = { + {"SPKOUT", NULL, "Speaker Driver"}, + {"Speaker Driver", NULL, "Speaker amp driver"}, + {"Speaker amp driver", NULL, "Left dac to speaker lineout"}, + {"Speaker amp driver", NULL, "Right dac to speaker lineout"}, + {"Left dac to speaker lineout", "Switch", "DAC left"}, + {"Right dac to speaker lineout", "Switch", "DAC right"}, + {"HPOUTL", NULL, "HP Left Driver"}, + {"HPOUTR", NULL, "HP Right Driver"}, + {"HP Left Driver", NULL, "HP amp left driver"}, + {"HP Right Driver", NULL, "HP amp right driver"}, + {"HP amp left driver", NULL, "Right dac to hp left amp"}, + {"HP amp right driver", NULL , "Right dac to hp right amp"}, + {"HP amp left driver", NULL, "Left dac to hp left amp"}, + {"HP amp right driver", NULL , "Right dac to hp right amp"}, + {"Right dac to hp left amp", "Switch", "DAC left"}, + {"Right dac to hp right amp", "Switch", "DAC right"}, + {"Left dac to hp left amp", "Switch", "DAC left"}, + {"Left dac to hp right amp", "Switch", "DAC right"}, + {"DAC left", NULL, "codecclk"}, + {"DAC right", NULL, "codecclk"}, + {"DAC left", NULL, "Playback"}, + {"DAC right", NULL, "Playback"}, + {"DAC left", NULL, "HSL Phase Opposite"}, + {"DAC right", NULL, "HSL Phase Opposite"}, + + {"Capture", NULL, "ADC left"}, + {"Capture", NULL, "ADC right"}, + {"ADC left", NULL, "codecclk"}, + {"ADC right", NULL, "codecclk"}, + {"ADC left", NULL, "Left PGA mixer"}, + {"ADC right", NULL, "Right PGA mixer"}, + {"Left PGA mixer", "Line Left Switch", "LINEIN2"}, + {"Right PGA mixer", "Line Right Switch", "LINEIN1"}, + {"Left PGA mixer", "Mic Left Switch", "MICIN2"}, + {"Right PGA mixer", "Mic Right Switch", "Mic input mode mux"}, + {"Mic input mode mux", "Single-ended", "MICIN1"}, + {"Mic input mode mux", "Differential", "MICIN1"}, +}; + +static int sirf_audio_codec_trigger(struct snd_pcm_substream *substream, + int cmd, + struct snd_soc_dai *dai) +{ + int playback = substream->stream == SNDRV_PCM_STREAM_PLAYBACK; + struct snd_soc_codec *codec = dai->codec; + u32 val = 0; + + /* + * This is a workaround, When stop playback, + * need disable HP amp, avoid the current noise. + */ + switch (cmd) { + case SNDRV_PCM_TRIGGER_STOP: + case SNDRV_PCM_TRIGGER_SUSPEND: + case SNDRV_PCM_TRIGGER_PAUSE_PUSH: + break; + case SNDRV_PCM_TRIGGER_START: + case SNDRV_PCM_TRIGGER_RESUME: + case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: + if (playback) + val = IC_HSLEN | IC_HSREN; + break; + default: + return -EINVAL; + } + + if (playback) + snd_soc_update_bits(codec, AUDIO_IC_CODEC_CTRL0, + IC_HSLEN | IC_HSREN, val); + return 0; +} + +struct snd_soc_dai_ops sirf_audio_codec_dai_ops = { + .trigger = sirf_audio_codec_trigger, +}; + +struct snd_soc_dai_driver sirf_audio_codec_dai = { + .name = "sirf-audio-codec", + .playback = { + .stream_name = "Playback", + .channels_min = 2, + .channels_max = 2, + .rates = SNDRV_PCM_RATE_48000, + .formats = SNDRV_PCM_FMTBIT_S16_LE, + }, + .capture = { + .stream_name = "Capture", + .channels_min = 1, + .channels_max = 2, + .rates = SNDRV_PCM_RATE_48000, + .formats = SNDRV_PCM_FMTBIT_S16_LE, + }, + .ops = &sirf_audio_codec_dai_ops, +}; + +static int sirf_audio_codec_probe(struct snd_soc_codec *codec) +{ + struct snd_soc_dapm_context *dapm = &codec->dapm; + + pm_runtime_enable(codec->dev); + + if (of_device_is_compatible(codec->dev->of_node, "sirf,prima2-audio-codec")) { + snd_soc_dapm_new_controls(dapm, + prima2_output_driver_dapm_widgets, + ARRAY_SIZE(prima2_output_driver_dapm_widgets)); + snd_soc_dapm_new_controls(dapm, + &prima2_codec_clock_dapm_widget, 1); + return snd_soc_add_codec_controls(codec, + volume_controls_prima2, + ARRAY_SIZE(volume_controls_prima2)); + } + if (of_device_is_compatible(codec->dev->of_node, "sirf,atlas6-audio-codec")) { + snd_soc_dapm_new_controls(dapm, + atlas6_output_driver_dapm_widgets, + ARRAY_SIZE(atlas6_output_driver_dapm_widgets)); + snd_soc_dapm_new_controls(dapm, + &atlas6_codec_clock_dapm_widget, 1); + return snd_soc_add_codec_controls(codec, + volume_controls_atlas6, + ARRAY_SIZE(volume_controls_atlas6)); + } + + return -EINVAL; +} + +static int sirf_audio_codec_remove(struct snd_soc_codec *codec) +{ + pm_runtime_disable(codec->dev); + return 0; +} + +static struct snd_soc_codec_driver soc_codec_device_sirf_audio_codec = { + .probe = sirf_audio_codec_probe, + .remove = sirf_audio_codec_remove, + .dapm_widgets = sirf_audio_codec_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(sirf_audio_codec_dapm_widgets), + .dapm_routes = sirf_audio_codec_map, + .num_dapm_routes = ARRAY_SIZE(sirf_audio_codec_map), + .idle_bias_off = true, +}; + +static const struct of_device_id sirf_audio_codec_of_match[] = { + { .compatible = "sirf,prima2-audio-codec" }, + { .compatible = "sirf,atlas6-audio-codec" }, + {} +}; +MODULE_DEVICE_TABLE(of, sirf_audio_codec_of_match); + +static const struct regmap_config sirf_audio_codec_regmap_config = { + .reg_bits = 32, + .reg_stride = 4, + .val_bits = 32, + .max_register = AUDIO_IC_CODEC_CTRL3, + .cache_type = REGCACHE_NONE, +}; + +static int sirf_audio_codec_driver_probe(struct platform_device *pdev) +{ + int ret; + struct sirf_audio_codec *sirf_audio_codec; + void __iomem *base; + struct resource *mem_res; + const struct of_device_id *match; + + match = of_match_node(sirf_audio_codec_of_match, pdev->dev.of_node); + + sirf_audio_codec = devm_kzalloc(&pdev->dev, + sizeof(struct sirf_audio_codec), GFP_KERNEL); + if (!sirf_audio_codec) + return -ENOMEM; + + platform_set_drvdata(pdev, sirf_audio_codec); + + mem_res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + base = devm_ioremap_resource(&pdev->dev, mem_res); + if (base == NULL) + return -ENOMEM; + + sirf_audio_codec->regmap = devm_regmap_init_mmio(&pdev->dev, base, + &sirf_audio_codec_regmap_config); + if (IS_ERR(sirf_audio_codec->regmap)) + return PTR_ERR(sirf_audio_codec->regmap); + + sirf_audio_codec->clk = devm_clk_get(&pdev->dev, NULL); + if (IS_ERR(sirf_audio_codec->clk)) { + dev_err(&pdev->dev, "Get clock failed.\n"); + return PTR_ERR(sirf_audio_codec->clk); + } + + ret = clk_prepare_enable(sirf_audio_codec->clk); + if (ret) { + dev_err(&pdev->dev, "Enable clock failed.\n"); + return ret; + } + + ret = snd_soc_register_codec(&(pdev->dev), + &soc_codec_device_sirf_audio_codec, + &sirf_audio_codec_dai, 1); + if (ret) { + dev_err(&pdev->dev, "Register Audio Codec dai failed.\n"); + goto err_clk_put; + } + + /* + * Always open charge pump, if not, when the charge pump closed the + * adc will not stable + */ + regmap_update_bits(sirf_audio_codec->regmap, AUDIO_IC_CODEC_CTRL0, + IC_CPFREQ, IC_CPFREQ); + + if (of_device_is_compatible(pdev->dev.of_node, "sirf,atlas6-audio-codec")) + regmap_update_bits(sirf_audio_codec->regmap, + AUDIO_IC_CODEC_CTRL0, IC_CPEN, IC_CPEN); + return 0; + +err_clk_put: + clk_disable_unprepare(sirf_audio_codec->clk); + return ret; +} + +static int sirf_audio_codec_driver_remove(struct platform_device *pdev) +{ + struct sirf_audio_codec *sirf_audio_codec = platform_get_drvdata(pdev); + + clk_disable_unprepare(sirf_audio_codec->clk); + snd_soc_unregister_codec(&(pdev->dev)); + + return 0; +} + +#ifdef CONFIG_PM_SLEEP +static int sirf_audio_codec_suspend(struct device *dev) +{ + struct sirf_audio_codec *sirf_audio_codec = dev_get_drvdata(dev); + + regmap_read(sirf_audio_codec->regmap, AUDIO_IC_CODEC_CTRL0, + &sirf_audio_codec->reg_ctrl0); + regmap_read(sirf_audio_codec->regmap, AUDIO_IC_CODEC_CTRL1, + &sirf_audio_codec->reg_ctrl1); + clk_disable_unprepare(sirf_audio_codec->clk); + + return 0; +} + +static int sirf_audio_codec_resume(struct device *dev) +{ + struct sirf_audio_codec *sirf_audio_codec = dev_get_drvdata(dev); + int ret; + + ret = clk_prepare_enable(sirf_audio_codec->clk); + if (ret) + return ret; + + regmap_write(sirf_audio_codec->regmap, AUDIO_IC_CODEC_CTRL0, + sirf_audio_codec->reg_ctrl0); + regmap_write(sirf_audio_codec->regmap, AUDIO_IC_CODEC_CTRL1, + sirf_audio_codec->reg_ctrl1); + + return 0; +} +#endif + +static const struct dev_pm_ops sirf_audio_codec_pm_ops = { + SET_SYSTEM_SLEEP_PM_OPS(sirf_audio_codec_suspend, sirf_audio_codec_resume) +}; + +static struct platform_driver sirf_audio_codec_driver = { + .driver = { + .name = "sirf-audio-codec", + .owner = THIS_MODULE, + .of_match_table = sirf_audio_codec_of_match, + .pm = &sirf_audio_codec_pm_ops, + }, + .probe = sirf_audio_codec_driver_probe, + .remove = sirf_audio_codec_driver_remove, +}; + +module_platform_driver(sirf_audio_codec_driver); + +MODULE_DESCRIPTION("SiRF audio codec driver"); +MODULE_AUTHOR("RongJun Ying <Rongjun.Ying@csr.com>"); +MODULE_LICENSE("GPL v2"); diff --git a/sound/soc/codecs/sirf-audio-codec.h b/sound/soc/codecs/sirf-audio-codec.h new file mode 100644 index 00000000000..d4c187b8e54 --- /dev/null +++ b/sound/soc/codecs/sirf-audio-codec.h @@ -0,0 +1,75 @@ +/* + * SiRF inner codec controllers define + * + * Copyright (c) 2011 Cambridge Silicon Radio Limited, a CSR plc group company. + * + * Licensed under GPLv2 or later. + */ + +#ifndef _SIRF_AUDIO_CODEC_H +#define _SIRF_AUDIO_CODEC_H + + +#define AUDIO_IC_CODEC_PWR (0x00E0) +#define AUDIO_IC_CODEC_CTRL0 (0x00E4) +#define AUDIO_IC_CODEC_CTRL1 (0x00E8) +#define AUDIO_IC_CODEC_CTRL2 (0x00EC) +#define AUDIO_IC_CODEC_CTRL3 (0x00F0) + +#define MICBIASEN (1 << 3) + +#define IC_RDACEN (1 << 0) +#define IC_LDACEN (1 << 1) +#define IC_HSREN (1 << 2) +#define IC_HSLEN (1 << 3) +#define IC_SPEN (1 << 4) +#define IC_CPEN (1 << 5) + +#define IC_HPRSELR (1 << 6) +#define IC_HPLSELR (1 << 7) +#define IC_HPRSELL (1 << 8) +#define IC_HPLSELL (1 << 9) +#define IC_SPSELR (1 << 10) +#define IC_SPSELL (1 << 11) + +#define IC_MONOR (1 << 12) +#define IC_MONOL (1 << 13) + +#define IC_RXOSRSEL (1 << 28) +#define IC_CPFREQ (1 << 29) +#define IC_HSINVEN (1 << 30) + +#define IC_MICINREN (1 << 0) +#define IC_MICINLEN (1 << 1) +#define IC_MICIN1SEL (1 << 2) +#define IC_MICIN2SEL (1 << 3) +#define IC_MICDIFSEL (1 << 4) +#define IC_LINEIN1SEL (1 << 5) +#define IC_LINEIN2SEL (1 << 6) +#define IC_RADCEN (1 << 7) +#define IC_LADCEN (1 << 8) +#define IC_ALM (1 << 9) + +#define IC_DIGMICEN (1 << 22) +#define IC_DIGMICFREQ (1 << 23) +#define IC_ADC14B_12 (1 << 24) +#define IC_FIRDAC_HSL_EN (1 << 25) +#define IC_FIRDAC_HSR_EN (1 << 26) +#define IC_FIRDAC_LOUT_EN (1 << 27) +#define IC_POR (1 << 28) +#define IC_CODEC_CLK_EN (1 << 29) +#define IC_HP_3DB_BOOST (1 << 30) + +#define IC_ADC_LEFT_GAIN_SHIFT 16 +#define IC_ADC_RIGHT_GAIN_SHIFT 10 +#define IC_ADC_GAIN_MASK 0x3F +#define IC_MIC_MAX_GAIN 0x39 + +#define IC_RXPGAR_MASK 0x3F +#define IC_RXPGAR_SHIFT 14 +#define IC_RXPGAL_MASK 0x3F +#define IC_RXPGAL_SHIFT 21 +#define IC_RXPGAR 0x7B +#define IC_RXPGAL 0x7B + +#endif /*__SIRF_AUDIO_CODEC_H*/ diff --git a/sound/soc/codecs/sn95031.c b/sound/soc/codecs/sn95031.c index 13045f2af4d..42dff26b3a2 100644 --- a/sound/soc/codecs/sn95031.c +++ b/sound/soc/codecs/sn95031.c @@ -312,14 +312,14 @@ static int sn95031_dmic56_event(struct snd_soc_dapm_widget *w, /* mux controls */ static const char *sn95031_mic_texts[] = { "AMIC", "LineIn" }; -static const struct soc_enum sn95031_micl_enum = - SOC_ENUM_SINGLE(SN95031_ADCCONFIG, 1, 2, sn95031_mic_texts); +static SOC_ENUM_SINGLE_DECL(sn95031_micl_enum, + SN95031_ADCCONFIG, 1, sn95031_mic_texts); static const struct snd_kcontrol_new sn95031_micl_mux_control = SOC_DAPM_ENUM("Route", sn95031_micl_enum); -static const struct soc_enum sn95031_micr_enum = - SOC_ENUM_SINGLE(SN95031_ADCCONFIG, 3, 2, sn95031_mic_texts); +static SOC_ENUM_SINGLE_DECL(sn95031_micr_enum, + SN95031_ADCCONFIG, 3, sn95031_mic_texts); static const struct snd_kcontrol_new sn95031_micr_mux_control = SOC_DAPM_ENUM("Route", sn95031_micr_enum); @@ -328,26 +328,26 @@ static const char *sn95031_input_texts[] = { "DMIC1", "DMIC2", "DMIC3", "DMIC4", "DMIC5", "DMIC6", "ADC Left", "ADC Right" }; -static const struct soc_enum sn95031_input1_enum = - SOC_ENUM_SINGLE(SN95031_AUDIOMUX12, 0, 8, sn95031_input_texts); +static SOC_ENUM_SINGLE_DECL(sn95031_input1_enum, + SN95031_AUDIOMUX12, 0, sn95031_input_texts); static const struct snd_kcontrol_new sn95031_input1_mux_control = SOC_DAPM_ENUM("Route", sn95031_input1_enum); -static const struct soc_enum sn95031_input2_enum = - SOC_ENUM_SINGLE(SN95031_AUDIOMUX12, 4, 8, sn95031_input_texts); +static SOC_ENUM_SINGLE_DECL(sn95031_input2_enum, + SN95031_AUDIOMUX12, 4, sn95031_input_texts); static const struct snd_kcontrol_new sn95031_input2_mux_control = SOC_DAPM_ENUM("Route", sn95031_input2_enum); -static const struct soc_enum sn95031_input3_enum = - SOC_ENUM_SINGLE(SN95031_AUDIOMUX34, 0, 8, sn95031_input_texts); +static SOC_ENUM_SINGLE_DECL(sn95031_input3_enum, + SN95031_AUDIOMUX34, 0, sn95031_input_texts); static const struct snd_kcontrol_new sn95031_input3_mux_control = SOC_DAPM_ENUM("Route", sn95031_input3_enum); -static const struct soc_enum sn95031_input4_enum = - SOC_ENUM_SINGLE(SN95031_AUDIOMUX34, 4, 8, sn95031_input_texts); +static SOC_ENUM_SINGLE_DECL(sn95031_input4_enum, + SN95031_AUDIOMUX34, 4, sn95031_input_texts); static const struct snd_kcontrol_new sn95031_input4_mux_control = SOC_DAPM_ENUM("Route", sn95031_input4_enum); @@ -359,19 +359,19 @@ static const char *sn95031_micmode_text[] = {"Single Ended", "Differential"}; /* 0dB to 30dB in 10dB steps */ static const DECLARE_TLV_DB_SCALE(mic_tlv, 0, 10, 0); -static const struct soc_enum sn95031_micmode1_enum = - SOC_ENUM_SINGLE(SN95031_MICAMP1, 1, 2, sn95031_micmode_text); -static const struct soc_enum sn95031_micmode2_enum = - SOC_ENUM_SINGLE(SN95031_MICAMP2, 1, 2, sn95031_micmode_text); +static SOC_ENUM_SINGLE_DECL(sn95031_micmode1_enum, + SN95031_MICAMP1, 1, sn95031_micmode_text); +static SOC_ENUM_SINGLE_DECL(sn95031_micmode2_enum, + SN95031_MICAMP2, 1, sn95031_micmode_text); static const char *sn95031_dmic_cfg_text[] = {"GPO", "DMIC"}; -static const struct soc_enum sn95031_dmic12_cfg_enum = - SOC_ENUM_SINGLE(SN95031_DMICMUX, 0, 2, sn95031_dmic_cfg_text); -static const struct soc_enum sn95031_dmic34_cfg_enum = - SOC_ENUM_SINGLE(SN95031_DMICMUX, 1, 2, sn95031_dmic_cfg_text); -static const struct soc_enum sn95031_dmic56_cfg_enum = - SOC_ENUM_SINGLE(SN95031_DMICMUX, 2, 2, sn95031_dmic_cfg_text); +static SOC_ENUM_SINGLE_DECL(sn95031_dmic12_cfg_enum, + SN95031_DMICMUX, 0, sn95031_dmic_cfg_text); +static SOC_ENUM_SINGLE_DECL(sn95031_dmic34_cfg_enum, + SN95031_DMICMUX, 1, sn95031_dmic_cfg_text); +static SOC_ENUM_SINGLE_DECL(sn95031_dmic56_cfg_enum, + SN95031_DMICMUX, 2, sn95031_dmic_cfg_text); static const struct snd_kcontrol_new sn95031_snd_controls[] = { SOC_ENUM("Mic1Mode Capture Route", sn95031_micmode1_enum), @@ -825,8 +825,6 @@ static int sn95031_codec_probe(struct snd_soc_codec *codec) { pr_debug("codec_probe called\n"); - snd_soc_codec_set_cache_io(codec, 0, 0, SND_SOC_REGMAP); - /* PCM interface config * This sets the pcm rx slot conguration to max 6 slots * for max 4 dais (2 stereo and 2 mono) diff --git a/sound/soc/codecs/ssm2518.c b/sound/soc/codecs/ssm2518.c index cc8debce752..56adb3e2def 100644 --- a/sound/soc/codecs/ssm2518.c +++ b/sound/soc/codecs/ssm2518.c @@ -169,19 +169,19 @@ static const char * const ssm2518_drc_hold_time_text[] = { "682.24 ms", "1364 ms", }; -static const SOC_ENUM_SINGLE_DECL(ssm2518_drc_peak_detector_attack_time_enum, +static SOC_ENUM_SINGLE_DECL(ssm2518_drc_peak_detector_attack_time_enum, SSM2518_REG_DRC_2, 4, ssm2518_drc_peak_detector_attack_time_text); -static const SOC_ENUM_SINGLE_DECL(ssm2518_drc_peak_detector_release_time_enum, +static SOC_ENUM_SINGLE_DECL(ssm2518_drc_peak_detector_release_time_enum, SSM2518_REG_DRC_2, 0, ssm2518_drc_peak_detector_release_time_text); -static const SOC_ENUM_SINGLE_DECL(ssm2518_drc_attack_time_enum, +static SOC_ENUM_SINGLE_DECL(ssm2518_drc_attack_time_enum, SSM2518_REG_DRC_6, 4, ssm2518_drc_peak_detector_attack_time_text); -static const SOC_ENUM_SINGLE_DECL(ssm2518_drc_decay_time_enum, +static SOC_ENUM_SINGLE_DECL(ssm2518_drc_decay_time_enum, SSM2518_REG_DRC_6, 0, ssm2518_drc_peak_detector_release_time_text); -static const SOC_ENUM_SINGLE_DECL(ssm2518_drc_hold_time_enum, +static SOC_ENUM_SINGLE_DECL(ssm2518_drc_hold_time_enum, SSM2518_REG_DRC_7, 4, ssm2518_drc_hold_time_text); -static const SOC_ENUM_SINGLE_DECL(ssm2518_drc_noise_gate_hold_time_enum, +static SOC_ENUM_SINGLE_DECL(ssm2518_drc_noise_gate_hold_time_enum, SSM2518_REG_DRC_7, 0, ssm2518_drc_hold_time_text); -static const SOC_ENUM_SINGLE_DECL(ssm2518_drc_rms_averaging_time_enum, +static SOC_ENUM_SINGLE_DECL(ssm2518_drc_rms_averaging_time_enum, SSM2518_REG_DRC_9, 0, ssm2518_drc_peak_detector_release_time_text); static const struct snd_kcontrol_new ssm2518_snd_controls[] = { @@ -648,16 +648,6 @@ static struct snd_soc_dai_driver ssm2518_dai = { static int ssm2518_probe(struct snd_soc_codec *codec) { - struct ssm2518 *ssm2518 = snd_soc_codec_get_drvdata(codec); - int ret; - - codec->control_data = ssm2518->regmap; - ret = snd_soc_codec_set_cache_io(codec, 0, 0, SND_SOC_REGMAP); - if (ret < 0) { - dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); - return ret; - } - return ssm2518_set_bias_level(codec, SND_SOC_BIAS_OFF); } diff --git a/sound/soc/codecs/ssm2602-i2c.c b/sound/soc/codecs/ssm2602-i2c.c new file mode 100644 index 00000000000..abd63d53717 --- /dev/null +++ b/sound/soc/codecs/ssm2602-i2c.c @@ -0,0 +1,57 @@ +/* + * SSM2602/SSM2603/SSM2604 I2C audio driver + * + * Copyright 2014 Analog Devices Inc. + * + * Licensed under the GPL-2. + */ + +#include <linux/module.h> +#include <linux/i2c.h> +#include <linux/regmap.h> + +#include <sound/soc.h> + +#include "ssm2602.h" + +/* + * ssm2602 2 wire address is determined by GPIO5 + * state during powerup. + * low = 0x1a + * high = 0x1b + */ +static int ssm2602_i2c_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + return ssm2602_probe(&client->dev, id->driver_data, + devm_regmap_init_i2c(client, &ssm2602_regmap_config)); +} + +static int ssm2602_i2c_remove(struct i2c_client *client) +{ + snd_soc_unregister_codec(&client->dev); + return 0; +} + +static const struct i2c_device_id ssm2602_i2c_id[] = { + { "ssm2602", SSM2602 }, + { "ssm2603", SSM2602 }, + { "ssm2604", SSM2604 }, + { } +}; +MODULE_DEVICE_TABLE(i2c, ssm2602_i2c_id); + +static struct i2c_driver ssm2602_i2c_driver = { + .driver = { + .name = "ssm2602", + .owner = THIS_MODULE, + }, + .probe = ssm2602_i2c_probe, + .remove = ssm2602_i2c_remove, + .id_table = ssm2602_i2c_id, +}; +module_i2c_driver(ssm2602_i2c_driver); + +MODULE_DESCRIPTION("ASoC SSM2602/SSM2603/SSM2604 I2C driver"); +MODULE_AUTHOR("Cliff Cai"); +MODULE_LICENSE("GPL"); diff --git a/sound/soc/codecs/ssm2602-spi.c b/sound/soc/codecs/ssm2602-spi.c new file mode 100644 index 00000000000..2bf55e24a7b --- /dev/null +++ b/sound/soc/codecs/ssm2602-spi.c @@ -0,0 +1,41 @@ +/* + * SSM2602 SPI audio driver + * + * Copyright 2014 Analog Devices Inc. + * + * Licensed under the GPL-2. + */ + +#include <linux/module.h> +#include <linux/spi/spi.h> +#include <linux/regmap.h> + +#include <sound/soc.h> + +#include "ssm2602.h" + +static int ssm2602_spi_probe(struct spi_device *spi) +{ + return ssm2602_probe(&spi->dev, SSM2602, + devm_regmap_init_spi(spi, &ssm2602_regmap_config)); +} + +static int ssm2602_spi_remove(struct spi_device *spi) +{ + snd_soc_unregister_codec(&spi->dev); + return 0; +} + +static struct spi_driver ssm2602_spi_driver = { + .driver = { + .name = "ssm2602", + .owner = THIS_MODULE, + }, + .probe = ssm2602_spi_probe, + .remove = ssm2602_spi_remove, +}; +module_spi_driver(ssm2602_spi_driver); + +MODULE_DESCRIPTION("ASoC SSM2602 SPI driver"); +MODULE_AUTHOR("Cliff Cai"); +MODULE_LICENSE("GPL"); diff --git a/sound/soc/codecs/ssm2602.c b/sound/soc/codecs/ssm2602.c index af76bbd1b24..97b0454eb34 100644 --- a/sound/soc/codecs/ssm2602.c +++ b/sound/soc/codecs/ssm2602.c @@ -27,32 +27,20 @@ */ #include <linux/module.h> -#include <linux/moduleparam.h> -#include <linux/init.h> -#include <linux/delay.h> -#include <linux/pm.h> -#include <linux/i2c.h> -#include <linux/spi/spi.h> #include <linux/regmap.h> #include <linux/slab.h> -#include <sound/core.h> + #include <sound/pcm.h> #include <sound/pcm_params.h> #include <sound/soc.h> -#include <sound/initval.h> #include <sound/tlv.h> #include "ssm2602.h" -enum ssm2602_type { - SSM2602, - SSM2604, -}; - /* codec private data */ struct ssm2602_priv { unsigned int sysclk; - struct snd_pcm_hw_constraint_list *sysclk_constraints; + const struct snd_pcm_hw_constraint_list *sysclk_constraints; struct regmap *regmap; @@ -75,15 +63,16 @@ static const u16 ssm2602_reg[SSM2602_CACHEREGNUM] = { /*Appending several "None"s just for OSS mixer use*/ static const char *ssm2602_input_select[] = { - "Line", "Mic", "None", "None", "None", - "None", "None", "None", + "Line", "Mic", }; static const char *ssm2602_deemph[] = {"None", "32Khz", "44.1Khz", "48Khz"}; static const struct soc_enum ssm2602_enum[] = { - SOC_ENUM_SINGLE(SSM2602_APANA, 2, 2, ssm2602_input_select), - SOC_ENUM_SINGLE(SSM2602_APDIGI, 1, 4, ssm2602_deemph), + SOC_ENUM_SINGLE(SSM2602_APANA, 2, ARRAY_SIZE(ssm2602_input_select), + ssm2602_input_select), + SOC_ENUM_SINGLE(SSM2602_APDIGI, 1, ARRAY_SIZE(ssm2602_deemph), + ssm2602_deemph), }; static const unsigned int ssm260x_outmix_tlv[] = { @@ -197,7 +186,7 @@ static const unsigned int ssm2602_rates_12288000[] = { 8000, 16000, 32000, 48000, 96000, }; -static struct snd_pcm_hw_constraint_list ssm2602_constraints_12288000 = { +static const struct snd_pcm_hw_constraint_list ssm2602_constraints_12288000 = { .list = ssm2602_rates_12288000, .count = ARRAY_SIZE(ssm2602_rates_12288000), }; @@ -206,7 +195,7 @@ static const unsigned int ssm2602_rates_11289600[] = { 8000, 44100, 88200, }; -static struct snd_pcm_hw_constraint_list ssm2602_constraints_11289600 = { +static const struct snd_pcm_hw_constraint_list ssm2602_constraints_11289600 = { .list = ssm2602_rates_11289600, .count = ARRAY_SIZE(ssm2602_rates_11289600), }; @@ -529,7 +518,7 @@ static int ssm2602_resume(struct snd_soc_codec *codec) return 0; } -static int ssm2602_probe(struct snd_soc_codec *codec) +static int ssm2602_codec_probe(struct snd_soc_codec *codec) { struct ssm2602_priv *ssm2602 = snd_soc_codec_get_drvdata(codec); struct snd_soc_dapm_context *dapm = &codec->dapm; @@ -554,7 +543,7 @@ static int ssm2602_probe(struct snd_soc_codec *codec) ARRAY_SIZE(ssm2602_routes)); } -static int ssm2604_probe(struct snd_soc_codec *codec) +static int ssm2604_codec_probe(struct snd_soc_codec *codec) { struct snd_soc_dapm_context *dapm = &codec->dapm; int ret; @@ -568,18 +557,11 @@ static int ssm2604_probe(struct snd_soc_codec *codec) ARRAY_SIZE(ssm2604_routes)); } -static int ssm260x_probe(struct snd_soc_codec *codec) +static int ssm260x_codec_probe(struct snd_soc_codec *codec) { struct ssm2602_priv *ssm2602 = snd_soc_codec_get_drvdata(codec); int ret; - codec->control_data = ssm2602->regmap; - ret = snd_soc_codec_set_cache_io(codec, 0, 0, SND_SOC_REGMAP); - if (ret < 0) { - dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); - return ret; - } - ret = regmap_write(ssm2602->regmap, SSM2602_RESET, 0); if (ret < 0) { dev_err(codec->dev, "Failed to issue reset: %d\n", ret); @@ -597,10 +579,10 @@ static int ssm260x_probe(struct snd_soc_codec *codec) switch (ssm2602->type) { case SSM2602: - ret = ssm2602_probe(codec); + ret = ssm2602_codec_probe(codec); break; case SSM2604: - ret = ssm2604_probe(codec); + ret = ssm2604_codec_probe(codec); break; } @@ -620,7 +602,7 @@ static int ssm2602_remove(struct snd_soc_codec *codec) } static struct snd_soc_codec_driver soc_codec_dev_ssm2602 = { - .probe = ssm260x_probe, + .probe = ssm260x_codec_probe, .remove = ssm2602_remove, .suspend = ssm2602_suspend, .resume = ssm2602_resume, @@ -639,7 +621,7 @@ static bool ssm2602_register_volatile(struct device *dev, unsigned int reg) return reg == SSM2602_RESET; } -static const struct regmap_config ssm2602_regmap_config = { +const struct regmap_config ssm2602_regmap_config = { .val_bits = 9, .reg_bits = 7, @@ -650,134 +632,28 @@ static const struct regmap_config ssm2602_regmap_config = { .reg_defaults_raw = ssm2602_reg, .num_reg_defaults_raw = ARRAY_SIZE(ssm2602_reg), }; +EXPORT_SYMBOL_GPL(ssm2602_regmap_config); -#if defined(CONFIG_SPI_MASTER) -static int ssm2602_spi_probe(struct spi_device *spi) +int ssm2602_probe(struct device *dev, enum ssm2602_type type, + struct regmap *regmap) { struct ssm2602_priv *ssm2602; - int ret; - - ssm2602 = devm_kzalloc(&spi->dev, sizeof(struct ssm2602_priv), - GFP_KERNEL); - if (ssm2602 == NULL) - return -ENOMEM; - - spi_set_drvdata(spi, ssm2602); - ssm2602->type = SSM2602; - ssm2602->regmap = devm_regmap_init_spi(spi, &ssm2602_regmap_config); - if (IS_ERR(ssm2602->regmap)) - return PTR_ERR(ssm2602->regmap); + if (IS_ERR(regmap)) + return PTR_ERR(regmap); - ret = snd_soc_register_codec(&spi->dev, - &soc_codec_dev_ssm2602, &ssm2602_dai, 1); - return ret; -} - -static int ssm2602_spi_remove(struct spi_device *spi) -{ - snd_soc_unregister_codec(&spi->dev); - return 0; -} - -static struct spi_driver ssm2602_spi_driver = { - .driver = { - .name = "ssm2602", - .owner = THIS_MODULE, - }, - .probe = ssm2602_spi_probe, - .remove = ssm2602_spi_remove, -}; -#endif - -#if IS_ENABLED(CONFIG_I2C) -/* - * ssm2602 2 wire address is determined by GPIO5 - * state during powerup. - * low = 0x1a - * high = 0x1b - */ -static int ssm2602_i2c_probe(struct i2c_client *i2c, - const struct i2c_device_id *id) -{ - struct ssm2602_priv *ssm2602; - int ret; - - ssm2602 = devm_kzalloc(&i2c->dev, sizeof(struct ssm2602_priv), - GFP_KERNEL); + ssm2602 = devm_kzalloc(dev, sizeof(*ssm2602), GFP_KERNEL); if (ssm2602 == NULL) return -ENOMEM; - i2c_set_clientdata(i2c, ssm2602); - ssm2602->type = id->driver_data; - - ssm2602->regmap = devm_regmap_init_i2c(i2c, &ssm2602_regmap_config); - if (IS_ERR(ssm2602->regmap)) - return PTR_ERR(ssm2602->regmap); - - ret = snd_soc_register_codec(&i2c->dev, - &soc_codec_dev_ssm2602, &ssm2602_dai, 1); - return ret; -} - -static int ssm2602_i2c_remove(struct i2c_client *client) -{ - snd_soc_unregister_codec(&client->dev); - return 0; -} - -static const struct i2c_device_id ssm2602_i2c_id[] = { - { "ssm2602", SSM2602 }, - { "ssm2603", SSM2602 }, - { "ssm2604", SSM2604 }, - { } -}; -MODULE_DEVICE_TABLE(i2c, ssm2602_i2c_id); - -/* corgi i2c codec control layer */ -static struct i2c_driver ssm2602_i2c_driver = { - .driver = { - .name = "ssm2602", - .owner = THIS_MODULE, - }, - .probe = ssm2602_i2c_probe, - .remove = ssm2602_i2c_remove, - .id_table = ssm2602_i2c_id, -}; -#endif - - -static int __init ssm2602_modinit(void) -{ - int ret = 0; - -#if defined(CONFIG_SPI_MASTER) - ret = spi_register_driver(&ssm2602_spi_driver); - if (ret) - return ret; -#endif - -#if IS_ENABLED(CONFIG_I2C) - ret = i2c_add_driver(&ssm2602_i2c_driver); - if (ret) - return ret; -#endif - - return ret; -} -module_init(ssm2602_modinit); - -static void __exit ssm2602_exit(void) -{ -#if defined(CONFIG_SPI_MASTER) - spi_unregister_driver(&ssm2602_spi_driver); -#endif + dev_set_drvdata(dev, ssm2602); + ssm2602->type = SSM2602; + ssm2602->regmap = regmap; -#if IS_ENABLED(CONFIG_I2C) - i2c_del_driver(&ssm2602_i2c_driver); -#endif + return snd_soc_register_codec(dev, &soc_codec_dev_ssm2602, + &ssm2602_dai, 1); } -module_exit(ssm2602_exit); +EXPORT_SYMBOL_GPL(ssm2602_probe); MODULE_DESCRIPTION("ASoC SSM2602/SSM2603/SSM2604 driver"); MODULE_AUTHOR("Cliff Cai"); diff --git a/sound/soc/codecs/ssm2602.h b/sound/soc/codecs/ssm2602.h index fbd07d7b73c..74753884768 100644 --- a/sound/soc/codecs/ssm2602.h +++ b/sound/soc/codecs/ssm2602.h @@ -28,6 +28,20 @@ #ifndef _SSM2602_H #define _SSM2602_H +#include <linux/regmap.h> + +struct device; + +enum ssm2602_type { + SSM2602, + SSM2604, +}; + +extern const struct regmap_config ssm2602_regmap_config; + +int ssm2602_probe(struct device *dev, enum ssm2602_type type, + struct regmap *regmap); + /* SSM2602 Codec Register definitions */ #define SSM2602_LINVOL 0x00 diff --git a/sound/soc/codecs/sta32x.c b/sound/soc/codecs/sta32x.c index 2735361a4c3..12577749b17 100644 --- a/sound/soc/codecs/sta32x.c +++ b/sound/soc/codecs/sta32x.c @@ -872,16 +872,6 @@ static int sta32x_probe(struct snd_soc_codec *codec) return ret; } - /* Tell ASoC what kind of I/O to use to read the registers. ASoC will - * then do the I2C transactions itself. - */ - codec->control_data = sta32x->regmap; - ret = snd_soc_codec_set_cache_io(codec, 8, 8, SND_SOC_REGMAP); - if (ret < 0) { - dev_err(codec->dev, "failed to set cache I/O (ret=%i)\n", ret); - goto err; - } - /* Chip documentation explicitly requires that the reset values * of reserved register bits are left untouched. * Write the register default value to cache for reserved registers, @@ -946,10 +936,6 @@ static int sta32x_probe(struct snd_soc_codec *codec) regulator_bulk_disable(ARRAY_SIZE(sta32x->supplies), sta32x->supplies); return 0; - -err: - regulator_bulk_disable(ARRAY_SIZE(sta32x->supplies), sta32x->supplies); - return ret; } static int sta32x_remove(struct snd_soc_codec *codec) diff --git a/sound/soc/codecs/sta529.c b/sound/soc/codecs/sta529.c index 40c07be9b58..a40c4b0196a 100644 --- a/sound/soc/codecs/sta529.c +++ b/sound/soc/codecs/sta529.c @@ -141,7 +141,7 @@ static const char *pwm_mode_text[] = { "Binary", "Headphone", "Ternary", static const DECLARE_TLV_DB_SCALE(out_gain_tlv, -9150, 50, 0); static const DECLARE_TLV_DB_SCALE(master_vol_tlv, -12750, 50, 0); -static const SOC_ENUM_SINGLE_DECL(pwm_src, STA529_FFXCFG1, 4, pwm_mode_text); +static SOC_ENUM_SINGLE_DECL(pwm_src, STA529_FFXCFG1, 4, pwm_mode_text); static const struct snd_kcontrol_new sta529_snd_controls[] = { SOC_DOUBLE_R_TLV("Digital Playback Volume", STA529_LVOL, STA529_RVOL, 0, @@ -193,8 +193,7 @@ static int sta529_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params, struct snd_soc_dai *dai) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_codec *codec = rtd->codec; + struct snd_soc_codec *codec = dai->codec; int pdata, play_freq_val, record_freq_val; int bclk_to_fs_ratio; @@ -322,16 +321,6 @@ static struct snd_soc_dai_driver sta529_dai = { static int sta529_probe(struct snd_soc_codec *codec) { - struct sta529 *sta529 = snd_soc_codec_get_drvdata(codec); - int ret; - - codec->control_data = sta529->regmap; - ret = snd_soc_codec_set_cache_io(codec, 8, 8, SND_SOC_REGMAP); - - if (ret < 0) { - dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); - return ret; - } sta529_set_bias_level(codec, SND_SOC_BIAS_STANDBY); return 0; diff --git a/sound/soc/codecs/stac9766.c b/sound/soc/codecs/stac9766.c index a5455c1aea4..53b810d23fe 100644 --- a/sound/soc/codecs/stac9766.c +++ b/sound/soc/codecs/stac9766.c @@ -62,25 +62,25 @@ static const char *stac9766_boost1[] = {"0dB", "10dB"}; static const char *stac9766_boost2[] = {"0dB", "20dB"}; static const char *stac9766_stereo_mic[] = {"Off", "On"}; -static const struct soc_enum stac9766_record_enum = - SOC_ENUM_DOUBLE(AC97_REC_SEL, 8, 0, 8, stac9766_record_mux); -static const struct soc_enum stac9766_mono_enum = - SOC_ENUM_SINGLE(AC97_GENERAL_PURPOSE, 9, 2, stac9766_mono_mux); -static const struct soc_enum stac9766_mic_enum = - SOC_ENUM_SINGLE(AC97_GENERAL_PURPOSE, 8, 2, stac9766_mic_mux); -static const struct soc_enum stac9766_SPDIF_enum = - SOC_ENUM_SINGLE(AC97_STAC_DA_CONTROL, 1, 2, stac9766_SPDIF_mux); -static const struct soc_enum stac9766_popbypass_enum = - SOC_ENUM_SINGLE(AC97_GENERAL_PURPOSE, 15, 2, stac9766_popbypass_mux); -static const struct soc_enum stac9766_record_all_enum = - SOC_ENUM_SINGLE(AC97_STAC_ANALOG_SPECIAL, 12, 2, - stac9766_record_all_mux); -static const struct soc_enum stac9766_boost1_enum = - SOC_ENUM_SINGLE(AC97_MIC, 6, 2, stac9766_boost1); /* 0/10dB */ -static const struct soc_enum stac9766_boost2_enum = - SOC_ENUM_SINGLE(AC97_STAC_ANALOG_SPECIAL, 2, 2, stac9766_boost2); /* 0/20dB */ -static const struct soc_enum stac9766_stereo_mic_enum = - SOC_ENUM_SINGLE(AC97_STAC_STEREO_MIC, 2, 1, stac9766_stereo_mic); +static SOC_ENUM_DOUBLE_DECL(stac9766_record_enum, + AC97_REC_SEL, 8, 0, stac9766_record_mux); +static SOC_ENUM_SINGLE_DECL(stac9766_mono_enum, + AC97_GENERAL_PURPOSE, 9, stac9766_mono_mux); +static SOC_ENUM_SINGLE_DECL(stac9766_mic_enum, + AC97_GENERAL_PURPOSE, 8, stac9766_mic_mux); +static SOC_ENUM_SINGLE_DECL(stac9766_SPDIF_enum, + AC97_STAC_DA_CONTROL, 1, stac9766_SPDIF_mux); +static SOC_ENUM_SINGLE_DECL(stac9766_popbypass_enum, + AC97_GENERAL_PURPOSE, 15, stac9766_popbypass_mux); +static SOC_ENUM_SINGLE_DECL(stac9766_record_all_enum, + AC97_STAC_ANALOG_SPECIAL, 12, + stac9766_record_all_mux); +static SOC_ENUM_SINGLE_DECL(stac9766_boost1_enum, + AC97_MIC, 6, stac9766_boost1); /* 0/10dB */ +static SOC_ENUM_SINGLE_DECL(stac9766_boost2_enum, + AC97_STAC_ANALOG_SPECIAL, 2, stac9766_boost2); /* 0/20dB */ +static SOC_ENUM_SINGLE_DECL(stac9766_stereo_mic_enum, + AC97_STAC_STEREO_MIC, 2, stac9766_stereo_mic); static const DECLARE_TLV_DB_LINEAR(master_tlv, -4600, 0); static const DECLARE_TLV_DB_LINEAR(record_tlv, 0, 2250); diff --git a/sound/soc/codecs/tlv320aic23-i2c.c b/sound/soc/codecs/tlv320aic23-i2c.c new file mode 100644 index 00000000000..20fc46092c2 --- /dev/null +++ b/sound/soc/codecs/tlv320aic23-i2c.c @@ -0,0 +1,59 @@ +/* + * ALSA SoC TLV320AIC23 codec driver I2C interface + * + * Author: Arun KS, <arunks@mistralsolutions.com> + * Copyright: (C) 2008 Mistral Solutions Pvt Ltd., + * + * Based on sound/soc/codecs/wm8731.c by Richard Purdie + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include <linux/i2c.h> +#include <linux/module.h> +#include <linux/regmap.h> +#include <sound/soc.h> + +#include "tlv320aic23.h" + +static int tlv320aic23_i2c_probe(struct i2c_client *i2c, + const struct i2c_device_id *i2c_id) +{ + struct regmap *regmap; + + if (!i2c_check_functionality(i2c->adapter, I2C_FUNC_SMBUS_BYTE_DATA)) + return -EINVAL; + + regmap = devm_regmap_init_i2c(i2c, &tlv320aic23_regmap); + return tlv320aic23_probe(&i2c->dev, regmap); +} + +static int __exit tlv320aic23_i2c_remove(struct i2c_client *i2c) +{ + snd_soc_unregister_codec(&i2c->dev); + return 0; +} + +static const struct i2c_device_id tlv320aic23_id[] = { + {"tlv320aic23", 0}, + {} +}; + +MODULE_DEVICE_TABLE(i2c, tlv320aic23_id); + +static struct i2c_driver tlv320aic23_i2c_driver = { + .driver = { + .name = "tlv320aic23-codec", + }, + .probe = tlv320aic23_i2c_probe, + .remove = __exit_p(tlv320aic23_i2c_remove), + .id_table = tlv320aic23_id, +}; + +module_i2c_driver(tlv320aic23_i2c_driver); + +MODULE_DESCRIPTION("ASoC TLV320AIC23 codec driver I2C"); +MODULE_AUTHOR("Arun KS <arunks@mistralsolutions.com>"); +MODULE_LICENSE("GPL"); diff --git a/sound/soc/codecs/tlv320aic23-spi.c b/sound/soc/codecs/tlv320aic23-spi.c new file mode 100644 index 00000000000..3b387e41d75 --- /dev/null +++ b/sound/soc/codecs/tlv320aic23-spi.c @@ -0,0 +1,56 @@ +/* + * ALSA SoC TLV320AIC23 codec driver SPI interface + * + * Author: Arun KS, <arunks@mistralsolutions.com> + * Copyright: (C) 2008 Mistral Solutions Pvt Ltd., + * + * Based on sound/soc/codecs/wm8731.c by Richard Purdie + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include <linux/module.h> +#include <linux/regmap.h> +#include <linux/spi/spi.h> +#include <sound/soc.h> + +#include "tlv320aic23.h" + +static int aic23_spi_probe(struct spi_device *spi) +{ + int ret; + struct regmap *regmap; + + dev_dbg(&spi->dev, "probing tlv320aic23 spi device\n"); + + spi->mode = SPI_MODE_0; + ret = spi_setup(spi); + if (ret < 0) + return ret; + + regmap = devm_regmap_init_spi(spi, &tlv320aic23_regmap); + return tlv320aic23_probe(&spi->dev, regmap); +} + +static int aic23_spi_remove(struct spi_device *spi) +{ + snd_soc_unregister_codec(&spi->dev); + return 0; +} + +static struct spi_driver aic23_spi = { + .driver = { + .name = "tlv320aic23", + .owner = THIS_MODULE, + }, + .probe = aic23_spi_probe, + .remove = aic23_spi_remove, +}; + +module_spi_driver(aic23_spi); + +MODULE_DESCRIPTION("ASoC TLV320AIC23 codec driver SPI"); +MODULE_AUTHOR("Arun KS <arunks@mistralsolutions.com>"); +MODULE_LICENSE("GPL"); diff --git a/sound/soc/codecs/tlv320aic23.c b/sound/soc/codecs/tlv320aic23.c index 5d430cc56f5..20864ee8793 100644 --- a/sound/soc/codecs/tlv320aic23.c +++ b/sound/soc/codecs/tlv320aic23.c @@ -23,7 +23,6 @@ #include <linux/init.h> #include <linux/delay.h> #include <linux/pm.h> -#include <linux/i2c.h> #include <linux/regmap.h> #include <linux/slab.h> #include <sound/core.h> @@ -51,7 +50,7 @@ static const struct reg_default tlv320aic23_reg[] = { { 9, 0x0000 }, }; -static const struct regmap_config tlv320aic23_regmap = { +const struct regmap_config tlv320aic23_regmap = { .reg_bits = 7, .val_bits = 9, @@ -60,20 +59,21 @@ static const struct regmap_config tlv320aic23_regmap = { .num_reg_defaults = ARRAY_SIZE(tlv320aic23_reg), .cache_type = REGCACHE_RBTREE, }; +EXPORT_SYMBOL(tlv320aic23_regmap); static const char *rec_src_text[] = { "Line", "Mic" }; static const char *deemph_text[] = {"None", "32Khz", "44.1Khz", "48Khz"}; -static const struct soc_enum rec_src_enum = - SOC_ENUM_SINGLE(TLV320AIC23_ANLG, 2, 2, rec_src_text); +static SOC_ENUM_SINGLE_DECL(rec_src_enum, + TLV320AIC23_ANLG, 2, rec_src_text); static const struct snd_kcontrol_new tlv320aic23_rec_src_mux_controls = SOC_DAPM_ENUM("Input Select", rec_src_enum); -static const struct soc_enum tlv320aic23_rec_src = - SOC_ENUM_SINGLE(TLV320AIC23_ANLG, 2, 2, rec_src_text); -static const struct soc_enum tlv320aic23_deemph = - SOC_ENUM_SINGLE(TLV320AIC23_DIGT, 1, 4, deemph_text); +static SOC_ENUM_SINGLE_DECL(tlv320aic23_rec_src, + TLV320AIC23_ANLG, 2, rec_src_text); +static SOC_ENUM_SINGLE_DECL(tlv320aic23_deemph, + TLV320AIC23_DIGT, 1, deemph_text); static const DECLARE_TLV_DB_SCALE(out_gain_tlv, -12100, 100, 0); static const DECLARE_TLV_DB_SCALE(input_gain_tlv, -1725, 75, 0); @@ -400,7 +400,7 @@ static void tlv320aic23_shutdown(struct snd_pcm_substream *substream, struct aic23 *aic23 = snd_soc_codec_get_drvdata(codec); /* deactivate */ - if (!codec->active) { + if (!snd_soc_codec_is_active(codec)) { udelay(50); snd_soc_write(codec, TLV320AIC23_ACTIVE, 0x0); } @@ -557,16 +557,8 @@ static int tlv320aic23_resume(struct snd_soc_codec *codec) return 0; } -static int tlv320aic23_probe(struct snd_soc_codec *codec) +static int tlv320aic23_codec_probe(struct snd_soc_codec *codec) { - int ret; - - ret = snd_soc_codec_set_cache_io(codec, 7, 9, SND_SOC_REGMAP); - if (ret < 0) { - dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); - return ret; - } - /* Reset codec */ snd_soc_write(codec, TLV320AIC23_RESET, 0); @@ -604,7 +596,7 @@ static int tlv320aic23_remove(struct snd_soc_codec *codec) } static struct snd_soc_codec_driver soc_codec_dev_tlv320aic23 = { - .probe = tlv320aic23_probe, + .probe = tlv320aic23_codec_probe, .remove = tlv320aic23_remove, .suspend = tlv320aic23_suspend, .resume = tlv320aic23_resume, @@ -617,56 +609,25 @@ static struct snd_soc_codec_driver soc_codec_dev_tlv320aic23 = { .num_dapm_routes = ARRAY_SIZE(tlv320aic23_intercon), }; -/* - * If the i2c layer weren't so broken, we could pass this kind of data - * around - */ -static int tlv320aic23_codec_probe(struct i2c_client *i2c, - const struct i2c_device_id *i2c_id) +int tlv320aic23_probe(struct device *dev, struct regmap *regmap) { struct aic23 *aic23; - int ret; - if (!i2c_check_functionality(i2c->adapter, I2C_FUNC_SMBUS_BYTE_DATA)) - return -EINVAL; + if (IS_ERR(regmap)) + return PTR_ERR(regmap); - aic23 = devm_kzalloc(&i2c->dev, sizeof(struct aic23), GFP_KERNEL); + aic23 = devm_kzalloc(dev, sizeof(struct aic23), GFP_KERNEL); if (aic23 == NULL) return -ENOMEM; - aic23->regmap = devm_regmap_init_i2c(i2c, &tlv320aic23_regmap); - if (IS_ERR(aic23->regmap)) - return PTR_ERR(aic23->regmap); + aic23->regmap = regmap; - i2c_set_clientdata(i2c, aic23); + dev_set_drvdata(dev, aic23); - ret = snd_soc_register_codec(&i2c->dev, - &soc_codec_dev_tlv320aic23, &tlv320aic23_dai, 1); - return ret; + return snd_soc_register_codec(dev, &soc_codec_dev_tlv320aic23, + &tlv320aic23_dai, 1); } -static int __exit tlv320aic23_i2c_remove(struct i2c_client *i2c) -{ - snd_soc_unregister_codec(&i2c->dev); - return 0; -} - -static const struct i2c_device_id tlv320aic23_id[] = { - {"tlv320aic23", 0}, - {} -}; - -MODULE_DEVICE_TABLE(i2c, tlv320aic23_id); - -static struct i2c_driver tlv320aic23_i2c_driver = { - .driver = { - .name = "tlv320aic23-codec", - }, - .probe = tlv320aic23_codec_probe, - .remove = __exit_p(tlv320aic23_i2c_remove), - .id_table = tlv320aic23_id, -}; - -module_i2c_driver(tlv320aic23_i2c_driver); +EXPORT_SYMBOL(tlv320aic23_probe); MODULE_DESCRIPTION("ASoC TLV320AIC23 codec driver"); MODULE_AUTHOR("Arun KS <arunks@mistralsolutions.com>"); diff --git a/sound/soc/codecs/tlv320aic23.h b/sound/soc/codecs/tlv320aic23.h index e804120bd3d..3a7235a04a8 100644 --- a/sound/soc/codecs/tlv320aic23.h +++ b/sound/soc/codecs/tlv320aic23.h @@ -12,6 +12,12 @@ #ifndef _TLV320AIC23_H #define _TLV320AIC23_H +struct device; +struct regmap_config; + +extern const struct regmap_config tlv320aic23_regmap; +int tlv320aic23_probe(struct device *dev, struct regmap *regmap); + /* Codec TLV320AIC23 */ #define TLV320AIC23_LINVOL 0x00 #define TLV320AIC23_RINVOL 0x01 diff --git a/sound/soc/codecs/tlv320aic26.c b/sound/soc/codecs/tlv320aic26.c index 94a658fa6d9..43069de3d56 100644 --- a/sound/soc/codecs/tlv320aic26.c +++ b/sound/soc/codecs/tlv320aic26.c @@ -238,8 +238,9 @@ static struct snd_soc_dai_driver aic26_dai = { * ALSA controls */ static const char *aic26_capture_src_text[] = {"Mic", "Aux"}; -static const struct soc_enum aic26_capture_src_enum = - SOC_ENUM_SINGLE(AIC26_REG_AUDIO_CTRL1, 12, 2, aic26_capture_src_text); +static SOC_ENUM_SINGLE_DECL(aic26_capture_src_enum, + AIC26_REG_AUDIO_CTRL1, 12, + aic26_capture_src_text); static const struct snd_kcontrol_new aic26_snd_controls[] = { /* Output */ @@ -295,8 +296,6 @@ static int aic26_probe(struct snd_soc_codec *codec) struct aic26 *aic26 = dev_get_drvdata(codec->dev); int ret, reg; - snd_soc_codec_set_cache_io(codec, 16, 16, SND_SOC_REGMAP); - aic26->codec = codec; /* Reset the codec to power on defaults */ diff --git a/sound/soc/codecs/tlv320aic31xx.c b/sound/soc/codecs/tlv320aic31xx.c new file mode 100644 index 00000000000..fa158cfe9b3 --- /dev/null +++ b/sound/soc/codecs/tlv320aic31xx.c @@ -0,0 +1,1280 @@ +/* + * ALSA SoC TLV320AIC31XX codec driver + * + * Copyright (C) 2014 Texas Instruments, Inc. + * + * Author: Jyri Sarha <jsarha@ti.com> + * + * Based on ground work by: Ajit Kulkarni <x0175765@ti.com> + * + * This package is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * THIS PACKAGE IS PROVIDED AS IS AND WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED + * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. + * + * The TLV320AIC31xx series of audio codec is a low-power, highly integrated + * high performance codec which provides a stereo DAC, a mono ADC, + * and mono/stereo Class-D speaker driver. + */ + +#include <linux/module.h> +#include <linux/moduleparam.h> +#include <linux/init.h> +#include <linux/delay.h> +#include <linux/pm.h> +#include <linux/i2c.h> +#include <linux/gpio.h> +#include <linux/regulator/consumer.h> +#include <linux/of_gpio.h> +#include <linux/slab.h> +#include <sound/core.h> +#include <sound/pcm.h> +#include <sound/pcm_params.h> +#include <sound/soc.h> +#include <sound/initval.h> +#include <sound/tlv.h> +#include <dt-bindings/sound/tlv320aic31xx-micbias.h> + +#include "tlv320aic31xx.h" + +static const struct reg_default aic31xx_reg_defaults[] = { + { AIC31XX_CLKMUX, 0x00 }, + { AIC31XX_PLLPR, 0x11 }, + { AIC31XX_PLLJ, 0x04 }, + { AIC31XX_PLLDMSB, 0x00 }, + { AIC31XX_PLLDLSB, 0x00 }, + { AIC31XX_NDAC, 0x01 }, + { AIC31XX_MDAC, 0x01 }, + { AIC31XX_DOSRMSB, 0x00 }, + { AIC31XX_DOSRLSB, 0x80 }, + { AIC31XX_NADC, 0x01 }, + { AIC31XX_MADC, 0x01 }, + { AIC31XX_AOSR, 0x80 }, + { AIC31XX_IFACE1, 0x00 }, + { AIC31XX_DATA_OFFSET, 0x00 }, + { AIC31XX_IFACE2, 0x00 }, + { AIC31XX_BCLKN, 0x01 }, + { AIC31XX_DACSETUP, 0x14 }, + { AIC31XX_DACMUTE, 0x0c }, + { AIC31XX_LDACVOL, 0x00 }, + { AIC31XX_RDACVOL, 0x00 }, + { AIC31XX_ADCSETUP, 0x00 }, + { AIC31XX_ADCFGA, 0x80 }, + { AIC31XX_ADCVOL, 0x00 }, + { AIC31XX_HPDRIVER, 0x04 }, + { AIC31XX_SPKAMP, 0x06 }, + { AIC31XX_DACMIXERROUTE, 0x00 }, + { AIC31XX_LANALOGHPL, 0x7f }, + { AIC31XX_RANALOGHPR, 0x7f }, + { AIC31XX_LANALOGSPL, 0x7f }, + { AIC31XX_RANALOGSPR, 0x7f }, + { AIC31XX_HPLGAIN, 0x02 }, + { AIC31XX_HPRGAIN, 0x02 }, + { AIC31XX_SPLGAIN, 0x00 }, + { AIC31XX_SPRGAIN, 0x00 }, + { AIC31XX_MICBIAS, 0x00 }, + { AIC31XX_MICPGA, 0x80 }, + { AIC31XX_MICPGAPI, 0x00 }, + { AIC31XX_MICPGAMI, 0x00 }, +}; + +static bool aic31xx_volatile(struct device *dev, unsigned int reg) +{ + switch (reg) { + case AIC31XX_PAGECTL: /* regmap implementation requires this */ + case AIC31XX_RESET: /* always clears after write */ + case AIC31XX_OT_FLAG: + case AIC31XX_ADCFLAG: + case AIC31XX_DACFLAG1: + case AIC31XX_DACFLAG2: + case AIC31XX_OFFLAG: /* Sticky interrupt flags */ + case AIC31XX_INTRDACFLAG: /* Sticky interrupt flags */ + case AIC31XX_INTRADCFLAG: /* Sticky interrupt flags */ + case AIC31XX_INTRDACFLAG2: + case AIC31XX_INTRADCFLAG2: + return true; + } + return false; +} + +static bool aic31xx_writeable(struct device *dev, unsigned int reg) +{ + switch (reg) { + case AIC31XX_OT_FLAG: + case AIC31XX_ADCFLAG: + case AIC31XX_DACFLAG1: + case AIC31XX_DACFLAG2: + case AIC31XX_OFFLAG: /* Sticky interrupt flags */ + case AIC31XX_INTRDACFLAG: /* Sticky interrupt flags */ + case AIC31XX_INTRADCFLAG: /* Sticky interrupt flags */ + case AIC31XX_INTRDACFLAG2: + case AIC31XX_INTRADCFLAG2: + return false; + } + return true; +} + +static const struct regmap_range_cfg aic31xx_ranges[] = { + { + .range_min = 0, + .range_max = 12 * 128, + .selector_reg = AIC31XX_PAGECTL, + .selector_mask = 0xff, + .selector_shift = 0, + .window_start = 0, + .window_len = 128, + }, +}; + +static const struct regmap_config aic31xx_i2c_regmap = { + .reg_bits = 8, + .val_bits = 8, + .writeable_reg = aic31xx_writeable, + .volatile_reg = aic31xx_volatile, + .reg_defaults = aic31xx_reg_defaults, + .num_reg_defaults = ARRAY_SIZE(aic31xx_reg_defaults), + .cache_type = REGCACHE_RBTREE, + .ranges = aic31xx_ranges, + .num_ranges = ARRAY_SIZE(aic31xx_ranges), + .max_register = 12 * 128, +}; + +#define AIC31XX_NUM_SUPPLIES 6 +static const char * const aic31xx_supply_names[AIC31XX_NUM_SUPPLIES] = { + "HPVDD", + "SPRVDD", + "SPLVDD", + "AVDD", + "IOVDD", + "DVDD", +}; + +struct aic31xx_disable_nb { + struct notifier_block nb; + struct aic31xx_priv *aic31xx; +}; + +struct aic31xx_priv { + struct snd_soc_codec *codec; + u8 i2c_regs_status; + struct device *dev; + struct regmap *regmap; + struct aic31xx_pdata pdata; + struct regulator_bulk_data supplies[AIC31XX_NUM_SUPPLIES]; + struct aic31xx_disable_nb disable_nb[AIC31XX_NUM_SUPPLIES]; + unsigned int sysclk; + int rate_div_line; +}; + +struct aic31xx_rate_divs { + u32 mclk; + u32 rate; + u8 p_val; + u8 pll_j; + u16 pll_d; + u16 dosr; + u8 ndac; + u8 mdac; + u8 aosr; + u8 nadc; + u8 madc; +}; + +/* ADC dividers can be disabled by cofiguring them to 0 */ +static const struct aic31xx_rate_divs aic31xx_divs[] = { + /* mclk rate pll: p j d dosr ndac mdac aors nadc madc */ + /* 8k rate */ + {12000000, 8000, 1, 8, 1920, 128, 48, 2, 128, 48, 2}, + {24000000, 8000, 2, 8, 1920, 128, 48, 2, 128, 48, 2}, + {25000000, 8000, 2, 7, 8643, 128, 48, 2, 128, 48, 2}, + /* 11.025k rate */ + {12000000, 11025, 1, 7, 5264, 128, 32, 2, 128, 32, 2}, + {24000000, 11025, 2, 7, 5264, 128, 32, 2, 128, 32, 2}, + {25000000, 11025, 2, 7, 2253, 128, 32, 2, 128, 32, 2}, + /* 16k rate */ + {12000000, 16000, 1, 8, 1920, 128, 24, 2, 128, 24, 2}, + {24000000, 16000, 2, 8, 1920, 128, 24, 2, 128, 24, 2}, + {25000000, 16000, 2, 7, 8643, 128, 24, 2, 128, 24, 2}, + /* 22.05k rate */ + {12000000, 22050, 1, 7, 5264, 128, 16, 2, 128, 16, 2}, + {24000000, 22050, 2, 7, 5264, 128, 16, 2, 128, 16, 2}, + {25000000, 22050, 2, 7, 2253, 128, 16, 2, 128, 16, 2}, + /* 32k rate */ + {12000000, 32000, 1, 8, 1920, 128, 12, 2, 128, 12, 2}, + {24000000, 32000, 2, 8, 1920, 128, 12, 2, 128, 12, 2}, + {25000000, 32000, 2, 7, 8643, 128, 12, 2, 128, 12, 2}, + /* 44.1k rate */ + {12000000, 44100, 1, 7, 5264, 128, 8, 2, 128, 8, 2}, + {24000000, 44100, 2, 7, 5264, 128, 8, 2, 128, 8, 2}, + {25000000, 44100, 2, 7, 2253, 128, 8, 2, 128, 8, 2}, + /* 48k rate */ + {12000000, 48000, 1, 8, 1920, 128, 8, 2, 128, 8, 2}, + {24000000, 48000, 2, 8, 1920, 128, 8, 2, 128, 8, 2}, + {25000000, 48000, 2, 7, 8643, 128, 8, 2, 128, 8, 2}, + /* 88.2k rate */ + {12000000, 88200, 1, 7, 5264, 64, 8, 2, 64, 8, 2}, + {24000000, 88200, 2, 7, 5264, 64, 8, 2, 64, 8, 2}, + {25000000, 88200, 2, 7, 2253, 64, 8, 2, 64, 8, 2}, + /* 96k rate */ + {12000000, 96000, 1, 8, 1920, 64, 8, 2, 64, 8, 2}, + {24000000, 96000, 2, 8, 1920, 64, 8, 2, 64, 8, 2}, + {25000000, 96000, 2, 7, 8643, 64, 8, 2, 64, 8, 2}, + /* 176.4k rate */ + {12000000, 176400, 1, 7, 5264, 32, 8, 2, 32, 8, 2}, + {24000000, 176400, 2, 7, 5264, 32, 8, 2, 32, 8, 2}, + {25000000, 176400, 2, 7, 2253, 32, 8, 2, 32, 8, 2}, + /* 192k rate */ + {12000000, 192000, 1, 8, 1920, 32, 8, 2, 32, 8, 2}, + {24000000, 192000, 2, 8, 1920, 32, 8, 2, 32, 8, 2}, + {25000000, 192000, 2, 7, 8643, 32, 8, 2, 32, 8, 2}, +}; + +static const char * const ldac_in_text[] = { + "Off", "Left Data", "Right Data", "Mono" +}; + +static const char * const rdac_in_text[] = { + "Off", "Right Data", "Left Data", "Mono" +}; + +static SOC_ENUM_SINGLE_DECL(ldac_in_enum, AIC31XX_DACSETUP, 4, ldac_in_text); + +static SOC_ENUM_SINGLE_DECL(rdac_in_enum, AIC31XX_DACSETUP, 2, rdac_in_text); + +static const char * const mic_select_text[] = { + "Off", "FFR 10 Ohm", "FFR 20 Ohm", "FFR 40 Ohm" +}; + +static const +SOC_ENUM_SINGLE_DECL(mic1lp_p_enum, AIC31XX_MICPGAPI, 6, mic_select_text); +static const +SOC_ENUM_SINGLE_DECL(mic1rp_p_enum, AIC31XX_MICPGAPI, 4, mic_select_text); +static const +SOC_ENUM_SINGLE_DECL(mic1lm_p_enum, AIC31XX_MICPGAPI, 2, mic_select_text); + +static const +SOC_ENUM_SINGLE_DECL(cm_m_enum, AIC31XX_MICPGAMI, 6, mic_select_text); +static const +SOC_ENUM_SINGLE_DECL(mic1lm_m_enum, AIC31XX_MICPGAMI, 4, mic_select_text); + +static const DECLARE_TLV_DB_SCALE(dac_vol_tlv, -6350, 50, 0); +static const DECLARE_TLV_DB_SCALE(adc_fgain_tlv, 0, 10, 0); +static const DECLARE_TLV_DB_SCALE(adc_cgain_tlv, -2000, 50, 0); +static const DECLARE_TLV_DB_SCALE(mic_pga_tlv, 0, 50, 0); +static const DECLARE_TLV_DB_SCALE(hp_drv_tlv, 0, 100, 0); +static const DECLARE_TLV_DB_SCALE(class_D_drv_tlv, 600, 600, 0); +static const DECLARE_TLV_DB_SCALE(hp_vol_tlv, -6350, 50, 0); +static const DECLARE_TLV_DB_SCALE(sp_vol_tlv, -6350, 50, 0); + +/* + * controls to be exported to the user space + */ +static const struct snd_kcontrol_new aic31xx_snd_controls[] = { + SOC_DOUBLE_R_S_TLV("DAC Playback Volume", AIC31XX_LDACVOL, + AIC31XX_RDACVOL, 0, -127, 48, 7, 0, dac_vol_tlv), + + SOC_SINGLE_TLV("ADC Fine Capture Volume", AIC31XX_ADCFGA, 4, 4, 1, + adc_fgain_tlv), + + SOC_SINGLE("ADC Capture Switch", AIC31XX_ADCFGA, 7, 1, 1), + SOC_DOUBLE_R_S_TLV("ADC Capture Volume", AIC31XX_ADCVOL, AIC31XX_ADCVOL, + 0, -24, 40, 6, 0, adc_cgain_tlv), + + SOC_SINGLE_TLV("Mic PGA Capture Volume", AIC31XX_MICPGA, 0, + 119, 0, mic_pga_tlv), + + SOC_DOUBLE_R("HP Driver Playback Switch", AIC31XX_HPLGAIN, + AIC31XX_HPRGAIN, 2, 1, 0), + SOC_DOUBLE_R_TLV("HP Driver Playback Volume", AIC31XX_HPLGAIN, + AIC31XX_HPRGAIN, 3, 0x09, 0, hp_drv_tlv), + + SOC_DOUBLE_R_TLV("HP Analog Playback Volume", AIC31XX_LANALOGHPL, + AIC31XX_RANALOGHPR, 0, 0x7F, 1, hp_vol_tlv), +}; + +static const struct snd_kcontrol_new aic311x_snd_controls[] = { + SOC_DOUBLE_R("Speaker Driver Playback Switch", AIC31XX_SPLGAIN, + AIC31XX_SPRGAIN, 2, 1, 0), + SOC_DOUBLE_R_TLV("Speaker Driver Playback Volume", AIC31XX_SPLGAIN, + AIC31XX_SPRGAIN, 3, 3, 0, class_D_drv_tlv), + + SOC_DOUBLE_R_TLV("Speaker Analog Playback Volume", AIC31XX_LANALOGSPL, + AIC31XX_RANALOGSPR, 0, 0x7F, 1, sp_vol_tlv), +}; + +static const struct snd_kcontrol_new aic310x_snd_controls[] = { + SOC_SINGLE("Speaker Driver Playback Switch", AIC31XX_SPLGAIN, + 2, 1, 0), + SOC_SINGLE_TLV("Speaker Driver Playback Volume", AIC31XX_SPLGAIN, + 3, 3, 0, class_D_drv_tlv), + + SOC_SINGLE_TLV("Speaker Analog Playback Volume", AIC31XX_LANALOGSPL, + 0, 0x7F, 1, sp_vol_tlv), +}; + +static const struct snd_kcontrol_new ldac_in_control = + SOC_DAPM_ENUM("DAC Left Input", ldac_in_enum); + +static const struct snd_kcontrol_new rdac_in_control = + SOC_DAPM_ENUM("DAC Right Input", rdac_in_enum); + +static int aic31xx_wait_bits(struct aic31xx_priv *aic31xx, unsigned int reg, + unsigned int mask, unsigned int wbits, int sleep, + int count) +{ + unsigned int bits; + int counter = count; + int ret = regmap_read(aic31xx->regmap, reg, &bits); + while ((bits & mask) != wbits && counter && !ret) { + usleep_range(sleep, sleep * 2); + ret = regmap_read(aic31xx->regmap, reg, &bits); + counter--; + } + if ((bits & mask) != wbits) { + dev_err(aic31xx->dev, + "%s: Failed! 0x%x was 0x%x expected 0x%x (%d, 0x%x, %d us)\n", + __func__, reg, bits, wbits, ret, mask, + (count - counter) * sleep); + ret = -1; + } + return ret; +} + +#define WIDGET_BIT(reg, shift) (((shift) << 8) | (reg)) + +static int aic31xx_dapm_power_event(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, int event) +{ + struct aic31xx_priv *aic31xx = snd_soc_codec_get_drvdata(w->codec); + unsigned int reg = AIC31XX_DACFLAG1; + unsigned int mask; + + switch (WIDGET_BIT(w->reg, w->shift)) { + case WIDGET_BIT(AIC31XX_DACSETUP, 7): + mask = AIC31XX_LDACPWRSTATUS_MASK; + break; + case WIDGET_BIT(AIC31XX_DACSETUP, 6): + mask = AIC31XX_RDACPWRSTATUS_MASK; + break; + case WIDGET_BIT(AIC31XX_HPDRIVER, 7): + mask = AIC31XX_HPLDRVPWRSTATUS_MASK; + break; + case WIDGET_BIT(AIC31XX_HPDRIVER, 6): + mask = AIC31XX_HPRDRVPWRSTATUS_MASK; + break; + case WIDGET_BIT(AIC31XX_SPKAMP, 7): + mask = AIC31XX_SPLDRVPWRSTATUS_MASK; + break; + case WIDGET_BIT(AIC31XX_SPKAMP, 6): + mask = AIC31XX_SPRDRVPWRSTATUS_MASK; + break; + case WIDGET_BIT(AIC31XX_ADCSETUP, 7): + mask = AIC31XX_ADCPWRSTATUS_MASK; + reg = AIC31XX_ADCFLAG; + break; + default: + dev_err(w->codec->dev, "Unknown widget '%s' calling %s/n", + w->name, __func__); + return -EINVAL; + } + + switch (event) { + case SND_SOC_DAPM_POST_PMU: + return aic31xx_wait_bits(aic31xx, reg, mask, mask, 5000, 100); + case SND_SOC_DAPM_POST_PMD: + return aic31xx_wait_bits(aic31xx, reg, mask, 0, 5000, 100); + default: + dev_dbg(w->codec->dev, + "Unhandled dapm widget event %d from %s\n", + event, w->name); + } + return 0; +} + +static const struct snd_kcontrol_new left_output_switches[] = { + SOC_DAPM_SINGLE("From Left DAC", AIC31XX_DACMIXERROUTE, 6, 1, 0), + SOC_DAPM_SINGLE("From MIC1LP", AIC31XX_DACMIXERROUTE, 5, 1, 0), + SOC_DAPM_SINGLE("From MIC1RP", AIC31XX_DACMIXERROUTE, 4, 1, 0), +}; + +static const struct snd_kcontrol_new right_output_switches[] = { + SOC_DAPM_SINGLE("From Right DAC", AIC31XX_DACMIXERROUTE, 2, 1, 0), + SOC_DAPM_SINGLE("From MIC1RP", AIC31XX_DACMIXERROUTE, 1, 1, 0), +}; + +static const struct snd_kcontrol_new p_term_mic1lp = + SOC_DAPM_ENUM("MIC1LP P-Terminal", mic1lp_p_enum); + +static const struct snd_kcontrol_new p_term_mic1rp = + SOC_DAPM_ENUM("MIC1RP P-Terminal", mic1rp_p_enum); + +static const struct snd_kcontrol_new p_term_mic1lm = + SOC_DAPM_ENUM("MIC1LM P-Terminal", mic1lm_p_enum); + +static const struct snd_kcontrol_new m_term_mic1lm = + SOC_DAPM_ENUM("MIC1LM M-Terminal", mic1lm_m_enum); + +static const struct snd_kcontrol_new aic31xx_dapm_hpl_switch = + SOC_DAPM_SINGLE("Switch", AIC31XX_LANALOGHPL, 7, 1, 0); + +static const struct snd_kcontrol_new aic31xx_dapm_hpr_switch = + SOC_DAPM_SINGLE("Switch", AIC31XX_RANALOGHPR, 7, 1, 0); + +static const struct snd_kcontrol_new aic31xx_dapm_spl_switch = + SOC_DAPM_SINGLE("Switch", AIC31XX_LANALOGSPL, 7, 1, 0); + +static const struct snd_kcontrol_new aic31xx_dapm_spr_switch = + SOC_DAPM_SINGLE("Switch", AIC31XX_RANALOGSPR, 7, 1, 0); + +static int mic_bias_event(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, int event) +{ + struct snd_soc_codec *codec = w->codec; + struct aic31xx_priv *aic31xx = snd_soc_codec_get_drvdata(codec); + switch (event) { + case SND_SOC_DAPM_POST_PMU: + /* change mic bias voltage to user defined */ + snd_soc_update_bits(codec, AIC31XX_MICBIAS, + AIC31XX_MICBIAS_MASK, + aic31xx->pdata.micbias_vg << + AIC31XX_MICBIAS_SHIFT); + dev_dbg(codec->dev, "%s: turned on\n", __func__); + break; + case SND_SOC_DAPM_PRE_PMD: + /* turn mic bias off */ + snd_soc_update_bits(codec, AIC31XX_MICBIAS, + AIC31XX_MICBIAS_MASK, 0); + dev_dbg(codec->dev, "%s: turned off\n", __func__); + break; + } + return 0; +} + +static const struct snd_soc_dapm_widget aic31xx_dapm_widgets[] = { + SND_SOC_DAPM_AIF_IN("DAC IN", "DAC Playback", 0, SND_SOC_NOPM, 0, 0), + + SND_SOC_DAPM_MUX("DAC Left Input", + SND_SOC_NOPM, 0, 0, &ldac_in_control), + SND_SOC_DAPM_MUX("DAC Right Input", + SND_SOC_NOPM, 0, 0, &rdac_in_control), + /* DACs */ + SND_SOC_DAPM_DAC_E("DAC Left", "Left Playback", + AIC31XX_DACSETUP, 7, 0, aic31xx_dapm_power_event, + SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD), + + SND_SOC_DAPM_DAC_E("DAC Right", "Right Playback", + AIC31XX_DACSETUP, 6, 0, aic31xx_dapm_power_event, + SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD), + + /* Output Mixers */ + SND_SOC_DAPM_MIXER("Output Left", SND_SOC_NOPM, 0, 0, + left_output_switches, + ARRAY_SIZE(left_output_switches)), + SND_SOC_DAPM_MIXER("Output Right", SND_SOC_NOPM, 0, 0, + right_output_switches, + ARRAY_SIZE(right_output_switches)), + + SND_SOC_DAPM_SWITCH("HP Left", SND_SOC_NOPM, 0, 0, + &aic31xx_dapm_hpl_switch), + SND_SOC_DAPM_SWITCH("HP Right", SND_SOC_NOPM, 0, 0, + &aic31xx_dapm_hpr_switch), + + /* Output drivers */ + SND_SOC_DAPM_OUT_DRV_E("HPL Driver", AIC31XX_HPDRIVER, 7, 0, + NULL, 0, aic31xx_dapm_power_event, + SND_SOC_DAPM_POST_PMD | SND_SOC_DAPM_POST_PMU), + SND_SOC_DAPM_OUT_DRV_E("HPR Driver", AIC31XX_HPDRIVER, 6, 0, + NULL, 0, aic31xx_dapm_power_event, + SND_SOC_DAPM_POST_PMD | SND_SOC_DAPM_POST_PMU), + + /* ADC */ + SND_SOC_DAPM_ADC_E("ADC", "Capture", AIC31XX_ADCSETUP, 7, 0, + aic31xx_dapm_power_event, SND_SOC_DAPM_POST_PMU | + SND_SOC_DAPM_POST_PMD), + + /* Input Selection to MIC_PGA */ + SND_SOC_DAPM_MUX("MIC1LP P-Terminal", SND_SOC_NOPM, 0, 0, + &p_term_mic1lp), + SND_SOC_DAPM_MUX("MIC1RP P-Terminal", SND_SOC_NOPM, 0, 0, + &p_term_mic1rp), + SND_SOC_DAPM_MUX("MIC1LM P-Terminal", SND_SOC_NOPM, 0, 0, + &p_term_mic1lm), + + SND_SOC_DAPM_MUX("MIC1LM M-Terminal", SND_SOC_NOPM, 0, 0, + &m_term_mic1lm), + /* Enabling & Disabling MIC Gain Ctl */ + SND_SOC_DAPM_PGA("MIC_GAIN_CTL", AIC31XX_MICPGA, + 7, 1, NULL, 0), + + /* Mic Bias */ + SND_SOC_DAPM_SUPPLY("MICBIAS", SND_SOC_NOPM, 0, 0, mic_bias_event, + SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD), + + /* Outputs */ + SND_SOC_DAPM_OUTPUT("HPL"), + SND_SOC_DAPM_OUTPUT("HPR"), + + /* Inputs */ + SND_SOC_DAPM_INPUT("MIC1LP"), + SND_SOC_DAPM_INPUT("MIC1RP"), + SND_SOC_DAPM_INPUT("MIC1LM"), +}; + +static const struct snd_soc_dapm_widget aic311x_dapm_widgets[] = { + /* AIC3111 and AIC3110 have stereo class-D amplifier */ + SND_SOC_DAPM_OUT_DRV_E("SPL ClassD", AIC31XX_SPKAMP, 7, 0, NULL, 0, + aic31xx_dapm_power_event, SND_SOC_DAPM_POST_PMU | + SND_SOC_DAPM_POST_PMD), + SND_SOC_DAPM_OUT_DRV_E("SPR ClassD", AIC31XX_SPKAMP, 6, 0, NULL, 0, + aic31xx_dapm_power_event, SND_SOC_DAPM_POST_PMU | + SND_SOC_DAPM_POST_PMD), + SND_SOC_DAPM_SWITCH("Speaker Left", SND_SOC_NOPM, 0, 0, + &aic31xx_dapm_spl_switch), + SND_SOC_DAPM_SWITCH("Speaker Right", SND_SOC_NOPM, 0, 0, + &aic31xx_dapm_spr_switch), + SND_SOC_DAPM_OUTPUT("SPL"), + SND_SOC_DAPM_OUTPUT("SPR"), +}; + +/* AIC3100 and AIC3120 have only mono class-D amplifier */ +static const struct snd_soc_dapm_widget aic310x_dapm_widgets[] = { + SND_SOC_DAPM_OUT_DRV_E("SPK ClassD", AIC31XX_SPKAMP, 7, 0, NULL, 0, + aic31xx_dapm_power_event, SND_SOC_DAPM_POST_PMU | + SND_SOC_DAPM_POST_PMD), + SND_SOC_DAPM_SWITCH("Speaker", SND_SOC_NOPM, 0, 0, + &aic31xx_dapm_spl_switch), + SND_SOC_DAPM_OUTPUT("SPK"), +}; + +static const struct snd_soc_dapm_route +aic31xx_audio_map[] = { + /* DAC Input Routing */ + {"DAC Left Input", "Left Data", "DAC IN"}, + {"DAC Left Input", "Right Data", "DAC IN"}, + {"DAC Left Input", "Mono", "DAC IN"}, + {"DAC Right Input", "Left Data", "DAC IN"}, + {"DAC Right Input", "Right Data", "DAC IN"}, + {"DAC Right Input", "Mono", "DAC IN"}, + {"DAC Left", NULL, "DAC Left Input"}, + {"DAC Right", NULL, "DAC Right Input"}, + + /* Mic input */ + {"MIC1LP P-Terminal", "FFR 10 Ohm", "MIC1LP"}, + {"MIC1LP P-Terminal", "FFR 20 Ohm", "MIC1LP"}, + {"MIC1LP P-Terminal", "FFR 40 Ohm", "MIC1LP"}, + {"MIC1RP P-Terminal", "FFR 10 Ohm", "MIC1RP"}, + {"MIC1RP P-Terminal", "FFR 20 Ohm", "MIC1RP"}, + {"MIC1RP P-Terminal", "FFR 40 Ohm", "MIC1RP"}, + {"MIC1LM P-Terminal", "FFR 10 Ohm", "MIC1LM"}, + {"MIC1LM P-Terminal", "FFR 20 Ohm", "MIC1LM"}, + {"MIC1LM P-Terminal", "FFR 40 Ohm", "MIC1LM"}, + + {"MIC1LM M-Terminal", "FFR 10 Ohm", "MIC1LM"}, + {"MIC1LM M-Terminal", "FFR 20 Ohm", "MIC1LM"}, + {"MIC1LM M-Terminal", "FFR 40 Ohm", "MIC1LM"}, + + {"MIC_GAIN_CTL", NULL, "MIC1LP P-Terminal"}, + {"MIC_GAIN_CTL", NULL, "MIC1RP P-Terminal"}, + {"MIC_GAIN_CTL", NULL, "MIC1LM P-Terminal"}, + {"MIC_GAIN_CTL", NULL, "MIC1LM M-Terminal"}, + + {"ADC", NULL, "MIC_GAIN_CTL"}, + + /* Left Output */ + {"Output Left", "From Left DAC", "DAC Left"}, + {"Output Left", "From MIC1LP", "MIC1LP"}, + {"Output Left", "From MIC1RP", "MIC1RP"}, + + /* Right Output */ + {"Output Right", "From Right DAC", "DAC Right"}, + {"Output Right", "From MIC1RP", "MIC1RP"}, + + /* HPL path */ + {"HP Left", "Switch", "Output Left"}, + {"HPL Driver", NULL, "HP Left"}, + {"HPL", NULL, "HPL Driver"}, + + /* HPR path */ + {"HP Right", "Switch", "Output Right"}, + {"HPR Driver", NULL, "HP Right"}, + {"HPR", NULL, "HPR Driver"}, +}; + +static const struct snd_soc_dapm_route +aic311x_audio_map[] = { + /* SP L path */ + {"Speaker Left", "Switch", "Output Left"}, + {"SPL ClassD", NULL, "Speaker Left"}, + {"SPL", NULL, "SPL ClassD"}, + + /* SP R path */ + {"Speaker Right", "Switch", "Output Right"}, + {"SPR ClassD", NULL, "Speaker Right"}, + {"SPR", NULL, "SPR ClassD"}, +}; + +static const struct snd_soc_dapm_route +aic310x_audio_map[] = { + /* SP L path */ + {"Speaker", "Switch", "Output Left"}, + {"SPK ClassD", NULL, "Speaker"}, + {"SPK", NULL, "SPK ClassD"}, +}; + +static int aic31xx_add_controls(struct snd_soc_codec *codec) +{ + int ret = 0; + struct aic31xx_priv *aic31xx = snd_soc_codec_get_drvdata(codec); + + if (aic31xx->pdata.codec_type & AIC31XX_STEREO_CLASS_D_BIT) + ret = snd_soc_add_codec_controls( + codec, aic311x_snd_controls, + ARRAY_SIZE(aic311x_snd_controls)); + else + ret = snd_soc_add_codec_controls( + codec, aic310x_snd_controls, + ARRAY_SIZE(aic310x_snd_controls)); + + return ret; +} + +static int aic31xx_add_widgets(struct snd_soc_codec *codec) +{ + struct snd_soc_dapm_context *dapm = &codec->dapm; + struct aic31xx_priv *aic31xx = snd_soc_codec_get_drvdata(codec); + int ret = 0; + + if (aic31xx->pdata.codec_type & AIC31XX_STEREO_CLASS_D_BIT) { + ret = snd_soc_dapm_new_controls( + dapm, aic311x_dapm_widgets, + ARRAY_SIZE(aic311x_dapm_widgets)); + if (ret) + return ret; + + ret = snd_soc_dapm_add_routes(dapm, aic311x_audio_map, + ARRAY_SIZE(aic311x_audio_map)); + if (ret) + return ret; + } else { + ret = snd_soc_dapm_new_controls( + dapm, aic310x_dapm_widgets, + ARRAY_SIZE(aic310x_dapm_widgets)); + if (ret) + return ret; + + ret = snd_soc_dapm_add_routes(dapm, aic310x_audio_map, + ARRAY_SIZE(aic310x_audio_map)); + if (ret) + return ret; + } + + return 0; +} + +static int aic31xx_setup_pll(struct snd_soc_codec *codec, + struct snd_pcm_hw_params *params) +{ + struct aic31xx_priv *aic31xx = snd_soc_codec_get_drvdata(codec); + int bclk_n = 0; + int i; + + /* Use PLL as CODEC_CLKIN and DAC_CLK as BDIV_CLKIN */ + snd_soc_update_bits(codec, AIC31XX_CLKMUX, + AIC31XX_CODEC_CLKIN_MASK, AIC31XX_CODEC_CLKIN_PLL); + snd_soc_update_bits(codec, AIC31XX_IFACE2, + AIC31XX_BDIVCLK_MASK, AIC31XX_DAC2BCLK); + + for (i = 0; i < ARRAY_SIZE(aic31xx_divs); i++) { + if (aic31xx_divs[i].rate == params_rate(params) && + aic31xx_divs[i].mclk == aic31xx->sysclk) + break; + } + + if (i == ARRAY_SIZE(aic31xx_divs)) { + dev_err(codec->dev, "%s: Sampling rate %u not supported\n", + __func__, params_rate(params)); + return -EINVAL; + } + + /* PLL configuration */ + snd_soc_update_bits(codec, AIC31XX_PLLPR, AIC31XX_PLL_MASK, + (aic31xx_divs[i].p_val << 4) | 0x01); + snd_soc_write(codec, AIC31XX_PLLJ, aic31xx_divs[i].pll_j); + + snd_soc_write(codec, AIC31XX_PLLDMSB, + aic31xx_divs[i].pll_d >> 8); + snd_soc_write(codec, AIC31XX_PLLDLSB, + aic31xx_divs[i].pll_d & 0xff); + + /* DAC dividers configuration */ + snd_soc_update_bits(codec, AIC31XX_NDAC, AIC31XX_PLL_MASK, + aic31xx_divs[i].ndac); + snd_soc_update_bits(codec, AIC31XX_MDAC, AIC31XX_PLL_MASK, + aic31xx_divs[i].mdac); + + snd_soc_write(codec, AIC31XX_DOSRMSB, aic31xx_divs[i].dosr >> 8); + snd_soc_write(codec, AIC31XX_DOSRLSB, aic31xx_divs[i].dosr & 0xff); + + /* ADC dividers configuration. Write reset value 1 if not used. */ + snd_soc_update_bits(codec, AIC31XX_NADC, AIC31XX_PLL_MASK, + aic31xx_divs[i].nadc ? aic31xx_divs[i].nadc : 1); + snd_soc_update_bits(codec, AIC31XX_MADC, AIC31XX_PLL_MASK, + aic31xx_divs[i].madc ? aic31xx_divs[i].madc : 1); + + snd_soc_write(codec, AIC31XX_AOSR, aic31xx_divs[i].aosr); + + /* Bit clock divider configuration. */ + bclk_n = (aic31xx_divs[i].dosr * aic31xx_divs[i].mdac) + / snd_soc_params_to_frame_size(params); + if (bclk_n == 0) { + dev_err(codec->dev, "%s: Not enough BLCK bandwidth\n", + __func__); + return -EINVAL; + } + + snd_soc_update_bits(codec, AIC31XX_BCLKN, + AIC31XX_PLL_MASK, bclk_n); + + aic31xx->rate_div_line = i; + + dev_dbg(codec->dev, + "pll %d.%04d/%d dosr %d n %d m %d aosr %d n %d m %d bclk_n %d\n", + aic31xx_divs[i].pll_j, aic31xx_divs[i].pll_d, + aic31xx_divs[i].p_val, aic31xx_divs[i].dosr, + aic31xx_divs[i].ndac, aic31xx_divs[i].mdac, + aic31xx_divs[i].aosr, aic31xx_divs[i].nadc, + aic31xx_divs[i].madc, bclk_n); + + return 0; +} + +static int aic31xx_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params, + struct snd_soc_dai *dai) +{ + struct snd_soc_codec *codec = dai->codec; + u8 data = 0; + + dev_dbg(codec->dev, "## %s: format %d width %d rate %d\n", + __func__, params_format(params), params_width(params), + params_rate(params)); + + switch (params_width(params)) { + case 16: + break; + case 20: + data = (AIC31XX_WORD_LEN_20BITS << + AIC31XX_IFACE1_DATALEN_SHIFT); + break; + case 24: + data = (AIC31XX_WORD_LEN_24BITS << + AIC31XX_IFACE1_DATALEN_SHIFT); + break; + case 32: + data = (AIC31XX_WORD_LEN_32BITS << + AIC31XX_IFACE1_DATALEN_SHIFT); + break; + default: + dev_err(codec->dev, "%s: Unsupported format %d\n", + __func__, params_format(params)); + return -EINVAL; + } + + snd_soc_update_bits(codec, AIC31XX_IFACE1, + AIC31XX_IFACE1_DATALEN_MASK, + data); + + return aic31xx_setup_pll(codec, params); +} + +static int aic31xx_dac_mute(struct snd_soc_dai *codec_dai, int mute) +{ + struct snd_soc_codec *codec = codec_dai->codec; + + if (mute) { + snd_soc_update_bits(codec, AIC31XX_DACMUTE, + AIC31XX_DACMUTE_MASK, + AIC31XX_DACMUTE_MASK); + } else { + snd_soc_update_bits(codec, AIC31XX_DACMUTE, + AIC31XX_DACMUTE_MASK, 0x0); + } + + return 0; +} + +static int aic31xx_set_dai_fmt(struct snd_soc_dai *codec_dai, + unsigned int fmt) +{ + struct snd_soc_codec *codec = codec_dai->codec; + u8 iface_reg1 = 0; + u8 iface_reg3 = 0; + u8 dsp_a_val = 0; + + dev_dbg(codec->dev, "## %s: fmt = 0x%x\n", __func__, fmt); + + /* set master/slave audio interface */ + switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { + case SND_SOC_DAIFMT_CBM_CFM: + iface_reg1 |= AIC31XX_BCLK_MASTER | AIC31XX_WCLK_MASTER; + break; + default: + dev_alert(codec->dev, "Invalid DAI master/slave interface\n"); + return -EINVAL; + } + + /* interface format */ + switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { + case SND_SOC_DAIFMT_I2S: + break; + case SND_SOC_DAIFMT_DSP_A: + dsp_a_val = 0x1; + case SND_SOC_DAIFMT_DSP_B: + /* NOTE: BCLKINV bit value 1 equas NB and 0 equals IB */ + switch (fmt & SND_SOC_DAIFMT_INV_MASK) { + case SND_SOC_DAIFMT_NB_NF: + iface_reg3 |= AIC31XX_BCLKINV_MASK; + break; + case SND_SOC_DAIFMT_IB_NF: + break; + default: + return -EINVAL; + } + iface_reg1 |= (AIC31XX_DSP_MODE << + AIC31XX_IFACE1_DATATYPE_SHIFT); + break; + case SND_SOC_DAIFMT_RIGHT_J: + iface_reg1 |= (AIC31XX_RIGHT_JUSTIFIED_MODE << + AIC31XX_IFACE1_DATATYPE_SHIFT); + break; + case SND_SOC_DAIFMT_LEFT_J: + iface_reg1 |= (AIC31XX_LEFT_JUSTIFIED_MODE << + AIC31XX_IFACE1_DATATYPE_SHIFT); + break; + default: + dev_err(codec->dev, "Invalid DAI interface format\n"); + return -EINVAL; + } + + snd_soc_update_bits(codec, AIC31XX_IFACE1, + AIC31XX_IFACE1_DATATYPE_MASK | + AIC31XX_IFACE1_MASTER_MASK, + iface_reg1); + snd_soc_update_bits(codec, AIC31XX_DATA_OFFSET, + AIC31XX_DATA_OFFSET_MASK, + dsp_a_val); + snd_soc_update_bits(codec, AIC31XX_IFACE2, + AIC31XX_BCLKINV_MASK, + iface_reg3); + + return 0; +} + +static int aic31xx_set_dai_sysclk(struct snd_soc_dai *codec_dai, + int clk_id, unsigned int freq, int dir) +{ + struct snd_soc_codec *codec = codec_dai->codec; + struct aic31xx_priv *aic31xx = snd_soc_codec_get_drvdata(codec); + int i; + + dev_dbg(codec->dev, "## %s: clk_id = %d, freq = %d, dir = %d\n", + __func__, clk_id, freq, dir); + + for (i = 0; aic31xx_divs[i].mclk != freq; i++) { + if (i == ARRAY_SIZE(aic31xx_divs)) { + dev_err(aic31xx->dev, "%s: Unsupported frequency %d\n", + __func__, freq); + return -EINVAL; + } + } + + /* set clock on MCLK, BCLK, or GPIO1 as PLL input */ + snd_soc_update_bits(codec, AIC31XX_CLKMUX, AIC31XX_PLL_CLKIN_MASK, + clk_id << AIC31XX_PLL_CLKIN_SHIFT); + + aic31xx->sysclk = freq; + return 0; +} + +static int aic31xx_regulator_event(struct notifier_block *nb, + unsigned long event, void *data) +{ + struct aic31xx_disable_nb *disable_nb = + container_of(nb, struct aic31xx_disable_nb, nb); + struct aic31xx_priv *aic31xx = disable_nb->aic31xx; + + if (event & REGULATOR_EVENT_DISABLE) { + /* + * Put codec to reset and as at least one of the + * supplies was disabled. + */ + if (gpio_is_valid(aic31xx->pdata.gpio_reset)) + gpio_set_value(aic31xx->pdata.gpio_reset, 0); + + regcache_mark_dirty(aic31xx->regmap); + dev_dbg(aic31xx->dev, "## %s: DISABLE received\n", __func__); + } + + return 0; +} + +static void aic31xx_clk_on(struct snd_soc_codec *codec) +{ + struct aic31xx_priv *aic31xx = snd_soc_codec_get_drvdata(codec); + u8 mask = AIC31XX_PM_MASK; + u8 on = AIC31XX_PM_MASK; + + dev_dbg(codec->dev, "codec clock -> on (rate %d)\n", + aic31xx_divs[aic31xx->rate_div_line].rate); + snd_soc_update_bits(codec, AIC31XX_PLLPR, mask, on); + mdelay(10); + snd_soc_update_bits(codec, AIC31XX_NDAC, mask, on); + snd_soc_update_bits(codec, AIC31XX_MDAC, mask, on); + if (aic31xx_divs[aic31xx->rate_div_line].nadc) + snd_soc_update_bits(codec, AIC31XX_NADC, mask, on); + if (aic31xx_divs[aic31xx->rate_div_line].madc) + snd_soc_update_bits(codec, AIC31XX_MADC, mask, on); + snd_soc_update_bits(codec, AIC31XX_BCLKN, mask, on); +} + +static void aic31xx_clk_off(struct snd_soc_codec *codec) +{ + u8 mask = AIC31XX_PM_MASK; + u8 off = 0; + + dev_dbg(codec->dev, "codec clock -> off\n"); + snd_soc_update_bits(codec, AIC31XX_BCLKN, mask, off); + snd_soc_update_bits(codec, AIC31XX_MADC, mask, off); + snd_soc_update_bits(codec, AIC31XX_NADC, mask, off); + snd_soc_update_bits(codec, AIC31XX_MDAC, mask, off); + snd_soc_update_bits(codec, AIC31XX_NDAC, mask, off); + snd_soc_update_bits(codec, AIC31XX_PLLPR, mask, off); +} + +static int aic31xx_power_on(struct snd_soc_codec *codec) +{ + struct aic31xx_priv *aic31xx = snd_soc_codec_get_drvdata(codec); + int ret = 0; + + ret = regulator_bulk_enable(ARRAY_SIZE(aic31xx->supplies), + aic31xx->supplies); + if (ret) + return ret; + + if (gpio_is_valid(aic31xx->pdata.gpio_reset)) { + gpio_set_value(aic31xx->pdata.gpio_reset, 1); + udelay(100); + } + regcache_cache_only(aic31xx->regmap, false); + ret = regcache_sync(aic31xx->regmap); + if (ret != 0) { + dev_err(codec->dev, + "Failed to restore cache: %d\n", ret); + regcache_cache_only(aic31xx->regmap, true); + regulator_bulk_disable(ARRAY_SIZE(aic31xx->supplies), + aic31xx->supplies); + return ret; + } + return 0; +} + +static int aic31xx_power_off(struct snd_soc_codec *codec) +{ + struct aic31xx_priv *aic31xx = snd_soc_codec_get_drvdata(codec); + int ret = 0; + + regcache_cache_only(aic31xx->regmap, true); + ret = regulator_bulk_disable(ARRAY_SIZE(aic31xx->supplies), + aic31xx->supplies); + + return ret; +} + +static int aic31xx_set_bias_level(struct snd_soc_codec *codec, + enum snd_soc_bias_level level) +{ + dev_dbg(codec->dev, "## %s: %d -> %d\n", __func__, + codec->dapm.bias_level, level); + + switch (level) { + case SND_SOC_BIAS_ON: + break; + case SND_SOC_BIAS_PREPARE: + if (codec->dapm.bias_level == SND_SOC_BIAS_STANDBY) + aic31xx_clk_on(codec); + break; + case SND_SOC_BIAS_STANDBY: + switch (codec->dapm.bias_level) { + case SND_SOC_BIAS_OFF: + aic31xx_power_on(codec); + break; + case SND_SOC_BIAS_PREPARE: + aic31xx_clk_off(codec); + break; + default: + BUG(); + } + break; + case SND_SOC_BIAS_OFF: + if (codec->dapm.bias_level == SND_SOC_BIAS_STANDBY) + aic31xx_power_off(codec); + break; + } + codec->dapm.bias_level = level; + + return 0; +} + +static int aic31xx_suspend(struct snd_soc_codec *codec) +{ + aic31xx_set_bias_level(codec, SND_SOC_BIAS_OFF); + return 0; +} + +static int aic31xx_resume(struct snd_soc_codec *codec) +{ + aic31xx_set_bias_level(codec, SND_SOC_BIAS_STANDBY); + return 0; +} + +static int aic31xx_codec_probe(struct snd_soc_codec *codec) +{ + int ret = 0; + struct aic31xx_priv *aic31xx = snd_soc_codec_get_drvdata(codec); + int i; + + dev_dbg(aic31xx->dev, "## %s\n", __func__); + + aic31xx = snd_soc_codec_get_drvdata(codec); + + aic31xx->codec = codec; + + for (i = 0; i < ARRAY_SIZE(aic31xx->supplies); i++) { + aic31xx->disable_nb[i].nb.notifier_call = + aic31xx_regulator_event; + aic31xx->disable_nb[i].aic31xx = aic31xx; + ret = regulator_register_notifier(aic31xx->supplies[i].consumer, + &aic31xx->disable_nb[i].nb); + if (ret) { + dev_err(codec->dev, + "Failed to request regulator notifier: %d\n", + ret); + return ret; + } + } + + regcache_cache_only(aic31xx->regmap, true); + regcache_mark_dirty(aic31xx->regmap); + + ret = aic31xx_add_controls(codec); + if (ret) + return ret; + + ret = aic31xx_add_widgets(codec); + + return ret; +} + +static int aic31xx_codec_remove(struct snd_soc_codec *codec) +{ + struct aic31xx_priv *aic31xx = snd_soc_codec_get_drvdata(codec); + int i; + /* power down chip */ + aic31xx_set_bias_level(codec, SND_SOC_BIAS_OFF); + + for (i = 0; i < ARRAY_SIZE(aic31xx->supplies); i++) + regulator_unregister_notifier(aic31xx->supplies[i].consumer, + &aic31xx->disable_nb[i].nb); + + return 0; +} + +static struct snd_soc_codec_driver soc_codec_driver_aic31xx = { + .probe = aic31xx_codec_probe, + .remove = aic31xx_codec_remove, + .suspend = aic31xx_suspend, + .resume = aic31xx_resume, + .set_bias_level = aic31xx_set_bias_level, + .controls = aic31xx_snd_controls, + .num_controls = ARRAY_SIZE(aic31xx_snd_controls), + .dapm_widgets = aic31xx_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(aic31xx_dapm_widgets), + .dapm_routes = aic31xx_audio_map, + .num_dapm_routes = ARRAY_SIZE(aic31xx_audio_map), +}; + +static struct snd_soc_dai_ops aic31xx_dai_ops = { + .hw_params = aic31xx_hw_params, + .set_sysclk = aic31xx_set_dai_sysclk, + .set_fmt = aic31xx_set_dai_fmt, + .digital_mute = aic31xx_dac_mute, +}; + +static struct snd_soc_dai_driver aic31xx_dai_driver[] = { + { + .name = "tlv320aic31xx-hifi", + .playback = { + .stream_name = "Playback", + .channels_min = 1, + .channels_max = 2, + .rates = AIC31XX_RATES, + .formats = AIC31XX_FORMATS, + }, + .capture = { + .stream_name = "Capture", + .channels_min = 1, + .channels_max = 2, + .rates = AIC31XX_RATES, + .formats = AIC31XX_FORMATS, + }, + .ops = &aic31xx_dai_ops, + .symmetric_rates = 1, + } +}; + +#if defined(CONFIG_OF) +static const struct of_device_id tlv320aic31xx_of_match[] = { + { .compatible = "ti,tlv320aic310x" }, + { .compatible = "ti,tlv320aic311x" }, + { .compatible = "ti,tlv320aic3100" }, + { .compatible = "ti,tlv320aic3110" }, + { .compatible = "ti,tlv320aic3120" }, + { .compatible = "ti,tlv320aic3111" }, + {}, +}; +MODULE_DEVICE_TABLE(of, tlv320aic31xx_of_match); + +static void aic31xx_pdata_from_of(struct aic31xx_priv *aic31xx) +{ + struct device_node *np = aic31xx->dev->of_node; + unsigned int value = MICBIAS_2_0V; + int ret; + + of_property_read_u32(np, "ai31xx-micbias-vg", &value); + switch (value) { + case MICBIAS_2_0V: + case MICBIAS_2_5V: + case MICBIAS_AVDDV: + aic31xx->pdata.micbias_vg = value; + break; + default: + dev_err(aic31xx->dev, + "Bad ai31xx-micbias-vg value %d DT\n", + value); + aic31xx->pdata.micbias_vg = MICBIAS_2_0V; + } + + ret = of_get_named_gpio(np, "gpio-reset", 0); + if (ret > 0) + aic31xx->pdata.gpio_reset = ret; +} +#else /* CONFIG_OF */ +static void aic31xx_pdata_from_of(struct aic31xx_priv *aic31xx) +{ +} +#endif /* CONFIG_OF */ + +static void aic31xx_device_init(struct aic31xx_priv *aic31xx) +{ + int ret, i; + + dev_set_drvdata(aic31xx->dev, aic31xx); + + if (dev_get_platdata(aic31xx->dev)) + memcpy(&aic31xx->pdata, dev_get_platdata(aic31xx->dev), + sizeof(aic31xx->pdata)); + else if (aic31xx->dev->of_node) + aic31xx_pdata_from_of(aic31xx); + + if (aic31xx->pdata.gpio_reset) { + ret = devm_gpio_request_one(aic31xx->dev, + aic31xx->pdata.gpio_reset, + GPIOF_OUT_INIT_HIGH, + "aic31xx-reset-pin"); + if (ret < 0) { + dev_err(aic31xx->dev, "not able to acquire gpio\n"); + return; + } + } + + for (i = 0; i < ARRAY_SIZE(aic31xx->supplies); i++) + aic31xx->supplies[i].supply = aic31xx_supply_names[i]; + + ret = devm_regulator_bulk_get(aic31xx->dev, + ARRAY_SIZE(aic31xx->supplies), + aic31xx->supplies); + if (ret != 0) + dev_err(aic31xx->dev, "Failed to request supplies: %d\n", ret); + +} + +static int aic31xx_i2c_probe(struct i2c_client *i2c, + const struct i2c_device_id *id) +{ + struct aic31xx_priv *aic31xx; + int ret; + const struct regmap_config *regmap_config; + + dev_dbg(&i2c->dev, "## %s: %s codec_type = %d\n", __func__, + id->name, (int) id->driver_data); + + regmap_config = &aic31xx_i2c_regmap; + + aic31xx = devm_kzalloc(&i2c->dev, sizeof(*aic31xx), GFP_KERNEL); + if (aic31xx == NULL) + return -ENOMEM; + + aic31xx->regmap = devm_regmap_init_i2c(i2c, regmap_config); + if (IS_ERR(aic31xx->regmap)) { + ret = PTR_ERR(aic31xx->regmap); + dev_err(&i2c->dev, "Failed to allocate register map: %d\n", + ret); + return ret; + } + aic31xx->dev = &i2c->dev; + + aic31xx->pdata.codec_type = id->driver_data; + + aic31xx_device_init(aic31xx); + + return snd_soc_register_codec(&i2c->dev, &soc_codec_driver_aic31xx, + aic31xx_dai_driver, + ARRAY_SIZE(aic31xx_dai_driver)); +} + +static int aic31xx_i2c_remove(struct i2c_client *i2c) +{ + snd_soc_unregister_codec(&i2c->dev); + return 0; +} + +static const struct i2c_device_id aic31xx_i2c_id[] = { + { "tlv320aic310x", AIC3100 }, + { "tlv320aic311x", AIC3110 }, + { "tlv320aic3100", AIC3100 }, + { "tlv320aic3110", AIC3110 }, + { "tlv320aic3120", AIC3120 }, + { "tlv320aic3111", AIC3111 }, + { } +}; +MODULE_DEVICE_TABLE(i2c, aic31xx_i2c_id); + +static struct i2c_driver aic31xx_i2c_driver = { + .driver = { + .name = "tlv320aic31xx-codec", + .owner = THIS_MODULE, + .of_match_table = of_match_ptr(tlv320aic31xx_of_match), + }, + .probe = aic31xx_i2c_probe, + .remove = aic31xx_i2c_remove, + .id_table = aic31xx_i2c_id, +}; + +module_i2c_driver(aic31xx_i2c_driver); + +MODULE_DESCRIPTION("ASoC TLV320AIC3111 codec driver"); +MODULE_AUTHOR("Jyri Sarha"); +MODULE_LICENSE("GPL"); diff --git a/sound/soc/codecs/tlv320aic31xx.h b/sound/soc/codecs/tlv320aic31xx.h new file mode 100644 index 00000000000..52ed57c69df --- /dev/null +++ b/sound/soc/codecs/tlv320aic31xx.h @@ -0,0 +1,258 @@ +/* + * ALSA SoC TLV320AIC31XX codec driver + * + * Copyright (C) 2013 Texas Instruments, Inc. + * + * This package is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED + * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. + * + */ +#ifndef _TLV320AIC31XX_H +#define _TLV320AIC31XX_H + +#define AIC31XX_RATES SNDRV_PCM_RATE_8000_192000 + +#define AIC31XX_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE \ + | SNDRV_PCM_FMTBIT_S24_3LE | SNDRV_PCM_FMTBIT_S32_LE) + + +#define AIC31XX_STEREO_CLASS_D_BIT 0x1 +#define AIC31XX_MINIDSP_BIT 0x2 + +enum aic31xx_type { + AIC3100 = 0, + AIC3110 = AIC31XX_STEREO_CLASS_D_BIT, + AIC3120 = AIC31XX_MINIDSP_BIT, + AIC3111 = (AIC31XX_STEREO_CLASS_D_BIT | AIC31XX_MINIDSP_BIT), +}; + +struct aic31xx_pdata { + enum aic31xx_type codec_type; + unsigned int gpio_reset; + int micbias_vg; +}; + +/* Page Control Register */ +#define AIC31XX_PAGECTL 0x00 + +/* Page 0 Registers */ +/* Software reset register */ +#define AIC31XX_RESET 0x01 +/* OT FLAG register */ +#define AIC31XX_OT_FLAG 0x03 +/* Clock clock Gen muxing, Multiplexers*/ +#define AIC31XX_CLKMUX 0x04 +/* PLL P and R-VAL register */ +#define AIC31XX_PLLPR 0x05 +/* PLL J-VAL register */ +#define AIC31XX_PLLJ 0x06 +/* PLL D-VAL MSB register */ +#define AIC31XX_PLLDMSB 0x07 +/* PLL D-VAL LSB register */ +#define AIC31XX_PLLDLSB 0x08 +/* DAC NDAC_VAL register*/ +#define AIC31XX_NDAC 0x0B +/* DAC MDAC_VAL register */ +#define AIC31XX_MDAC 0x0C +/* DAC OSR setting register 1, MSB value */ +#define AIC31XX_DOSRMSB 0x0D +/* DAC OSR setting register 2, LSB value */ +#define AIC31XX_DOSRLSB 0x0E +#define AIC31XX_MINI_DSP_INPOL 0x10 +/* Clock setting register 8, PLL */ +#define AIC31XX_NADC 0x12 +/* Clock setting register 9, PLL */ +#define AIC31XX_MADC 0x13 +/* ADC Oversampling (AOSR) Register */ +#define AIC31XX_AOSR 0x14 +/* Clock setting register 9, Multiplexers */ +#define AIC31XX_CLKOUTMUX 0x19 +/* Clock setting register 10, CLOCKOUT M divider value */ +#define AIC31XX_CLKOUTMVAL 0x1A +/* Audio Interface Setting Register 1 */ +#define AIC31XX_IFACE1 0x1B +/* Audio Data Slot Offset Programming */ +#define AIC31XX_DATA_OFFSET 0x1C +/* Audio Interface Setting Register 2 */ +#define AIC31XX_IFACE2 0x1D +/* Clock setting register 11, BCLK N Divider */ +#define AIC31XX_BCLKN 0x1E +/* Audio Interface Setting Register 3, Secondary Audio Interface */ +#define AIC31XX_IFACESEC1 0x1F +/* Audio Interface Setting Register 4 */ +#define AIC31XX_IFACESEC2 0x20 +/* Audio Interface Setting Register 5 */ +#define AIC31XX_IFACESEC3 0x21 +/* I2C Bus Condition */ +#define AIC31XX_I2C 0x22 +/* ADC FLAG */ +#define AIC31XX_ADCFLAG 0x24 +/* DAC Flag Registers */ +#define AIC31XX_DACFLAG1 0x25 +#define AIC31XX_DACFLAG2 0x26 +/* Sticky Interrupt flag (overflow) */ +#define AIC31XX_OFFLAG 0x27 +/* Sticy DAC Interrupt flags */ +#define AIC31XX_INTRDACFLAG 0x2C +/* Sticy ADC Interrupt flags */ +#define AIC31XX_INTRADCFLAG 0x2D +/* DAC Interrupt flags 2 */ +#define AIC31XX_INTRDACFLAG2 0x2E +/* ADC Interrupt flags 2 */ +#define AIC31XX_INTRADCFLAG2 0x2F +/* INT1 interrupt control */ +#define AIC31XX_INT1CTRL 0x30 +/* INT2 interrupt control */ +#define AIC31XX_INT2CTRL 0x31 +/* GPIO1 control */ +#define AIC31XX_GPIO1 0x33 + +#define AIC31XX_DACPRB 0x3C +/* ADC Instruction Set Register */ +#define AIC31XX_ADCPRB 0x3D +/* DAC channel setup register */ +#define AIC31XX_DACSETUP 0x3F +/* DAC Mute and volume control register */ +#define AIC31XX_DACMUTE 0x40 +/* Left DAC channel digital volume control */ +#define AIC31XX_LDACVOL 0x41 +/* Right DAC channel digital volume control */ +#define AIC31XX_RDACVOL 0x42 +/* Headset detection */ +#define AIC31XX_HSDETECT 0x43 +/* ADC Digital Mic */ +#define AIC31XX_ADCSETUP 0x51 +/* ADC Digital Volume Control Fine Adjust */ +#define AIC31XX_ADCFGA 0x52 +/* ADC Digital Volume Control Coarse Adjust */ +#define AIC31XX_ADCVOL 0x53 + + +/* Page 1 Registers */ +/* Headphone drivers */ +#define AIC31XX_HPDRIVER 0x9F +/* Class-D Speakear Amplifier */ +#define AIC31XX_SPKAMP 0xA0 +/* HP Output Drivers POP Removal Settings */ +#define AIC31XX_HPPOP 0xA1 +/* Output Driver PGA Ramp-Down Period Control */ +#define AIC31XX_SPPGARAMP 0xA2 +/* DAC_L and DAC_R Output Mixer Routing */ +#define AIC31XX_DACMIXERROUTE 0xA3 +/* Left Analog Vol to HPL */ +#define AIC31XX_LANALOGHPL 0xA4 +/* Right Analog Vol to HPR */ +#define AIC31XX_RANALOGHPR 0xA5 +/* Left Analog Vol to SPL */ +#define AIC31XX_LANALOGSPL 0xA6 +/* Right Analog Vol to SPR */ +#define AIC31XX_RANALOGSPR 0xA7 +/* HPL Driver */ +#define AIC31XX_HPLGAIN 0xA8 +/* HPR Driver */ +#define AIC31XX_HPRGAIN 0xA9 +/* SPL Driver */ +#define AIC31XX_SPLGAIN 0xAA +/* SPR Driver */ +#define AIC31XX_SPRGAIN 0xAB +/* HP Driver Control */ +#define AIC31XX_HPCONTROL 0xAC +/* MIC Bias Control */ +#define AIC31XX_MICBIAS 0xAE +/* MIC PGA*/ +#define AIC31XX_MICPGA 0xAF +/* Delta-Sigma Mono ADC Channel Fine-Gain Input Selection for P-Terminal */ +#define AIC31XX_MICPGAPI 0xB0 +/* ADC Input Selection for M-Terminal */ +#define AIC31XX_MICPGAMI 0xB1 +/* Input CM Settings */ +#define AIC31XX_MICPGACM 0xB2 + +/* Bits, masks and shifts */ + +/* AIC31XX_CLKMUX */ +#define AIC31XX_PLL_CLKIN_MASK 0x0c +#define AIC31XX_PLL_CLKIN_SHIFT 2 +#define AIC31XX_PLL_CLKIN_MCLK 0 +#define AIC31XX_CODEC_CLKIN_MASK 0x03 +#define AIC31XX_CODEC_CLKIN_SHIFT 0 +#define AIC31XX_CODEC_CLKIN_PLL 3 +#define AIC31XX_CODEC_CLKIN_BCLK 1 + +/* AIC31XX_PLLPR, AIC31XX_NDAC, AIC31XX_MDAC, AIC31XX_NADC, AIC31XX_MADC, + AIC31XX_BCLKN */ +#define AIC31XX_PLL_MASK 0x7f +#define AIC31XX_PM_MASK 0x80 + +/* AIC31XX_IFACE1 */ +#define AIC31XX_WORD_LEN_16BITS 0x00 +#define AIC31XX_WORD_LEN_20BITS 0x01 +#define AIC31XX_WORD_LEN_24BITS 0x02 +#define AIC31XX_WORD_LEN_32BITS 0x03 +#define AIC31XX_IFACE1_DATALEN_MASK 0x30 +#define AIC31XX_IFACE1_DATALEN_SHIFT (4) +#define AIC31XX_IFACE1_DATATYPE_MASK 0xC0 +#define AIC31XX_IFACE1_DATATYPE_SHIFT (6) +#define AIC31XX_I2S_MODE 0x00 +#define AIC31XX_DSP_MODE 0x01 +#define AIC31XX_RIGHT_JUSTIFIED_MODE 0x02 +#define AIC31XX_LEFT_JUSTIFIED_MODE 0x03 +#define AIC31XX_IFACE1_MASTER_MASK 0x0C +#define AIC31XX_BCLK_MASTER 0x08 +#define AIC31XX_WCLK_MASTER 0x04 + +/* AIC31XX_DATA_OFFSET */ +#define AIC31XX_DATA_OFFSET_MASK 0xFF + +/* AIC31XX_IFACE2 */ +#define AIC31XX_BCLKINV_MASK 0x08 +#define AIC31XX_BDIVCLK_MASK 0x03 +#define AIC31XX_DAC2BCLK 0x00 +#define AIC31XX_DACMOD2BCLK 0x01 +#define AIC31XX_ADC2BCLK 0x02 +#define AIC31XX_ADCMOD2BCLK 0x03 + +/* AIC31XX_ADCFLAG */ +#define AIC31XX_ADCPWRSTATUS_MASK 0x40 + +/* AIC31XX_DACFLAG1 */ +#define AIC31XX_LDACPWRSTATUS_MASK 0x80 +#define AIC31XX_RDACPWRSTATUS_MASK 0x08 +#define AIC31XX_HPLDRVPWRSTATUS_MASK 0x20 +#define AIC31XX_HPRDRVPWRSTATUS_MASK 0x02 +#define AIC31XX_SPLDRVPWRSTATUS_MASK 0x10 +#define AIC31XX_SPRDRVPWRSTATUS_MASK 0x01 + +/* AIC31XX_INTRDACFLAG */ +#define AIC31XX_HPSCDETECT_MASK 0x80 +#define AIC31XX_BUTTONPRESS_MASK 0x20 +#define AIC31XX_HSPLUG_MASK 0x10 +#define AIC31XX_LDRCTHRES_MASK 0x08 +#define AIC31XX_RDRCTHRES_MASK 0x04 +#define AIC31XX_DACSINT_MASK 0x02 +#define AIC31XX_DACAINT_MASK 0x01 + +/* AIC31XX_INT1CTRL */ +#define AIC31XX_HSPLUGDET_MASK 0x80 +#define AIC31XX_BUTTONPRESSDET_MASK 0x40 +#define AIC31XX_DRCTHRES_MASK 0x20 +#define AIC31XX_AGCNOISE_MASK 0x10 +#define AIC31XX_OC_MASK 0x08 +#define AIC31XX_ENGINE_MASK 0x04 + +/* AIC31XX_DACSETUP */ +#define AIC31XX_SOFTSTEP_MASK 0x03 + +/* AIC31XX_DACMUTE */ +#define AIC31XX_DACMUTE_MASK 0x0C + +/* AIC31XX_MICBIAS */ +#define AIC31XX_MICBIAS_MASK 0x03 +#define AIC31XX_MICBIAS_SHIFT 0 + +#endif /* _TLV320AIC31XX_H */ diff --git a/sound/soc/codecs/tlv320aic32x4.c b/sound/soc/codecs/tlv320aic32x4.c index 688151ba309..1d9b117345a 100644 --- a/sound/soc/codecs/tlv320aic32x4.c +++ b/sound/soc/codecs/tlv320aic32x4.c @@ -29,9 +29,12 @@ #include <linux/delay.h> #include <linux/pm.h> #include <linux/gpio.h> +#include <linux/of_gpio.h> #include <linux/i2c.h> #include <linux/cdev.h> #include <linux/slab.h> +#include <linux/clk.h> +#include <linux/regulator/consumer.h> #include <sound/tlv320aic32x4.h> #include <sound/core.h> @@ -66,20 +69,32 @@ struct aic32x4_priv { u32 micpga_routing; bool swapdacs; int rstn_gpio; + struct clk *mclk; + + struct regulator *supply_ldo; + struct regulator *supply_iov; + struct regulator *supply_dv; + struct regulator *supply_av; }; -/* 0dB min, 1dB steps */ -static DECLARE_TLV_DB_SCALE(tlv_step_1, 0, 100, 0); /* 0dB min, 0.5dB steps */ static DECLARE_TLV_DB_SCALE(tlv_step_0_5, 0, 50, 0); +/* -63.5dB min, 0.5dB steps */ +static DECLARE_TLV_DB_SCALE(tlv_pcm, -6350, 50, 0); +/* -6dB min, 1dB steps */ +static DECLARE_TLV_DB_SCALE(tlv_driver_gain, -600, 100, 0); +/* -12dB min, 0.5dB steps */ +static DECLARE_TLV_DB_SCALE(tlv_adc_vol, -1200, 50, 0); static const struct snd_kcontrol_new aic32x4_snd_controls[] = { - SOC_DOUBLE_R_TLV("PCM Playback Volume", AIC32X4_LDACVOL, - AIC32X4_RDACVOL, 0, 0x30, 0, tlv_step_0_5), - SOC_DOUBLE_R_TLV("HP Driver Gain Volume", AIC32X4_HPLGAIN, - AIC32X4_HPRGAIN, 0, 0x1D, 0, tlv_step_1), - SOC_DOUBLE_R_TLV("LO Driver Gain Volume", AIC32X4_LOLGAIN, - AIC32X4_LORGAIN, 0, 0x1D, 0, tlv_step_1), + SOC_DOUBLE_R_S_TLV("PCM Playback Volume", AIC32X4_LDACVOL, + AIC32X4_RDACVOL, 0, -0x7f, 0x30, 7, 0, tlv_pcm), + SOC_DOUBLE_R_S_TLV("HP Driver Gain Volume", AIC32X4_HPLGAIN, + AIC32X4_HPRGAIN, 0, -0x6, 0x1d, 5, 0, + tlv_driver_gain), + SOC_DOUBLE_R_S_TLV("LO Driver Gain Volume", AIC32X4_LOLGAIN, + AIC32X4_LORGAIN, 0, -0x6, 0x1d, 5, 0, + tlv_driver_gain), SOC_DOUBLE_R("HP DAC Playback Switch", AIC32X4_HPLGAIN, AIC32X4_HPRGAIN, 6, 0x01, 1), SOC_DOUBLE_R("LO DAC Playback Switch", AIC32X4_LOLGAIN, @@ -90,8 +105,8 @@ static const struct snd_kcontrol_new aic32x4_snd_controls[] = { SOC_SINGLE("ADCFGA Left Mute Switch", AIC32X4_ADCFGA, 7, 1, 0), SOC_SINGLE("ADCFGA Right Mute Switch", AIC32X4_ADCFGA, 3, 1, 0), - SOC_DOUBLE_R_TLV("ADC Level Volume", AIC32X4_LADCVOL, - AIC32X4_RADCVOL, 0, 0x28, 0, tlv_step_0_5), + SOC_DOUBLE_R_S_TLV("ADC Level Volume", AIC32X4_LADCVOL, + AIC32X4_RADCVOL, 0, -0x18, 0x28, 6, 0, tlv_adc_vol), SOC_DOUBLE_R_TLV("PGA Level Volume", AIC32X4_LMICPGAVOL, AIC32X4_RMICPGAVOL, 0, 0x5f, 0, tlv_step_0_5), @@ -480,8 +495,18 @@ static int aic32x4_mute(struct snd_soc_dai *dai, int mute) static int aic32x4_set_bias_level(struct snd_soc_codec *codec, enum snd_soc_bias_level level) { + struct aic32x4_priv *aic32x4 = snd_soc_codec_get_drvdata(codec); + int ret; + switch (level) { case SND_SOC_BIAS_ON: + /* Switch on master clock */ + ret = clk_prepare_enable(aic32x4->mclk); + if (ret) { + dev_err(codec->dev, "Failed to enable master clock\n"); + return ret; + } + /* Switch on PLL */ snd_soc_update_bits(codec, AIC32X4_PLLPR, AIC32X4_PLLEN, AIC32X4_PLLEN); @@ -509,29 +534,32 @@ static int aic32x4_set_bias_level(struct snd_soc_codec *codec, case SND_SOC_BIAS_PREPARE: break; case SND_SOC_BIAS_STANDBY: - /* Switch off PLL */ - snd_soc_update_bits(codec, AIC32X4_PLLPR, - AIC32X4_PLLEN, 0); + /* Switch off BCLK_N Divider */ + snd_soc_update_bits(codec, AIC32X4_BCLKN, + AIC32X4_BCLKEN, 0); - /* Switch off NDAC Divider */ - snd_soc_update_bits(codec, AIC32X4_NDAC, - AIC32X4_NDACEN, 0); + /* Switch off MADC Divider */ + snd_soc_update_bits(codec, AIC32X4_MADC, + AIC32X4_MADCEN, 0); + + /* Switch off NADC Divider */ + snd_soc_update_bits(codec, AIC32X4_NADC, + AIC32X4_NADCEN, 0); /* Switch off MDAC Divider */ snd_soc_update_bits(codec, AIC32X4_MDAC, AIC32X4_MDACEN, 0); - /* Switch off NADC Divider */ - snd_soc_update_bits(codec, AIC32X4_NADC, - AIC32X4_NADCEN, 0); + /* Switch off NDAC Divider */ + snd_soc_update_bits(codec, AIC32X4_NDAC, + AIC32X4_NDACEN, 0); - /* Switch off MADC Divider */ - snd_soc_update_bits(codec, AIC32X4_MADC, - AIC32X4_MADCEN, 0); + /* Switch off PLL */ + snd_soc_update_bits(codec, AIC32X4_PLLPR, + AIC32X4_PLLEN, 0); - /* Switch off BCLK_N Divider */ - snd_soc_update_bits(codec, AIC32X4_BCLKN, - AIC32X4_BCLKEN, 0); + /* Switch off master clock */ + clk_disable_unprepare(aic32x4->mclk); break; case SND_SOC_BIAS_OFF: break; @@ -586,9 +614,7 @@ static int aic32x4_probe(struct snd_soc_codec *codec) struct aic32x4_priv *aic32x4 = snd_soc_codec_get_drvdata(codec); u32 tmp_reg; - snd_soc_codec_set_cache_io(codec, 8, 8, SND_SOC_REGMAP); - - if (aic32x4->rstn_gpio >= 0) { + if (gpio_is_valid(aic32x4->rstn_gpio)) { ndelay(10); gpio_set_value(aic32x4->rstn_gpio, 1); } @@ -663,11 +689,122 @@ static struct snd_soc_codec_driver soc_codec_dev_aic32x4 = { .num_dapm_routes = ARRAY_SIZE(aic32x4_dapm_routes), }; +static int aic32x4_parse_dt(struct aic32x4_priv *aic32x4, + struct device_node *np) +{ + aic32x4->swapdacs = false; + aic32x4->micpga_routing = 0; + aic32x4->rstn_gpio = of_get_named_gpio(np, "reset-gpios", 0); + + return 0; +} + +static void aic32x4_disable_regulators(struct aic32x4_priv *aic32x4) +{ + regulator_disable(aic32x4->supply_iov); + + if (!IS_ERR(aic32x4->supply_ldo)) + regulator_disable(aic32x4->supply_ldo); + + if (!IS_ERR(aic32x4->supply_dv)) + regulator_disable(aic32x4->supply_dv); + + if (!IS_ERR(aic32x4->supply_av)) + regulator_disable(aic32x4->supply_av); +} + +static int aic32x4_setup_regulators(struct device *dev, + struct aic32x4_priv *aic32x4) +{ + int ret = 0; + + aic32x4->supply_ldo = devm_regulator_get_optional(dev, "ldoin"); + aic32x4->supply_iov = devm_regulator_get(dev, "iov"); + aic32x4->supply_dv = devm_regulator_get_optional(dev, "dv"); + aic32x4->supply_av = devm_regulator_get_optional(dev, "av"); + + /* Check if the regulator requirements are fulfilled */ + + if (IS_ERR(aic32x4->supply_iov)) { + dev_err(dev, "Missing supply 'iov'\n"); + return PTR_ERR(aic32x4->supply_iov); + } + + if (IS_ERR(aic32x4->supply_ldo)) { + if (PTR_ERR(aic32x4->supply_ldo) == -EPROBE_DEFER) + return -EPROBE_DEFER; + + if (IS_ERR(aic32x4->supply_dv)) { + dev_err(dev, "Missing supply 'dv' or 'ldoin'\n"); + return PTR_ERR(aic32x4->supply_dv); + } + if (IS_ERR(aic32x4->supply_av)) { + dev_err(dev, "Missing supply 'av' or 'ldoin'\n"); + return PTR_ERR(aic32x4->supply_av); + } + } else { + if (IS_ERR(aic32x4->supply_dv) && + PTR_ERR(aic32x4->supply_dv) == -EPROBE_DEFER) + return -EPROBE_DEFER; + if (IS_ERR(aic32x4->supply_av) && + PTR_ERR(aic32x4->supply_av) == -EPROBE_DEFER) + return -EPROBE_DEFER; + } + + ret = regulator_enable(aic32x4->supply_iov); + if (ret) { + dev_err(dev, "Failed to enable regulator iov\n"); + return ret; + } + + if (!IS_ERR(aic32x4->supply_ldo)) { + ret = regulator_enable(aic32x4->supply_ldo); + if (ret) { + dev_err(dev, "Failed to enable regulator ldo\n"); + goto error_ldo; + } + } + + if (!IS_ERR(aic32x4->supply_dv)) { + ret = regulator_enable(aic32x4->supply_dv); + if (ret) { + dev_err(dev, "Failed to enable regulator dv\n"); + goto error_dv; + } + } + + if (!IS_ERR(aic32x4->supply_av)) { + ret = regulator_enable(aic32x4->supply_av); + if (ret) { + dev_err(dev, "Failed to enable regulator av\n"); + goto error_av; + } + } + + if (!IS_ERR(aic32x4->supply_ldo) && IS_ERR(aic32x4->supply_av)) + aic32x4->power_cfg |= AIC32X4_PWR_AIC32X4_LDO_ENABLE; + + return 0; + +error_av: + if (!IS_ERR(aic32x4->supply_dv)) + regulator_disable(aic32x4->supply_dv); + +error_dv: + if (!IS_ERR(aic32x4->supply_ldo)) + regulator_disable(aic32x4->supply_ldo); + +error_ldo: + regulator_disable(aic32x4->supply_iov); + return ret; +} + static int aic32x4_i2c_probe(struct i2c_client *i2c, const struct i2c_device_id *id) { struct aic32x4_pdata *pdata = i2c->dev.platform_data; struct aic32x4_priv *aic32x4; + struct device_node *np = i2c->dev.of_node; int ret; aic32x4 = devm_kzalloc(&i2c->dev, sizeof(struct aic32x4_priv), @@ -686,6 +823,12 @@ static int aic32x4_i2c_probe(struct i2c_client *i2c, aic32x4->swapdacs = pdata->swapdacs; aic32x4->micpga_routing = pdata->micpga_routing; aic32x4->rstn_gpio = pdata->rstn_gpio; + } else if (np) { + ret = aic32x4_parse_dt(aic32x4, np); + if (ret) { + dev_err(&i2c->dev, "Failed to parse DT node\n"); + return ret; + } } else { aic32x4->power_cfg = 0; aic32x4->swapdacs = false; @@ -693,20 +836,44 @@ static int aic32x4_i2c_probe(struct i2c_client *i2c, aic32x4->rstn_gpio = -1; } - if (aic32x4->rstn_gpio >= 0) { + aic32x4->mclk = devm_clk_get(&i2c->dev, "mclk"); + if (IS_ERR(aic32x4->mclk)) { + dev_err(&i2c->dev, "Failed getting the mclk. The current implementation does not support the usage of this codec without mclk\n"); + return PTR_ERR(aic32x4->mclk); + } + + if (gpio_is_valid(aic32x4->rstn_gpio)) { ret = devm_gpio_request_one(&i2c->dev, aic32x4->rstn_gpio, GPIOF_OUT_INIT_LOW, "tlv320aic32x4 rstn"); if (ret != 0) return ret; } + ret = aic32x4_setup_regulators(&i2c->dev, aic32x4); + if (ret) { + dev_err(&i2c->dev, "Failed to setup regulators\n"); + return ret; + } + ret = snd_soc_register_codec(&i2c->dev, &soc_codec_dev_aic32x4, &aic32x4_dai, 1); - return ret; + if (ret) { + dev_err(&i2c->dev, "Failed to register codec\n"); + aic32x4_disable_regulators(aic32x4); + return ret; + } + + i2c_set_clientdata(i2c, aic32x4); + + return 0; } static int aic32x4_i2c_remove(struct i2c_client *client) { + struct aic32x4_priv *aic32x4 = i2c_get_clientdata(client); + + aic32x4_disable_regulators(aic32x4); + snd_soc_unregister_codec(&client->dev); return 0; } @@ -717,10 +884,17 @@ static const struct i2c_device_id aic32x4_i2c_id[] = { }; MODULE_DEVICE_TABLE(i2c, aic32x4_i2c_id); +static const struct of_device_id aic32x4_of_id[] = { + { .compatible = "ti,tlv320aic32x4", }, + { /* senitel */ } +}; +MODULE_DEVICE_TABLE(of, aic32x4_of_id); + static struct i2c_driver aic32x4_i2c_driver = { .driver = { .name = "tlv320aic32x4", .owner = THIS_MODULE, + .of_match_table = aic32x4_of_id, }, .probe = aic32x4_i2c_probe, .remove = aic32x4_i2c_remove, diff --git a/sound/soc/codecs/tlv320aic3x.c b/sound/soc/codecs/tlv320aic3x.c index 470fbfb4b38..b1835103e9b 100644 --- a/sound/soc/codecs/tlv320aic3x.c +++ b/sound/soc/codecs/tlv320aic3x.c @@ -1344,12 +1344,6 @@ static int aic3x_probe(struct snd_soc_codec *codec) INIT_LIST_HEAD(&aic3x->list); aic3x->codec = codec; - ret = snd_soc_codec_set_cache_io(codec, 8, 8, SND_SOC_REGMAP); - if (ret != 0) { - dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); - return ret; - } - for (i = 0; i < ARRAY_SIZE(aic3x->supplies); i++) { aic3x->disable_nb[i].nb.notifier_call = aic3x_regulator_event; aic3x->disable_nb[i].aic3x = aic3x; diff --git a/sound/soc/codecs/tlv320dac33.c b/sound/soc/codecs/tlv320dac33.c index 4f358393d6d..6bfc8a17331 100644 --- a/sound/soc/codecs/tlv320dac33.c +++ b/sound/soc/codecs/tlv320dac33.c @@ -122,7 +122,6 @@ struct tlv320dac33_priv { unsigned int uthr; enum dac33_state state; - enum snd_soc_control_type control_type; void *control_data; }; @@ -461,7 +460,7 @@ static int dac33_set_fifo_mode(struct snd_kcontrol *kcontrol, if (dac33->fifo_mode == ucontrol->value.integer.value[0]) return 0; /* Do not allow changes while stream is running*/ - if (codec->active) + if (snd_soc_codec_is_active(codec)) return -EPERM; if (ucontrol->value.integer.value[0] < 0 || @@ -478,9 +477,7 @@ static const char *dac33_fifo_mode_texts[] = { "Bypass", "Mode 1", "Mode 7" }; -static const struct soc_enum dac33_fifo_mode_enum = - SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(dac33_fifo_mode_texts), - dac33_fifo_mode_texts); +static SOC_ENUM_SINGLE_EXT_DECL(dac33_fifo_mode_enum, dac33_fifo_mode_texts); /* L/R Line Output Gain */ static const char *lr_lineout_gain_texts[] = { @@ -488,15 +485,13 @@ static const char *lr_lineout_gain_texts[] = { "Line 0dB DAC 12dB", "Line 6dB DAC 18dB", }; -static const struct soc_enum l_lineout_gain_enum = - SOC_ENUM_SINGLE(DAC33_LDAC_PWR_CTRL, 0, - ARRAY_SIZE(lr_lineout_gain_texts), - lr_lineout_gain_texts); +static SOC_ENUM_SINGLE_DECL(l_lineout_gain_enum, + DAC33_LDAC_PWR_CTRL, 0, + lr_lineout_gain_texts); -static const struct soc_enum r_lineout_gain_enum = - SOC_ENUM_SINGLE(DAC33_RDAC_PWR_CTRL, 0, - ARRAY_SIZE(lr_lineout_gain_texts), - lr_lineout_gain_texts); +static SOC_ENUM_SINGLE_DECL(r_lineout_gain_enum, + DAC33_RDAC_PWR_CTRL, 0, + lr_lineout_gain_texts); /* * DACL/R digital volume control: @@ -534,18 +529,16 @@ static const struct snd_kcontrol_new dac33_dapm_abypassr_control = /* LOP L/R invert selection */ static const char *dac33_lr_lom_texts[] = {"DAC", "LOP"}; -static const struct soc_enum dac33_left_lom_enum = - SOC_ENUM_SINGLE(DAC33_OUT_AMP_CTRL, 3, - ARRAY_SIZE(dac33_lr_lom_texts), - dac33_lr_lom_texts); +static SOC_ENUM_SINGLE_DECL(dac33_left_lom_enum, + DAC33_OUT_AMP_CTRL, 3, + dac33_lr_lom_texts); static const struct snd_kcontrol_new dac33_dapm_left_lom_control = SOC_DAPM_ENUM("Route", dac33_left_lom_enum); -static const struct soc_enum dac33_right_lom_enum = - SOC_ENUM_SINGLE(DAC33_OUT_AMP_CTRL, 2, - ARRAY_SIZE(dac33_lr_lom_texts), - dac33_lr_lom_texts); +static SOC_ENUM_SINGLE_DECL(dac33_right_lom_enum, + DAC33_OUT_AMP_CTRL, 2, + dac33_lr_lom_texts); static const struct snd_kcontrol_new dac33_dapm_right_lom_control = SOC_DAPM_ENUM("Route", dac33_right_lom_enum); diff --git a/sound/soc/codecs/twl4030.c b/sound/soc/codecs/twl4030.c index 00665ada23e..975e0f760ac 100644 --- a/sound/soc/codecs/twl4030.c +++ b/sound/soc/codecs/twl4030.c @@ -415,10 +415,9 @@ static const struct snd_kcontrol_new twl4030_dapm_carkitr_controls[] = { static const char *twl4030_handsfreel_texts[] = {"Voice", "AudioL1", "AudioL2", "AudioR2"}; -static const struct soc_enum twl4030_handsfreel_enum = - SOC_ENUM_SINGLE(TWL4030_REG_HFL_CTL, 0, - ARRAY_SIZE(twl4030_handsfreel_texts), - twl4030_handsfreel_texts); +static SOC_ENUM_SINGLE_DECL(twl4030_handsfreel_enum, + TWL4030_REG_HFL_CTL, 0, + twl4030_handsfreel_texts); static const struct snd_kcontrol_new twl4030_dapm_handsfreel_control = SOC_DAPM_ENUM("Route", twl4030_handsfreel_enum); @@ -431,10 +430,9 @@ static const struct snd_kcontrol_new twl4030_dapm_handsfreelmute_control = static const char *twl4030_handsfreer_texts[] = {"Voice", "AudioR1", "AudioR2", "AudioL2"}; -static const struct soc_enum twl4030_handsfreer_enum = - SOC_ENUM_SINGLE(TWL4030_REG_HFR_CTL, 0, - ARRAY_SIZE(twl4030_handsfreer_texts), - twl4030_handsfreer_texts); +static SOC_ENUM_SINGLE_DECL(twl4030_handsfreer_enum, + TWL4030_REG_HFR_CTL, 0, + twl4030_handsfreer_texts); static const struct snd_kcontrol_new twl4030_dapm_handsfreer_control = SOC_DAPM_ENUM("Route", twl4030_handsfreer_enum); @@ -448,10 +446,9 @@ static const struct snd_kcontrol_new twl4030_dapm_handsfreermute_control = static const char *twl4030_vibra_texts[] = {"AudioL1", "AudioR1", "AudioL2", "AudioR2"}; -static const struct soc_enum twl4030_vibra_enum = - SOC_ENUM_SINGLE(TWL4030_REG_VIBRA_CTL, 2, - ARRAY_SIZE(twl4030_vibra_texts), - twl4030_vibra_texts); +static SOC_ENUM_SINGLE_DECL(twl4030_vibra_enum, + TWL4030_REG_VIBRA_CTL, 2, + twl4030_vibra_texts); static const struct snd_kcontrol_new twl4030_dapm_vibra_control = SOC_DAPM_ENUM("Route", twl4030_vibra_enum); @@ -460,10 +457,9 @@ SOC_DAPM_ENUM("Route", twl4030_vibra_enum); static const char *twl4030_vibrapath_texts[] = {"Local vibrator", "Audio"}; -static const struct soc_enum twl4030_vibrapath_enum = - SOC_ENUM_SINGLE(TWL4030_REG_VIBRA_CTL, 4, - ARRAY_SIZE(twl4030_vibrapath_texts), - twl4030_vibrapath_texts); +static SOC_ENUM_SINGLE_DECL(twl4030_vibrapath_enum, + TWL4030_REG_VIBRA_CTL, 4, + twl4030_vibrapath_texts); static const struct snd_kcontrol_new twl4030_dapm_vibrapath_control = SOC_DAPM_ENUM("Route", twl4030_vibrapath_enum); @@ -490,10 +486,9 @@ static const struct snd_kcontrol_new twl4030_dapm_analogrmic_controls[] = { static const char *twl4030_micpathtx1_texts[] = {"Analog", "Digimic0"}; -static const struct soc_enum twl4030_micpathtx1_enum = - SOC_ENUM_SINGLE(TWL4030_REG_ADCMICSEL, 0, - ARRAY_SIZE(twl4030_micpathtx1_texts), - twl4030_micpathtx1_texts); +static SOC_ENUM_SINGLE_DECL(twl4030_micpathtx1_enum, + TWL4030_REG_ADCMICSEL, 0, + twl4030_micpathtx1_texts); static const struct snd_kcontrol_new twl4030_dapm_micpathtx1_control = SOC_DAPM_ENUM("Route", twl4030_micpathtx1_enum); @@ -502,10 +497,9 @@ SOC_DAPM_ENUM("Route", twl4030_micpathtx1_enum); static const char *twl4030_micpathtx2_texts[] = {"Analog", "Digimic1"}; -static const struct soc_enum twl4030_micpathtx2_enum = - SOC_ENUM_SINGLE(TWL4030_REG_ADCMICSEL, 2, - ARRAY_SIZE(twl4030_micpathtx2_texts), - twl4030_micpathtx2_texts); +static SOC_ENUM_SINGLE_DECL(twl4030_micpathtx2_enum, + TWL4030_REG_ADCMICSEL, 2, + twl4030_micpathtx2_texts); static const struct snd_kcontrol_new twl4030_dapm_micpathtx2_control = SOC_DAPM_ENUM("Route", twl4030_micpathtx2_enum); @@ -955,19 +949,15 @@ static const char *twl4030_op_modes_texts[] = { "Option 2 (voice/audio)", "Option 1 (audio)" }; -static const struct soc_enum twl4030_op_modes_enum = - SOC_ENUM_SINGLE(TWL4030_REG_CODEC_MODE, 0, - ARRAY_SIZE(twl4030_op_modes_texts), - twl4030_op_modes_texts); +static SOC_ENUM_SINGLE_DECL(twl4030_op_modes_enum, + TWL4030_REG_CODEC_MODE, 0, + twl4030_op_modes_texts); static int snd_soc_put_twl4030_opmode_enum_double(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); struct twl4030_priv *twl4030 = snd_soc_codec_get_drvdata(codec); - struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; - unsigned short val; - unsigned short mask; if (twl4030->configured) { dev_err(codec->dev, @@ -975,19 +965,7 @@ static int snd_soc_put_twl4030_opmode_enum_double(struct snd_kcontrol *kcontrol, return -EBUSY; } - if (ucontrol->value.enumerated.item[0] > e->max - 1) - return -EINVAL; - - val = ucontrol->value.enumerated.item[0] << e->shift_l; - mask = e->mask << e->shift_l; - if (e->shift_l != e->shift_r) { - if (ucontrol->value.enumerated.item[1] > e->max - 1) - return -EINVAL; - val |= ucontrol->value.enumerated.item[1] << e->shift_r; - mask |= e->mask << e->shift_r; - } - - return snd_soc_update_bits(codec, e->reg, mask, val); + return snd_soc_put_enum_double(kcontrol, ucontrol); } /* @@ -1044,10 +1022,9 @@ static const char *twl4030_avadc_clk_priority_texts[] = { "Voice high priority", "HiFi high priority" }; -static const struct soc_enum twl4030_avadc_clk_priority_enum = - SOC_ENUM_SINGLE(TWL4030_REG_AVADC_CTL, 2, - ARRAY_SIZE(twl4030_avadc_clk_priority_texts), - twl4030_avadc_clk_priority_texts); +static SOC_ENUM_SINGLE_DECL(twl4030_avadc_clk_priority_enum, + TWL4030_REG_AVADC_CTL, 2, + twl4030_avadc_clk_priority_texts); static const char *twl4030_rampdelay_texts[] = { "27/20/14 ms", "55/40/27 ms", "109/81/55 ms", "218/161/109 ms", @@ -1055,40 +1032,36 @@ static const char *twl4030_rampdelay_texts[] = { "3495/2581/1748 ms" }; -static const struct soc_enum twl4030_rampdelay_enum = - SOC_ENUM_SINGLE(TWL4030_REG_HS_POPN_SET, 2, - ARRAY_SIZE(twl4030_rampdelay_texts), - twl4030_rampdelay_texts); +static SOC_ENUM_SINGLE_DECL(twl4030_rampdelay_enum, + TWL4030_REG_HS_POPN_SET, 2, + twl4030_rampdelay_texts); /* Vibra H-bridge direction mode */ static const char *twl4030_vibradirmode_texts[] = { "Vibra H-bridge direction", "Audio data MSB", }; -static const struct soc_enum twl4030_vibradirmode_enum = - SOC_ENUM_SINGLE(TWL4030_REG_VIBRA_CTL, 5, - ARRAY_SIZE(twl4030_vibradirmode_texts), - twl4030_vibradirmode_texts); +static SOC_ENUM_SINGLE_DECL(twl4030_vibradirmode_enum, + TWL4030_REG_VIBRA_CTL, 5, + twl4030_vibradirmode_texts); /* Vibra H-bridge direction */ static const char *twl4030_vibradir_texts[] = { "Positive polarity", "Negative polarity", }; -static const struct soc_enum twl4030_vibradir_enum = - SOC_ENUM_SINGLE(TWL4030_REG_VIBRA_CTL, 1, - ARRAY_SIZE(twl4030_vibradir_texts), - twl4030_vibradir_texts); +static SOC_ENUM_SINGLE_DECL(twl4030_vibradir_enum, + TWL4030_REG_VIBRA_CTL, 1, + twl4030_vibradir_texts); /* Digimic Left and right swapping */ static const char *twl4030_digimicswap_texts[] = { "Not swapped", "Swapped", }; -static const struct soc_enum twl4030_digimicswap_enum = - SOC_ENUM_SINGLE(TWL4030_REG_MISC_SET_1, 0, - ARRAY_SIZE(twl4030_digimicswap_texts), - twl4030_digimicswap_texts); +static SOC_ENUM_SINGLE_DECL(twl4030_digimicswap_enum, + TWL4030_REG_MISC_SET_1, 0, + twl4030_digimicswap_texts); static const struct snd_kcontrol_new twl4030_snd_controls[] = { /* Codec operation mode control */ diff --git a/sound/soc/codecs/twl6040.c b/sound/soc/codecs/twl6040.c index 0afe8bef676..bd3a20647fd 100644 --- a/sound/soc/codecs/twl6040.c +++ b/sound/soc/codecs/twl6040.c @@ -81,7 +81,7 @@ struct twl6040_data { }; /* set of rates for each pll: low-power and high-performance */ -static unsigned int lp_rates[] = { +static const unsigned int lp_rates[] = { 8000, 11250, 16000, @@ -93,7 +93,7 @@ static unsigned int lp_rates[] = { 96000, }; -static unsigned int hp_rates[] = { +static const unsigned int hp_rates[] = { 8000, 16000, 32000, @@ -101,7 +101,7 @@ static unsigned int hp_rates[] = { 96000, }; -static struct snd_pcm_hw_constraint_list sysclk_constraints[] = { +static const struct snd_pcm_hw_constraint_list sysclk_constraints[] = { { .count = ARRAY_SIZE(lp_rates), .list = lp_rates, }, { .count = ARRAY_SIZE(hp_rates), .list = hp_rates, }, }; @@ -392,8 +392,10 @@ static const char *twl6040_amicr_texts[] = {"Headset Mic", "Sub Mic", "Aux/FM Right", "Off"}; static const struct soc_enum twl6040_enum[] = { - SOC_ENUM_SINGLE(TWL6040_REG_MICLCTL, 3, 4, twl6040_amicl_texts), - SOC_ENUM_SINGLE(TWL6040_REG_MICRCTL, 3, 4, twl6040_amicr_texts), + SOC_ENUM_SINGLE(TWL6040_REG_MICLCTL, 3, + ARRAY_SIZE(twl6040_amicl_texts), twl6040_amicl_texts), + SOC_ENUM_SINGLE(TWL6040_REG_MICRCTL, 3, + ARRAY_SIZE(twl6040_amicr_texts), twl6040_amicr_texts), }; static const char *twl6040_hs_texts[] = { @@ -476,9 +478,8 @@ static const char *twl6040_power_mode_texts[] = { "Low-Power", "High-Performance", }; -static const struct soc_enum twl6040_power_mode_enum = - SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(twl6040_power_mode_texts), - twl6040_power_mode_texts); +static SOC_ENUM_SINGLE_EXT_DECL(twl6040_power_mode_enum, + twl6040_power_mode_texts); static int twl6040_headset_power_get_enum(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) diff --git a/sound/soc/codecs/uda134x.c b/sound/soc/codecs/uda134x.c index c94d4c1e3da..edf27acc1d7 100644 --- a/sound/soc/codecs/uda134x.c +++ b/sound/soc/codecs/uda134x.c @@ -203,8 +203,7 @@ static int uda134x_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params, struct snd_soc_dai *dai) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_codec *codec = rtd->codec; + struct snd_soc_codec *codec = dai->codec; struct uda134x_priv *uda134x = snd_soc_codec_get_drvdata(codec); u8 hw_params; diff --git a/sound/soc/codecs/uda1380.c b/sound/soc/codecs/uda1380.c index 726df6d43c2..e62e70781ec 100644 --- a/sound/soc/codecs/uda1380.c +++ b/sound/soc/codecs/uda1380.c @@ -108,7 +108,7 @@ static int uda1380_write(struct snd_soc_codec *codec, unsigned int reg, /* the interpolator & decimator regs must only be written when the * codec DAI is active. */ - if (!codec->active && (reg >= UDA1380_MVOL)) + if (!snd_soc_codec_is_active(codec) && (reg >= UDA1380_MVOL)) return 0; pr_debug("uda1380: hw write %x val %x\n", reg, value); if (codec->hw_write(codec->control_data, data, 3) == 3) { @@ -237,25 +237,27 @@ static const char *uda1380_os_setting[] = { }; static const struct soc_enum uda1380_deemp_enum[] = { - SOC_ENUM_SINGLE(UDA1380_DEEMP, 8, 5, uda1380_deemp), - SOC_ENUM_SINGLE(UDA1380_DEEMP, 0, 5, uda1380_deemp), + SOC_ENUM_SINGLE(UDA1380_DEEMP, 8, ARRAY_SIZE(uda1380_deemp), + uda1380_deemp), + SOC_ENUM_SINGLE(UDA1380_DEEMP, 0, ARRAY_SIZE(uda1380_deemp), + uda1380_deemp), }; -static const struct soc_enum uda1380_input_sel_enum = - SOC_ENUM_SINGLE(UDA1380_ADC, 2, 4, uda1380_input_sel); /* SEL_MIC, SEL_LNA */ -static const struct soc_enum uda1380_output_sel_enum = - SOC_ENUM_SINGLE(UDA1380_PM, 7, 2, uda1380_output_sel); /* R02_EN_AVC */ -static const struct soc_enum uda1380_spf_enum = - SOC_ENUM_SINGLE(UDA1380_MODE, 14, 4, uda1380_spf_mode); /* M */ -static const struct soc_enum uda1380_capture_sel_enum = - SOC_ENUM_SINGLE(UDA1380_IFACE, 6, 2, uda1380_capture_sel); /* SEL_SOURCE */ -static const struct soc_enum uda1380_sel_ns_enum = - SOC_ENUM_SINGLE(UDA1380_MIXER, 14, 2, uda1380_sel_ns); /* SEL_NS */ -static const struct soc_enum uda1380_mix_enum = - SOC_ENUM_SINGLE(UDA1380_MIXER, 12, 4, uda1380_mix_control); /* MIX, MIX_POS */ -static const struct soc_enum uda1380_sdet_enum = - SOC_ENUM_SINGLE(UDA1380_MIXER, 4, 4, uda1380_sdet_setting); /* SD_VALUE */ -static const struct soc_enum uda1380_os_enum = - SOC_ENUM_SINGLE(UDA1380_MIXER, 0, 3, uda1380_os_setting); /* OS */ +static SOC_ENUM_SINGLE_DECL(uda1380_input_sel_enum, + UDA1380_ADC, 2, uda1380_input_sel); /* SEL_MIC, SEL_LNA */ +static SOC_ENUM_SINGLE_DECL(uda1380_output_sel_enum, + UDA1380_PM, 7, uda1380_output_sel); /* R02_EN_AVC */ +static SOC_ENUM_SINGLE_DECL(uda1380_spf_enum, + UDA1380_MODE, 14, uda1380_spf_mode); /* M */ +static SOC_ENUM_SINGLE_DECL(uda1380_capture_sel_enum, + UDA1380_IFACE, 6, uda1380_capture_sel); /* SEL_SOURCE */ +static SOC_ENUM_SINGLE_DECL(uda1380_sel_ns_enum, + UDA1380_MIXER, 14, uda1380_sel_ns); /* SEL_NS */ +static SOC_ENUM_SINGLE_DECL(uda1380_mix_enum, + UDA1380_MIXER, 12, uda1380_mix_control); /* MIX, MIX_POS */ +static SOC_ENUM_SINGLE_DECL(uda1380_sdet_enum, + UDA1380_MIXER, 4, uda1380_sdet_setting); /* SD_VALUE */ +static SOC_ENUM_SINGLE_DECL(uda1380_os_enum, + UDA1380_MIXER, 0, uda1380_os_setting); /* OS */ /* * from -48 dB in 1.5 dB steps (mute instead of -49.5 dB) @@ -564,8 +566,7 @@ static int uda1380_pcm_hw_params(struct snd_pcm_substream *substream, static void uda1380_pcm_shutdown(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_codec *codec = rtd->codec; + struct snd_soc_codec *codec = dai->codec; u16 clk = uda1380_read_reg_cache(codec, UDA1380_CLK); /* shut down WSPLL power if running from this clock */ diff --git a/sound/soc/codecs/wl1273.c b/sound/soc/codecs/wl1273.c index b7ab2ef567c..6be5f80b65f 100644 --- a/sound/soc/codecs/wl1273.c +++ b/sound/soc/codecs/wl1273.c @@ -197,7 +197,7 @@ static int snd_wl1273_set_audio_route(struct snd_kcontrol *kcontrol, return 0; /* Do not allow changes while stream is running */ - if (codec->active) + if (snd_soc_codec_is_active(codec)) return -EPERM; if (ucontrol->value.integer.value[0] < 0 || @@ -209,8 +209,7 @@ static int snd_wl1273_set_audio_route(struct snd_kcontrol *kcontrol, return 1; } -static const struct soc_enum wl1273_enum = - SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(wl1273_audio_route), wl1273_audio_route); +static SOC_ENUM_SINGLE_EXT_DECL(wl1273_enum, wl1273_audio_route); static int snd_wl1273_fm_audio_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) @@ -247,9 +246,7 @@ static int snd_wl1273_fm_audio_put(struct snd_kcontrol *kcontrol, static const char * const wl1273_audio_strings[] = { "Digital", "Analog" }; -static const struct soc_enum wl1273_audio_enum = - SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(wl1273_audio_strings), - wl1273_audio_strings); +static SOC_ENUM_SINGLE_EXT_DECL(wl1273_audio_enum, wl1273_audio_strings); static int snd_wl1273_fm_volume_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) diff --git a/sound/soc/codecs/wm2000.c b/sound/soc/codecs/wm2000.c index 8ae50274ea8..83a2c872925 100644 --- a/sound/soc/codecs/wm2000.c +++ b/sound/soc/codecs/wm2000.c @@ -786,8 +786,6 @@ static int wm2000_probe(struct snd_soc_codec *codec) { struct wm2000_priv *wm2000 = dev_get_drvdata(codec->dev); - snd_soc_codec_set_cache_io(codec, 16, 8, SND_SOC_REGMAP); - /* This will trigger a transition to standby mode by default */ wm2000_anc_set_mode(wm2000); diff --git a/sound/soc/codecs/wm2200.c b/sound/soc/codecs/wm2200.c index 57ba315d0c8..2e721e06671 100644 --- a/sound/soc/codecs/wm2200.c +++ b/sound/soc/codecs/wm2200.c @@ -1113,11 +1113,10 @@ static const char *wm2200_rxanc_input_sel_texts[] = { "None", "IN1", "IN2", "IN3", }; -static const struct soc_enum wm2200_rxanc_input_sel = - SOC_ENUM_SINGLE(WM2200_RXANC_SRC, - WM2200_IN_RXANC_SEL_SHIFT, - ARRAY_SIZE(wm2200_rxanc_input_sel_texts), - wm2200_rxanc_input_sel_texts); +static SOC_ENUM_SINGLE_DECL(wm2200_rxanc_input_sel, + WM2200_RXANC_SRC, + WM2200_IN_RXANC_SEL_SHIFT, + wm2200_rxanc_input_sel_texts); static const struct snd_kcontrol_new wm2200_snd_controls[] = { SOC_SINGLE("IN1 High Performance Switch", WM2200_IN1L_CONTROL, @@ -1288,11 +1287,10 @@ static const char *wm2200_aec_loopback_texts[] = { "OUT1L", "OUT1R", "OUT2L", "OUT2R", }; -static const struct soc_enum wm2200_aec_loopback = - SOC_ENUM_SINGLE(WM2200_DAC_AEC_CONTROL_1, - WM2200_AEC_LOOPBACK_SRC_SHIFT, - ARRAY_SIZE(wm2200_aec_loopback_texts), - wm2200_aec_loopback_texts); +static SOC_ENUM_SINGLE_DECL(wm2200_aec_loopback, + WM2200_DAC_AEC_CONTROL_1, + WM2200_AEC_LOOPBACK_SRC_SHIFT, + wm2200_aec_loopback_texts); static const struct snd_kcontrol_new wm2200_aec_loopback_mux = SOC_DAPM_ENUM("AEC Loopback", wm2200_aec_loopback); @@ -1556,15 +1554,8 @@ static int wm2200_probe(struct snd_soc_codec *codec) int ret; wm2200->codec = codec; - codec->control_data = wm2200->regmap; codec->dapm.bias_level = SND_SOC_BIAS_OFF; - ret = snd_soc_codec_set_cache_io(codec, 16, 16, SND_SOC_REGMAP); - if (ret != 0) { - dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); - return ret; - } - ret = snd_soc_add_codec_controls(codec, wm_adsp1_fw_controls, 2); if (ret != 0) return ret; diff --git a/sound/soc/codecs/wm5100.c b/sound/soc/codecs/wm5100.c index 4e3e31aaf50..eca983fad89 100644 --- a/sound/soc/codecs/wm5100.c +++ b/sound/soc/codecs/wm5100.c @@ -506,21 +506,21 @@ static const char *wm5100_lhpf_mode_text[] = { "Low-pass", "High-pass" }; -static const struct soc_enum wm5100_lhpf1_mode = - SOC_ENUM_SINGLE(WM5100_HPLPF1_1, WM5100_LHPF1_MODE_SHIFT, 2, - wm5100_lhpf_mode_text); +static SOC_ENUM_SINGLE_DECL(wm5100_lhpf1_mode, + WM5100_HPLPF1_1, WM5100_LHPF1_MODE_SHIFT, + wm5100_lhpf_mode_text); -static const struct soc_enum wm5100_lhpf2_mode = - SOC_ENUM_SINGLE(WM5100_HPLPF2_1, WM5100_LHPF2_MODE_SHIFT, 2, - wm5100_lhpf_mode_text); +static SOC_ENUM_SINGLE_DECL(wm5100_lhpf2_mode, + WM5100_HPLPF2_1, WM5100_LHPF2_MODE_SHIFT, + wm5100_lhpf_mode_text); -static const struct soc_enum wm5100_lhpf3_mode = - SOC_ENUM_SINGLE(WM5100_HPLPF3_1, WM5100_LHPF3_MODE_SHIFT, 2, - wm5100_lhpf_mode_text); +static SOC_ENUM_SINGLE_DECL(wm5100_lhpf3_mode, + WM5100_HPLPF3_1, WM5100_LHPF3_MODE_SHIFT, + wm5100_lhpf_mode_text); -static const struct soc_enum wm5100_lhpf4_mode = - SOC_ENUM_SINGLE(WM5100_HPLPF4_1, WM5100_LHPF4_MODE_SHIFT, 2, - wm5100_lhpf_mode_text); +static SOC_ENUM_SINGLE_DECL(wm5100_lhpf4_mode, + WM5100_HPLPF4_1, WM5100_LHPF4_MODE_SHIFT, + wm5100_lhpf_mode_text); static const struct snd_kcontrol_new wm5100_snd_controls[] = { SOC_SINGLE("IN1 High Performance Switch", WM5100_IN1L_CONTROL, @@ -2100,6 +2100,7 @@ static void wm5100_micd_irq(struct wm5100_priv *wm5100) int wm5100_detect(struct snd_soc_codec *codec, struct snd_soc_jack *jack) { struct wm5100_priv *wm5100 = snd_soc_codec_get_drvdata(codec); + struct snd_soc_dapm_context *dapm = &codec->dapm; if (jack) { wm5100->jack = jack; @@ -2117,9 +2118,14 @@ int wm5100_detect(struct snd_soc_codec *codec, struct snd_soc_jack *jack) WM5100_ACCDET_RATE_MASK); /* We need the charge pump to power MICBIAS */ - snd_soc_dapm_force_enable_pin(&codec->dapm, "CP2"); - snd_soc_dapm_force_enable_pin(&codec->dapm, "SYSCLK"); - snd_soc_dapm_sync(&codec->dapm); + snd_soc_dapm_mutex_lock(dapm); + + snd_soc_dapm_force_enable_pin_unlocked(dapm, "CP2"); + snd_soc_dapm_force_enable_pin_unlocked(dapm, "SYSCLK"); + + snd_soc_dapm_sync_unlocked(dapm); + + snd_soc_dapm_mutex_unlock(dapm); /* We start off just enabling microphone detection - even a * plain headphone will trigger detection. @@ -2337,13 +2343,6 @@ static int wm5100_probe(struct snd_soc_codec *codec) int ret, i; wm5100->codec = codec; - codec->control_data = wm5100->regmap; - - ret = snd_soc_codec_set_cache_io(codec, 16, 16, SND_SOC_REGMAP); - if (ret != 0) { - dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); - return ret; - } for (i = 0; i < ARRAY_SIZE(wm5100_dig_vu); i++) snd_soc_update_bits(codec, wm5100_dig_vu[i], WM5100_OUT_VU, diff --git a/sound/soc/codecs/wm5102.c b/sound/soc/codecs/wm5102.c index ce9c8e14d4b..dcf1d12cfef 100644 --- a/sound/soc/codecs/wm5102.c +++ b/sound/soc/codecs/wm5102.c @@ -582,7 +582,7 @@ static int wm5102_sysclk_ev(struct snd_soc_dapm_widget *w, { struct snd_soc_codec *codec = w->codec; struct arizona *arizona = dev_get_drvdata(codec->dev->parent); - struct regmap *regmap = codec->control_data; + struct regmap *regmap = arizona->regmap; const struct reg_default *patch = NULL; int i, patch_size; @@ -622,13 +622,16 @@ static const unsigned int wm5102_osr_val[] = { static const struct soc_enum wm5102_hpout_osr[] = { SOC_VALUE_ENUM_SINGLE(ARIZONA_OUTPUT_PATH_CONFIG_1L, - ARIZONA_OUT1_OSR_SHIFT, 0x7, 3, + ARIZONA_OUT1_OSR_SHIFT, 0x7, + ARRAY_SIZE(wm5102_osr_text), wm5102_osr_text, wm5102_osr_val), SOC_VALUE_ENUM_SINGLE(ARIZONA_OUTPUT_PATH_CONFIG_2L, - ARIZONA_OUT2_OSR_SHIFT, 0x7, 3, + ARIZONA_OUT2_OSR_SHIFT, 0x7, + ARRAY_SIZE(wm5102_osr_text), wm5102_osr_text, wm5102_osr_val), SOC_VALUE_ENUM_SINGLE(ARIZONA_OUTPUT_PATH_CONFIG_3L, - ARIZONA_OUT3_OSR_SHIFT, 0x7, 3, + ARIZONA_OUT3_OSR_SHIFT, 0x7, + ARRAY_SIZE(wm5102_osr_text), wm5102_osr_text, wm5102_osr_val), }; @@ -685,15 +688,8 @@ ARIZONA_MIXER_CONTROLS("EQ2", ARIZONA_EQ2MIX_INPUT_1_SOURCE), ARIZONA_MIXER_CONTROLS("EQ3", ARIZONA_EQ3MIX_INPUT_1_SOURCE), ARIZONA_MIXER_CONTROLS("EQ4", ARIZONA_EQ4MIX_INPUT_1_SOURCE), -SND_SOC_BYTES_MASK("EQ1 Coefficients", ARIZONA_EQ1_1, 21, - ARIZONA_EQ1_ENA_MASK), -SND_SOC_BYTES_MASK("EQ2 Coefficients", ARIZONA_EQ2_1, 21, - ARIZONA_EQ2_ENA_MASK), -SND_SOC_BYTES_MASK("EQ3 Coefficients", ARIZONA_EQ3_1, 21, - ARIZONA_EQ3_ENA_MASK), -SND_SOC_BYTES_MASK("EQ4 Coefficients", ARIZONA_EQ4_1, 21, - ARIZONA_EQ4_ENA_MASK), - +SND_SOC_BYTES("EQ1 Coefficients", ARIZONA_EQ1_3, 19), +SOC_SINGLE("EQ1 Mode Switch", ARIZONA_EQ1_2, ARIZONA_EQ1_B1_MODE, 1, 0), SOC_SINGLE_TLV("EQ1 B1 Volume", ARIZONA_EQ1_1, ARIZONA_EQ1_B1_GAIN_SHIFT, 24, 0, eq_tlv), SOC_SINGLE_TLV("EQ1 B2 Volume", ARIZONA_EQ1_1, ARIZONA_EQ1_B2_GAIN_SHIFT, @@ -705,6 +701,8 @@ SOC_SINGLE_TLV("EQ1 B4 Volume", ARIZONA_EQ1_2, ARIZONA_EQ1_B4_GAIN_SHIFT, SOC_SINGLE_TLV("EQ1 B5 Volume", ARIZONA_EQ1_2, ARIZONA_EQ1_B5_GAIN_SHIFT, 24, 0, eq_tlv), +SND_SOC_BYTES("EQ2 Coefficients", ARIZONA_EQ2_3, 19), +SOC_SINGLE("EQ2 Mode Switch", ARIZONA_EQ2_2, ARIZONA_EQ2_B1_MODE, 1, 0), SOC_SINGLE_TLV("EQ2 B1 Volume", ARIZONA_EQ2_1, ARIZONA_EQ2_B1_GAIN_SHIFT, 24, 0, eq_tlv), SOC_SINGLE_TLV("EQ2 B2 Volume", ARIZONA_EQ2_1, ARIZONA_EQ2_B2_GAIN_SHIFT, @@ -716,6 +714,8 @@ SOC_SINGLE_TLV("EQ2 B4 Volume", ARIZONA_EQ2_2, ARIZONA_EQ2_B4_GAIN_SHIFT, SOC_SINGLE_TLV("EQ2 B5 Volume", ARIZONA_EQ2_2, ARIZONA_EQ2_B5_GAIN_SHIFT, 24, 0, eq_tlv), +SND_SOC_BYTES("EQ3 Coefficients", ARIZONA_EQ3_3, 19), +SOC_SINGLE("EQ3 Mode Switch", ARIZONA_EQ3_2, ARIZONA_EQ3_B1_MODE, 1, 0), SOC_SINGLE_TLV("EQ3 B1 Volume", ARIZONA_EQ3_1, ARIZONA_EQ3_B1_GAIN_SHIFT, 24, 0, eq_tlv), SOC_SINGLE_TLV("EQ3 B2 Volume", ARIZONA_EQ3_1, ARIZONA_EQ3_B2_GAIN_SHIFT, @@ -727,6 +727,8 @@ SOC_SINGLE_TLV("EQ3 B4 Volume", ARIZONA_EQ3_2, ARIZONA_EQ3_B4_GAIN_SHIFT, SOC_SINGLE_TLV("EQ3 B5 Volume", ARIZONA_EQ3_2, ARIZONA_EQ3_B5_GAIN_SHIFT, 24, 0, eq_tlv), +SND_SOC_BYTES("EQ4 Coefficients", ARIZONA_EQ4_3, 19), +SOC_SINGLE("EQ4 Mode Switch", ARIZONA_EQ4_2, ARIZONA_EQ4_B1_MODE, 1, 0), SOC_SINGLE_TLV("EQ4 B1 Volume", ARIZONA_EQ4_1, ARIZONA_EQ4_B1_GAIN_SHIFT, 24, 0, eq_tlv), SOC_SINGLE_TLV("EQ4 B2 Volume", ARIZONA_EQ4_1, ARIZONA_EQ4_B2_GAIN_SHIFT, @@ -1758,9 +1760,7 @@ static int wm5102_codec_probe(struct snd_soc_codec *codec) struct wm5102_priv *priv = snd_soc_codec_get_drvdata(codec); int ret; - codec->control_data = priv->core.arizona->regmap; - - ret = snd_soc_codec_set_cache_io(codec, 32, 16, SND_SOC_REGMAP); + ret = snd_soc_codec_set_cache_io(codec, priv->core.arizona->regmap); if (ret != 0) return ret; diff --git a/sound/soc/codecs/wm5110.c b/sound/soc/codecs/wm5110.c index 2c3c962d9a8..df5a38dd832 100644 --- a/sound/soc/codecs/wm5110.c +++ b/sound/soc/codecs/wm5110.c @@ -136,7 +136,7 @@ static int wm5110_sysclk_ev(struct snd_soc_dapm_widget *w, { struct snd_soc_codec *codec = w->codec; struct arizona *arizona = dev_get_drvdata(codec->dev->parent); - struct regmap *regmap = codec->control_data; + struct regmap *regmap = arizona->regmap; const struct reg_default *patch = NULL; int i, patch_size; @@ -247,15 +247,8 @@ ARIZONA_MIXER_CONTROLS("EQ2", ARIZONA_EQ2MIX_INPUT_1_SOURCE), ARIZONA_MIXER_CONTROLS("EQ3", ARIZONA_EQ3MIX_INPUT_1_SOURCE), ARIZONA_MIXER_CONTROLS("EQ4", ARIZONA_EQ4MIX_INPUT_1_SOURCE), -SND_SOC_BYTES_MASK("EQ1 Coefficients", ARIZONA_EQ1_1, 21, - ARIZONA_EQ1_ENA_MASK), -SND_SOC_BYTES_MASK("EQ2 Coefficients", ARIZONA_EQ2_1, 21, - ARIZONA_EQ2_ENA_MASK), -SND_SOC_BYTES_MASK("EQ3 Coefficients", ARIZONA_EQ3_1, 21, - ARIZONA_EQ3_ENA_MASK), -SND_SOC_BYTES_MASK("EQ4 Coefficients", ARIZONA_EQ4_1, 21, - ARIZONA_EQ4_ENA_MASK), - +SND_SOC_BYTES("EQ1 Coefficients", ARIZONA_EQ1_3, 19), +SOC_SINGLE("EQ1 Mode Switch", ARIZONA_EQ1_2, ARIZONA_EQ1_B1_MODE, 1, 0), SOC_SINGLE_TLV("EQ1 B1 Volume", ARIZONA_EQ1_1, ARIZONA_EQ1_B1_GAIN_SHIFT, 24, 0, eq_tlv), SOC_SINGLE_TLV("EQ1 B2 Volume", ARIZONA_EQ1_1, ARIZONA_EQ1_B2_GAIN_SHIFT, @@ -267,6 +260,8 @@ SOC_SINGLE_TLV("EQ1 B4 Volume", ARIZONA_EQ1_2, ARIZONA_EQ1_B4_GAIN_SHIFT, SOC_SINGLE_TLV("EQ1 B5 Volume", ARIZONA_EQ1_2, ARIZONA_EQ1_B5_GAIN_SHIFT, 24, 0, eq_tlv), +SND_SOC_BYTES("EQ2 Coefficients", ARIZONA_EQ2_3, 19), +SOC_SINGLE("EQ2 Mode Switch", ARIZONA_EQ2_2, ARIZONA_EQ2_B1_MODE, 1, 0), SOC_SINGLE_TLV("EQ2 B1 Volume", ARIZONA_EQ2_1, ARIZONA_EQ2_B1_GAIN_SHIFT, 24, 0, eq_tlv), SOC_SINGLE_TLV("EQ2 B2 Volume", ARIZONA_EQ2_1, ARIZONA_EQ2_B2_GAIN_SHIFT, @@ -278,6 +273,8 @@ SOC_SINGLE_TLV("EQ2 B4 Volume", ARIZONA_EQ2_2, ARIZONA_EQ2_B4_GAIN_SHIFT, SOC_SINGLE_TLV("EQ2 B5 Volume", ARIZONA_EQ2_2, ARIZONA_EQ2_B5_GAIN_SHIFT, 24, 0, eq_tlv), +SND_SOC_BYTES("EQ3 Coefficients", ARIZONA_EQ3_3, 19), +SOC_SINGLE("EQ3 Mode Switch", ARIZONA_EQ3_2, ARIZONA_EQ3_B1_MODE, 1, 0), SOC_SINGLE_TLV("EQ3 B1 Volume", ARIZONA_EQ3_1, ARIZONA_EQ3_B1_GAIN_SHIFT, 24, 0, eq_tlv), SOC_SINGLE_TLV("EQ3 B2 Volume", ARIZONA_EQ3_1, ARIZONA_EQ3_B2_GAIN_SHIFT, @@ -289,6 +286,8 @@ SOC_SINGLE_TLV("EQ3 B4 Volume", ARIZONA_EQ3_2, ARIZONA_EQ3_B4_GAIN_SHIFT, SOC_SINGLE_TLV("EQ3 B5 Volume", ARIZONA_EQ3_2, ARIZONA_EQ3_B5_GAIN_SHIFT, 24, 0, eq_tlv), +SND_SOC_BYTES("EQ4 Coefficients", ARIZONA_EQ4_3, 19), +SOC_SINGLE("EQ4 Mode Switch", ARIZONA_EQ4_2, ARIZONA_EQ4_B1_MODE, 1, 0), SOC_SINGLE_TLV("EQ4 B1 Volume", ARIZONA_EQ4_1, ARIZONA_EQ4_B1_GAIN_SHIFT, 24, 0, eq_tlv), SOC_SINGLE_TLV("EQ4 B2 Volume", ARIZONA_EQ4_1, ARIZONA_EQ4_B2_GAIN_SHIFT, @@ -1588,10 +1587,9 @@ static int wm5110_codec_probe(struct snd_soc_codec *codec) struct wm5110_priv *priv = snd_soc_codec_get_drvdata(codec); int ret; - codec->control_data = priv->core.arizona->regmap; priv->core.arizona->dapm = &codec->dapm; - ret = snd_soc_codec_set_cache_io(codec, 32, 16, SND_SOC_REGMAP); + ret = snd_soc_codec_set_cache_io(codec, priv->core.arizona->regmap); if (ret != 0) return ret; diff --git a/sound/soc/codecs/wm8350.c b/sound/soc/codecs/wm8350.c index a183dcf3d5c..757256bf767 100644 --- a/sound/soc/codecs/wm8350.c +++ b/sound/soc/codecs/wm8350.c @@ -1505,9 +1505,7 @@ static int wm8350_codec_probe(struct snd_soc_codec *codec) if (ret != 0) return ret; - codec->control_data = wm8350->regmap; - - snd_soc_codec_set_cache_io(codec, 8, 16, SND_SOC_REGMAP); + snd_soc_codec_set_cache_io(codec, wm8350->regmap); /* Put the codec into reset if it wasn't already */ wm8350_clear_bits(wm8350, WM8350_POWER_MGMT_5, WM8350_CODEC_ENA); diff --git a/sound/soc/codecs/wm8400.c b/sound/soc/codecs/wm8400.c index 6d684d934f4..146564feaea 100644 --- a/sound/soc/codecs/wm8400.c +++ b/sound/soc/codecs/wm8400.c @@ -1316,10 +1316,9 @@ static int wm8400_codec_probe(struct snd_soc_codec *codec) snd_soc_codec_set_drvdata(codec, priv); priv->wm8400 = wm8400; - codec->control_data = wm8400->regmap; priv->codec = codec; - snd_soc_codec_set_cache_io(codec, 8, 16, SND_SOC_REGMAP); + snd_soc_codec_set_cache_io(codec, wm8400->regmap); ret = devm_regulator_bulk_get(wm8400->dev, ARRAY_SIZE(power), &power[0]); diff --git a/sound/soc/codecs/wm8510.c b/sound/soc/codecs/wm8510.c index 7df7d457275..1c1e328feeb 100644 --- a/sound/soc/codecs/wm8510.c +++ b/sound/soc/codecs/wm8510.c @@ -589,20 +589,12 @@ static int wm8510_resume(struct snd_soc_codec *codec) static int wm8510_probe(struct snd_soc_codec *codec) { - int ret; - - ret = snd_soc_codec_set_cache_io(codec, 7, 9, SND_SOC_REGMAP); - if (ret < 0) { - printk(KERN_ERR "wm8510: failed to set cache I/O: %d\n", ret); - return ret; - } - wm8510_reset(codec); /* power on device */ wm8510_set_bias_level(codec, SND_SOC_BIAS_STANDBY); - return ret; + return 0; } /* power down chip */ diff --git a/sound/soc/codecs/wm8523.c b/sound/soc/codecs/wm8523.c index 74d106dc766..601ee8178af 100644 --- a/sound/soc/codecs/wm8523.c +++ b/sound/soc/codecs/wm8523.c @@ -75,8 +75,8 @@ static const char *wm8523_zd_count_text[] = { "2048", }; -static const struct soc_enum wm8523_zc_count = - SOC_ENUM_SINGLE(WM8523_ZERO_DETECT, 0, 2, wm8523_zd_count_text); +static SOC_ENUM_SINGLE_DECL(wm8523_zc_count, WM8523_ZERO_DETECT, 0, + wm8523_zd_count_text); static const struct snd_kcontrol_new wm8523_controls[] = { SOC_DOUBLE_R_TLV("Playback Volume", WM8523_DAC_GAINL, WM8523_DAC_GAINR, @@ -392,18 +392,11 @@ static int wm8523_resume(struct snd_soc_codec *codec) static int wm8523_probe(struct snd_soc_codec *codec) { struct wm8523_priv *wm8523 = snd_soc_codec_get_drvdata(codec); - int ret; wm8523->rate_constraint.list = &wm8523->rate_constraint_list[0]; wm8523->rate_constraint.count = ARRAY_SIZE(wm8523->rate_constraint_list); - ret = snd_soc_codec_set_cache_io(codec, 8, 16, SND_SOC_REGMAP); - if (ret != 0) { - dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); - return ret; - } - /* Change some default settings - latch VU and enable ZC */ snd_soc_update_bits(codec, WM8523_DAC_GAINR, WM8523_DACR_VU, WM8523_DACR_VU); diff --git a/sound/soc/codecs/wm8580.c b/sound/soc/codecs/wm8580.c index 318989acbbe..af7ed8b5d4e 100644 --- a/sound/soc/codecs/wm8580.c +++ b/sound/soc/codecs/wm8580.c @@ -504,8 +504,7 @@ static int wm8580_paif_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params, struct snd_soc_dai *dai) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_codec *codec = rtd->codec; + struct snd_soc_codec *codec = dai->codec; struct wm8580_priv *wm8580 = snd_soc_codec_get_drvdata(codec); u16 paifa = 0; u16 paifb = 0; @@ -869,12 +868,6 @@ static int wm8580_probe(struct snd_soc_codec *codec) struct wm8580_priv *wm8580 = snd_soc_codec_get_drvdata(codec); int ret = 0; - ret = snd_soc_codec_set_cache_io(codec, 7, 9, SND_SOC_REGMAP); - if (ret < 0) { - dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); - return ret; - } - ret = regulator_bulk_enable(ARRAY_SIZE(wm8580->supplies), wm8580->supplies); if (ret != 0) { diff --git a/sound/soc/codecs/wm8711.c b/sound/soc/codecs/wm8711.c index d99f948c513..b0fbcb377ba 100644 --- a/sound/soc/codecs/wm8711.c +++ b/sound/soc/codecs/wm8711.c @@ -201,7 +201,7 @@ static void wm8711_shutdown(struct snd_pcm_substream *substream, struct snd_soc_codec *codec = dai->codec; /* deactivate */ - if (!codec->active) { + if (!snd_soc_codec_is_active(codec)) { udelay(50); snd_soc_write(codec, WM8711_ACTIVE, 0x0); } @@ -367,12 +367,6 @@ static int wm8711_probe(struct snd_soc_codec *codec) { int ret; - ret = snd_soc_codec_set_cache_io(codec, 7, 9, SND_SOC_REGMAP); - if (ret < 0) { - dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); - return ret; - } - ret = wm8711_reset(codec); if (ret < 0) { dev_err(codec->dev, "Failed to issue reset\n"); diff --git a/sound/soc/codecs/wm8728.c b/sound/soc/codecs/wm8728.c index cd89033e84c..bac7fc28fe7 100644 --- a/sound/soc/codecs/wm8728.c +++ b/sound/soc/codecs/wm8728.c @@ -228,19 +228,10 @@ static int wm8728_resume(struct snd_soc_codec *codec) static int wm8728_probe(struct snd_soc_codec *codec) { - int ret; - - ret = snd_soc_codec_set_cache_io(codec, 7, 9, SND_SOC_REGMAP); - if (ret < 0) { - printk(KERN_ERR "wm8728: failed to configure cache I/O: %d\n", - ret); - return ret; - } - /* power on device */ wm8728_set_bias_level(codec, SND_SOC_BIAS_STANDBY); - return ret; + return 0; } static int wm8728_remove(struct snd_soc_codec *codec) diff --git a/sound/soc/codecs/wm8731.c b/sound/soc/codecs/wm8731.c index 029720366ff..d74f43975b9 100644 --- a/sound/soc/codecs/wm8731.c +++ b/sound/soc/codecs/wm8731.c @@ -83,8 +83,8 @@ static bool wm8731_writeable(struct device *dev, unsigned int reg) static const char *wm8731_input_select[] = {"Line In", "Mic"}; -static const struct soc_enum wm8731_insel_enum = - SOC_ENUM_SINGLE(WM8731_APANA, 2, 2, wm8731_input_select); +static SOC_ENUM_SINGLE_DECL(wm8731_insel_enum, + WM8731_APANA, 2, wm8731_input_select); static int wm8731_deemph[] = { 0, 32000, 44100, 48000 }; @@ -583,13 +583,6 @@ static int wm8731_probe(struct snd_soc_codec *codec) struct wm8731_priv *wm8731 = snd_soc_codec_get_drvdata(codec); int ret = 0, i; - codec->control_data = wm8731->regmap; - ret = snd_soc_codec_set_cache_io(codec, 7, 9, SND_SOC_REGMAP); - if (ret < 0) { - dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); - return ret; - } - for (i = 0; i < ARRAY_SIZE(wm8731->supplies); i++) wm8731->supplies[i].supply = wm8731_supply_names[i]; diff --git a/sound/soc/codecs/wm8737.c b/sound/soc/codecs/wm8737.c index 2f167a8ca01..b27f26cdc04 100644 --- a/sound/soc/codecs/wm8737.c +++ b/sound/soc/codecs/wm8737.c @@ -99,29 +99,29 @@ static const char *micbias_enum_text[] = { "100%", }; -static const struct soc_enum micbias_enum = - SOC_ENUM_SINGLE(WM8737_MIC_PREAMP_CONTROL, 0, 4, micbias_enum_text); +static SOC_ENUM_SINGLE_DECL(micbias_enum, + WM8737_MIC_PREAMP_CONTROL, 0, micbias_enum_text); static const char *low_cutoff_text[] = { "Low", "High" }; -static const struct soc_enum low_3d = - SOC_ENUM_SINGLE(WM8737_3D_ENHANCE, 6, 2, low_cutoff_text); +static SOC_ENUM_SINGLE_DECL(low_3d, + WM8737_3D_ENHANCE, 6, low_cutoff_text); static const char *high_cutoff_text[] = { "High", "Low" }; -static const struct soc_enum high_3d = - SOC_ENUM_SINGLE(WM8737_3D_ENHANCE, 5, 2, high_cutoff_text); +static SOC_ENUM_SINGLE_DECL(high_3d, + WM8737_3D_ENHANCE, 5, high_cutoff_text); static const char *alc_fn_text[] = { "Disabled", "Right", "Left", "Stereo" }; -static const struct soc_enum alc_fn = - SOC_ENUM_SINGLE(WM8737_ALC1, 7, 4, alc_fn_text); +static SOC_ENUM_SINGLE_DECL(alc_fn, + WM8737_ALC1, 7, alc_fn_text); static const char *alc_hold_text[] = { "0", "2.67ms", "5.33ms", "10.66ms", "21.32ms", "42.64ms", "85.28ms", @@ -129,24 +129,24 @@ static const char *alc_hold_text[] = { "10.916s", "21.832s", "43.691s" }; -static const struct soc_enum alc_hold = - SOC_ENUM_SINGLE(WM8737_ALC2, 0, 16, alc_hold_text); +static SOC_ENUM_SINGLE_DECL(alc_hold, + WM8737_ALC2, 0, alc_hold_text); static const char *alc_atk_text[] = { "8.4ms", "16.8ms", "33.6ms", "67.2ms", "134.4ms", "268.8ms", "537.6ms", "1.075s", "2.15s", "4.3s", "8.6s" }; -static const struct soc_enum alc_atk = - SOC_ENUM_SINGLE(WM8737_ALC3, 0, 11, alc_atk_text); +static SOC_ENUM_SINGLE_DECL(alc_atk, + WM8737_ALC3, 0, alc_atk_text); static const char *alc_dcy_text[] = { "33.6ms", "67.2ms", "134.4ms", "268.8ms", "537.6ms", "1.075s", "2.15s", "4.3s", "8.6s", "17.2s", "34.41s" }; -static const struct soc_enum alc_dcy = - SOC_ENUM_SINGLE(WM8737_ALC3, 4, 11, alc_dcy_text); +static SOC_ENUM_SINGLE_DECL(alc_dcy, + WM8737_ALC3, 4, alc_dcy_text); static const struct snd_kcontrol_new wm8737_snd_controls[] = { SOC_DOUBLE_R_TLV("Mic Boost Volume", WM8737_AUDIO_PATH_L, WM8737_AUDIO_PATH_R, @@ -191,8 +191,8 @@ static const char *linsel_text[] = { "LINPUT1", "LINPUT2", "LINPUT3", "LINPUT1 DC", }; -static const struct soc_enum linsel_enum = - SOC_ENUM_SINGLE(WM8737_AUDIO_PATH_L, 7, 4, linsel_text); +static SOC_ENUM_SINGLE_DECL(linsel_enum, + WM8737_AUDIO_PATH_L, 7, linsel_text); static const struct snd_kcontrol_new linsel_mux = SOC_DAPM_ENUM("LINSEL", linsel_enum); @@ -202,8 +202,8 @@ static const char *rinsel_text[] = { "RINPUT1", "RINPUT2", "RINPUT3", "RINPUT1 DC", }; -static const struct soc_enum rinsel_enum = - SOC_ENUM_SINGLE(WM8737_AUDIO_PATH_R, 7, 4, rinsel_text); +static SOC_ENUM_SINGLE_DECL(rinsel_enum, + WM8737_AUDIO_PATH_R, 7, rinsel_text); static const struct snd_kcontrol_new rinsel_mux = SOC_DAPM_ENUM("RINSEL", rinsel_enum); @@ -212,15 +212,15 @@ static const char *bypass_text[] = { "Direct", "Preamp" }; -static const struct soc_enum lbypass_enum = - SOC_ENUM_SINGLE(WM8737_MIC_PREAMP_CONTROL, 2, 2, bypass_text); +static SOC_ENUM_SINGLE_DECL(lbypass_enum, + WM8737_MIC_PREAMP_CONTROL, 2, bypass_text); static const struct snd_kcontrol_new lbypass_mux = SOC_DAPM_ENUM("Left Bypass", lbypass_enum); -static const struct soc_enum rbypass_enum = - SOC_ENUM_SINGLE(WM8737_MIC_PREAMP_CONTROL, 3, 2, bypass_text); +static SOC_ENUM_SINGLE_DECL(rbypass_enum, + WM8737_MIC_PREAMP_CONTROL, 3, bypass_text); static const struct snd_kcontrol_new rbypass_mux = SOC_DAPM_ENUM("Left Bypass", rbypass_enum); @@ -570,12 +570,6 @@ static int wm8737_probe(struct snd_soc_codec *codec) struct wm8737_priv *wm8737 = snd_soc_codec_get_drvdata(codec); int ret; - ret = snd_soc_codec_set_cache_io(codec, 7, 9, SND_SOC_REGMAP); - if (ret != 0) { - dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); - return ret; - } - ret = regulator_bulk_enable(ARRAY_SIZE(wm8737->supplies), wm8737->supplies); if (ret != 0) { @@ -644,7 +638,7 @@ static const struct regmap_config wm8737_regmap = { .volatile_reg = wm8737_volatile, }; -#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) +#if IS_ENABLED(CONFIG_I2C) static int wm8737_i2c_probe(struct i2c_client *i2c, const struct i2c_device_id *id) { @@ -758,7 +752,7 @@ static struct spi_driver wm8737_spi_driver = { static int __init wm8737_modinit(void) { int ret; -#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) +#if IS_ENABLED(CONFIG_I2C) ret = i2c_add_driver(&wm8737_i2c_driver); if (ret != 0) { printk(KERN_ERR "Failed to register WM8737 I2C driver: %d\n", @@ -781,7 +775,7 @@ static void __exit wm8737_exit(void) #if defined(CONFIG_SPI_MASTER) spi_unregister_driver(&wm8737_spi_driver); #endif -#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) +#if IS_ENABLED(CONFIG_I2C) i2c_del_driver(&wm8737_i2c_driver); #endif } diff --git a/sound/soc/codecs/wm8741.c b/sound/soc/codecs/wm8741.c index 2895c8d3b5e..b33542a0460 100644 --- a/sound/soc/codecs/wm8741.c +++ b/sound/soc/codecs/wm8741.c @@ -44,7 +44,7 @@ struct wm8741_priv { struct regmap *regmap; struct regulator_bulk_data supplies[WM8741_NUM_SUPPLIES]; unsigned int sysclk; - struct snd_pcm_hw_constraint_list *sysclk_constraints; + const struct snd_pcm_hw_constraint_list *sysclk_constraints; }; static const struct reg_default wm8741_reg_defaults[] = { @@ -122,74 +122,74 @@ static struct { { 6, 768 }, }; -static unsigned int rates_11289[] = { +static const unsigned int rates_11289[] = { 44100, 88235, }; -static struct snd_pcm_hw_constraint_list constraints_11289 = { +static const struct snd_pcm_hw_constraint_list constraints_11289 = { .count = ARRAY_SIZE(rates_11289), .list = rates_11289, }; -static unsigned int rates_12288[] = { +static const unsigned int rates_12288[] = { 32000, 48000, 96000, }; -static struct snd_pcm_hw_constraint_list constraints_12288 = { +static const struct snd_pcm_hw_constraint_list constraints_12288 = { .count = ARRAY_SIZE(rates_12288), .list = rates_12288, }; -static unsigned int rates_16384[] = { +static const unsigned int rates_16384[] = { 32000, }; -static struct snd_pcm_hw_constraint_list constraints_16384 = { +static const struct snd_pcm_hw_constraint_list constraints_16384 = { .count = ARRAY_SIZE(rates_16384), .list = rates_16384, }; -static unsigned int rates_16934[] = { +static const unsigned int rates_16934[] = { 44100, 88235, }; -static struct snd_pcm_hw_constraint_list constraints_16934 = { +static const struct snd_pcm_hw_constraint_list constraints_16934 = { .count = ARRAY_SIZE(rates_16934), .list = rates_16934, }; -static unsigned int rates_18432[] = { +static const unsigned int rates_18432[] = { 48000, 96000, }; -static struct snd_pcm_hw_constraint_list constraints_18432 = { +static const struct snd_pcm_hw_constraint_list constraints_18432 = { .count = ARRAY_SIZE(rates_18432), .list = rates_18432, }; -static unsigned int rates_22579[] = { +static const unsigned int rates_22579[] = { 44100, 88235, 1764000 }; -static struct snd_pcm_hw_constraint_list constraints_22579 = { +static const struct snd_pcm_hw_constraint_list constraints_22579 = { .count = ARRAY_SIZE(rates_22579), .list = rates_22579, }; -static unsigned int rates_24576[] = { +static const unsigned int rates_24576[] = { 32000, 48000, 96000, 192000 }; -static struct snd_pcm_hw_constraint_list constraints_24576 = { +static const struct snd_pcm_hw_constraint_list constraints_24576 = { .count = ARRAY_SIZE(rates_24576), .list = rates_24576, }; -static unsigned int rates_36864[] = { +static const unsigned int rates_36864[] = { 48000, 96000, 19200 }; -static struct snd_pcm_hw_constraint_list constraints_36864 = { +static const struct snd_pcm_hw_constraint_list constraints_36864 = { .count = ARRAY_SIZE(rates_36864), .list = rates_36864, }; @@ -429,12 +429,6 @@ static int wm8741_probe(struct snd_soc_codec *codec) goto err_get; } - ret = snd_soc_codec_set_cache_io(codec, 7, 9, SND_SOC_REGMAP); - if (ret != 0) { - dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); - goto err_enable; - } - ret = wm8741_reset(codec); if (ret < 0) { dev_err(codec->dev, "Failed to issue reset\n"); diff --git a/sound/soc/codecs/wm8750.c b/sound/soc/codecs/wm8750.c index 78616a638a5..33990b63d21 100644 --- a/sound/soc/codecs/wm8750.c +++ b/sound/soc/codecs/wm8750.c @@ -702,12 +702,6 @@ static int wm8750_probe(struct snd_soc_codec *codec) { int ret; - ret = snd_soc_codec_set_cache_io(codec, 7, 9, SND_SOC_REGMAP); - if (ret < 0) { - printk(KERN_ERR "wm8750: failed to set cache I/O: %d\n", ret); - return ret; - } - ret = wm8750_reset(codec); if (ret < 0) { printk(KERN_ERR "wm8750: failed to reset: %d\n", ret); diff --git a/sound/soc/codecs/wm8753.c b/sound/soc/codecs/wm8753.c index be85da93a26..cbb8d55052a 100644 --- a/sound/soc/codecs/wm8753.c +++ b/sound/soc/codecs/wm8753.c @@ -251,7 +251,7 @@ static int wm8753_set_dai(struct snd_kcontrol *kcontrol, if (wm8753->dai_func == ucontrol->value.integer.value[0]) return 0; - if (codec->active) + if (snd_soc_codec_is_active(codec)) return -EBUSY; ioctl = snd_soc_read(codec, WM8753_IOCTL); @@ -1314,7 +1314,7 @@ static int wm8753_mute(struct snd_soc_dai *dai, int mute) /* the digital mute covers the HiFi and Voice DAC's on the WM8753. * make sure we check if they are not both active when we mute */ if (mute && wm8753->dai_func == 1) { - if (!codec->active) + if (!snd_soc_codec_is_active(codec)) snd_soc_write(codec, WM8753_DAC, mute_reg | 0x8); } else { if (mute) @@ -1440,7 +1440,6 @@ static void wm8753_work(struct work_struct *work) static int wm8753_suspend(struct snd_soc_codec *codec) { wm8753_set_bias_level(codec, SND_SOC_BIAS_OFF); - codec->cache_sync = 1; return 0; } @@ -1471,13 +1470,6 @@ static int wm8753_probe(struct snd_soc_codec *codec) INIT_DELAYED_WORK(&codec->dapm.delayed_work, wm8753_work); - codec->control_data = wm8753->regmap; - ret = snd_soc_codec_set_cache_io(codec, 7, 9, SND_SOC_REGMAP); - if (ret < 0) { - dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); - return ret; - } - ret = wm8753_reset(codec); if (ret < 0) { dev_err(codec->dev, "Failed to issue reset: %d\n", ret); diff --git a/sound/soc/codecs/wm8770.c b/sound/soc/codecs/wm8770.c index 5bce2101348..c61aeb38efb 100644 --- a/sound/soc/codecs/wm8770.c +++ b/sound/soc/codecs/wm8770.c @@ -580,12 +580,6 @@ static int wm8770_probe(struct snd_soc_codec *codec) wm8770 = snd_soc_codec_get_drvdata(codec); wm8770->codec = codec; - ret = snd_soc_codec_set_cache_io(codec, 7, 9, SND_SOC_REGMAP); - if (ret < 0) { - dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); - return ret; - } - ret = regulator_bulk_enable(ARRAY_SIZE(wm8770->supplies), wm8770->supplies); if (ret) { diff --git a/sound/soc/codecs/wm8776.c b/sound/soc/codecs/wm8776.c index ef824672523..70952ceb278 100644 --- a/sound/soc/codecs/wm8776.c +++ b/sound/soc/codecs/wm8776.c @@ -430,12 +430,6 @@ static int wm8776_probe(struct snd_soc_codec *codec) { int ret = 0; - ret = snd_soc_codec_set_cache_io(codec, 7, 9, SND_SOC_REGMAP); - if (ret < 0) { - dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); - return ret; - } - ret = wm8776_reset(codec); if (ret < 0) { dev_err(codec->dev, "Failed to issue reset: %d\n", ret); diff --git a/sound/soc/codecs/wm8804.c b/sound/soc/codecs/wm8804.c index 9bc8206a680..ee76f0fb429 100644 --- a/sound/soc/codecs/wm8804.c +++ b/sound/soc/codecs/wm8804.c @@ -92,7 +92,7 @@ WM8804_REGULATOR_EVENT(0) WM8804_REGULATOR_EVENT(1) static const char *txsrc_text[] = { "S/PDIF RX", "AIF" }; -static const SOC_ENUM_SINGLE_EXT_DECL(txsrc, txsrc_text); +static SOC_ENUM_SINGLE_EXT_DECL(txsrc, txsrc_text); static const struct snd_kcontrol_new wm8804_snd_controls[] = { SOC_ENUM_EXT("Input Source", txsrc, txsrc_get, txsrc_put), @@ -546,14 +546,6 @@ static int wm8804_probe(struct snd_soc_codec *codec) wm8804 = snd_soc_codec_get_drvdata(codec); - codec->control_data = wm8804->regmap; - - ret = snd_soc_codec_set_cache_io(codec, 8, 8, SND_SOC_REGMAP); - if (ret < 0) { - dev_err(codec->dev, "Failed to set cache i/o: %d\n", ret); - return ret; - } - for (i = 0; i < ARRAY_SIZE(wm8804->supplies); i++) wm8804->supplies[i].supply = wm8804_supply_names[i]; diff --git a/sound/soc/codecs/wm8900.c b/sound/soc/codecs/wm8900.c index 43c2201cb90..d09fdce57f5 100644 --- a/sound/soc/codecs/wm8900.c +++ b/sound/soc/codecs/wm8900.c @@ -1178,13 +1178,7 @@ static int wm8900_resume(struct snd_soc_codec *codec) static int wm8900_probe(struct snd_soc_codec *codec) { - int ret = 0, reg; - - ret = snd_soc_codec_set_cache_io(codec, 8, 16, SND_SOC_REGMAP); - if (ret != 0) { - dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); - return ret; - } + int reg; reg = snd_soc_read(codec, WM8900_REG_ID); if (reg != 0x8900) { diff --git a/sound/soc/codecs/wm8903.c b/sound/soc/codecs/wm8903.c index eebcb1da3b7..b0084a127d1 100644 --- a/sound/soc/codecs/wm8903.c +++ b/sound/soc/codecs/wm8903.c @@ -489,28 +489,28 @@ static const char *hpf_mode_text[] = { "Hi-fi", "Voice 1", "Voice 2", "Voice 3" }; -static const struct soc_enum hpf_mode = - SOC_ENUM_SINGLE(WM8903_ADC_DIGITAL_0, 5, 4, hpf_mode_text); +static SOC_ENUM_SINGLE_DECL(hpf_mode, + WM8903_ADC_DIGITAL_0, 5, hpf_mode_text); static const char *osr_text[] = { "Low power", "High performance" }; -static const struct soc_enum adc_osr = - SOC_ENUM_SINGLE(WM8903_ANALOGUE_ADC_0, 0, 2, osr_text); +static SOC_ENUM_SINGLE_DECL(adc_osr, + WM8903_ANALOGUE_ADC_0, 0, osr_text); -static const struct soc_enum dac_osr = - SOC_ENUM_SINGLE(WM8903_DAC_DIGITAL_1, 0, 2, osr_text); +static SOC_ENUM_SINGLE_DECL(dac_osr, + WM8903_DAC_DIGITAL_1, 0, osr_text); static const char *drc_slope_text[] = { "1", "1/2", "1/4", "1/8", "1/16", "0" }; -static const struct soc_enum drc_slope_r0 = - SOC_ENUM_SINGLE(WM8903_DRC_2, 3, 6, drc_slope_text); +static SOC_ENUM_SINGLE_DECL(drc_slope_r0, + WM8903_DRC_2, 3, drc_slope_text); -static const struct soc_enum drc_slope_r1 = - SOC_ENUM_SINGLE(WM8903_DRC_2, 0, 6, drc_slope_text); +static SOC_ENUM_SINGLE_DECL(drc_slope_r1, + WM8903_DRC_2, 0, drc_slope_text); static const char *drc_attack_text[] = { "instantaneous", @@ -518,125 +518,125 @@ static const char *drc_attack_text[] = { "46.4ms", "92.8ms", "185.6ms" }; -static const struct soc_enum drc_attack = - SOC_ENUM_SINGLE(WM8903_DRC_1, 12, 11, drc_attack_text); +static SOC_ENUM_SINGLE_DECL(drc_attack, + WM8903_DRC_1, 12, drc_attack_text); static const char *drc_decay_text[] = { "186ms", "372ms", "743ms", "1.49s", "2.97s", "5.94s", "11.89s", "23.87s", "47.56s" }; -static const struct soc_enum drc_decay = - SOC_ENUM_SINGLE(WM8903_DRC_1, 8, 9, drc_decay_text); +static SOC_ENUM_SINGLE_DECL(drc_decay, + WM8903_DRC_1, 8, drc_decay_text); static const char *drc_ff_delay_text[] = { "5 samples", "9 samples" }; -static const struct soc_enum drc_ff_delay = - SOC_ENUM_SINGLE(WM8903_DRC_0, 5, 2, drc_ff_delay_text); +static SOC_ENUM_SINGLE_DECL(drc_ff_delay, + WM8903_DRC_0, 5, drc_ff_delay_text); static const char *drc_qr_decay_text[] = { "0.725ms", "1.45ms", "5.8ms" }; -static const struct soc_enum drc_qr_decay = - SOC_ENUM_SINGLE(WM8903_DRC_1, 4, 3, drc_qr_decay_text); +static SOC_ENUM_SINGLE_DECL(drc_qr_decay, + WM8903_DRC_1, 4, drc_qr_decay_text); static const char *drc_smoothing_text[] = { "Low", "Medium", "High" }; -static const struct soc_enum drc_smoothing = - SOC_ENUM_SINGLE(WM8903_DRC_0, 11, 3, drc_smoothing_text); +static SOC_ENUM_SINGLE_DECL(drc_smoothing, + WM8903_DRC_0, 11, drc_smoothing_text); static const char *soft_mute_text[] = { "Fast (fs/2)", "Slow (fs/32)" }; -static const struct soc_enum soft_mute = - SOC_ENUM_SINGLE(WM8903_DAC_DIGITAL_1, 10, 2, soft_mute_text); +static SOC_ENUM_SINGLE_DECL(soft_mute, + WM8903_DAC_DIGITAL_1, 10, soft_mute_text); static const char *mute_mode_text[] = { "Hard", "Soft" }; -static const struct soc_enum mute_mode = - SOC_ENUM_SINGLE(WM8903_DAC_DIGITAL_1, 9, 2, mute_mode_text); +static SOC_ENUM_SINGLE_DECL(mute_mode, + WM8903_DAC_DIGITAL_1, 9, mute_mode_text); static const char *companding_text[] = { "ulaw", "alaw" }; -static const struct soc_enum dac_companding = - SOC_ENUM_SINGLE(WM8903_AUDIO_INTERFACE_0, 0, 2, companding_text); +static SOC_ENUM_SINGLE_DECL(dac_companding, + WM8903_AUDIO_INTERFACE_0, 0, companding_text); -static const struct soc_enum adc_companding = - SOC_ENUM_SINGLE(WM8903_AUDIO_INTERFACE_0, 2, 2, companding_text); +static SOC_ENUM_SINGLE_DECL(adc_companding, + WM8903_AUDIO_INTERFACE_0, 2, companding_text); static const char *input_mode_text[] = { "Single-Ended", "Differential Line", "Differential Mic" }; -static const struct soc_enum linput_mode_enum = - SOC_ENUM_SINGLE(WM8903_ANALOGUE_LEFT_INPUT_1, 0, 3, input_mode_text); +static SOC_ENUM_SINGLE_DECL(linput_mode_enum, + WM8903_ANALOGUE_LEFT_INPUT_1, 0, input_mode_text); -static const struct soc_enum rinput_mode_enum = - SOC_ENUM_SINGLE(WM8903_ANALOGUE_RIGHT_INPUT_1, 0, 3, input_mode_text); +static SOC_ENUM_SINGLE_DECL(rinput_mode_enum, + WM8903_ANALOGUE_RIGHT_INPUT_1, 0, input_mode_text); static const char *linput_mux_text[] = { "IN1L", "IN2L", "IN3L" }; -static const struct soc_enum linput_enum = - SOC_ENUM_SINGLE(WM8903_ANALOGUE_LEFT_INPUT_1, 2, 3, linput_mux_text); +static SOC_ENUM_SINGLE_DECL(linput_enum, + WM8903_ANALOGUE_LEFT_INPUT_1, 2, linput_mux_text); -static const struct soc_enum linput_inv_enum = - SOC_ENUM_SINGLE(WM8903_ANALOGUE_LEFT_INPUT_1, 4, 3, linput_mux_text); +static SOC_ENUM_SINGLE_DECL(linput_inv_enum, + WM8903_ANALOGUE_LEFT_INPUT_1, 4, linput_mux_text); static const char *rinput_mux_text[] = { "IN1R", "IN2R", "IN3R" }; -static const struct soc_enum rinput_enum = - SOC_ENUM_SINGLE(WM8903_ANALOGUE_RIGHT_INPUT_1, 2, 3, rinput_mux_text); +static SOC_ENUM_SINGLE_DECL(rinput_enum, + WM8903_ANALOGUE_RIGHT_INPUT_1, 2, rinput_mux_text); -static const struct soc_enum rinput_inv_enum = - SOC_ENUM_SINGLE(WM8903_ANALOGUE_RIGHT_INPUT_1, 4, 3, rinput_mux_text); +static SOC_ENUM_SINGLE_DECL(rinput_inv_enum, + WM8903_ANALOGUE_RIGHT_INPUT_1, 4, rinput_mux_text); static const char *sidetone_text[] = { "None", "Left", "Right" }; -static const struct soc_enum lsidetone_enum = - SOC_ENUM_SINGLE(WM8903_DAC_DIGITAL_0, 2, 3, sidetone_text); +static SOC_ENUM_SINGLE_DECL(lsidetone_enum, + WM8903_DAC_DIGITAL_0, 2, sidetone_text); -static const struct soc_enum rsidetone_enum = - SOC_ENUM_SINGLE(WM8903_DAC_DIGITAL_0, 0, 3, sidetone_text); +static SOC_ENUM_SINGLE_DECL(rsidetone_enum, + WM8903_DAC_DIGITAL_0, 0, sidetone_text); static const char *adcinput_text[] = { "ADC", "DMIC" }; -static const struct soc_enum adcinput_enum = - SOC_ENUM_SINGLE(WM8903_CLOCK_RATE_TEST_4, 9, 2, adcinput_text); +static SOC_ENUM_SINGLE_DECL(adcinput_enum, + WM8903_CLOCK_RATE_TEST_4, 9, adcinput_text); static const char *aif_text[] = { "Left", "Right" }; -static const struct soc_enum lcapture_enum = - SOC_ENUM_SINGLE(WM8903_AUDIO_INTERFACE_0, 7, 2, aif_text); +static SOC_ENUM_SINGLE_DECL(lcapture_enum, + WM8903_AUDIO_INTERFACE_0, 7, aif_text); -static const struct soc_enum rcapture_enum = - SOC_ENUM_SINGLE(WM8903_AUDIO_INTERFACE_0, 6, 2, aif_text); +static SOC_ENUM_SINGLE_DECL(rcapture_enum, + WM8903_AUDIO_INTERFACE_0, 6, aif_text); -static const struct soc_enum lplay_enum = - SOC_ENUM_SINGLE(WM8903_AUDIO_INTERFACE_0, 5, 2, aif_text); +static SOC_ENUM_SINGLE_DECL(lplay_enum, + WM8903_AUDIO_INTERFACE_0, 5, aif_text); -static const struct soc_enum rplay_enum = - SOC_ENUM_SINGLE(WM8903_AUDIO_INTERFACE_0, 4, 2, aif_text); +static SOC_ENUM_SINGLE_DECL(rplay_enum, + WM8903_AUDIO_INTERFACE_0, 4, aif_text); static const struct snd_kcontrol_new wm8903_snd_controls[] = { @@ -1897,21 +1897,13 @@ static void wm8903_free_gpio(struct wm8903_priv *wm8903) static int wm8903_probe(struct snd_soc_codec *codec) { struct wm8903_priv *wm8903 = snd_soc_codec_get_drvdata(codec); - int ret; wm8903->codec = codec; - codec->control_data = wm8903->regmap; - - ret = snd_soc_codec_set_cache_io(codec, 8, 16, SND_SOC_REGMAP); - if (ret != 0) { - dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); - return ret; - } /* power on device */ wm8903_set_bias_level(codec, SND_SOC_BIAS_STANDBY); - return ret; + return 0; } /* power down chip */ diff --git a/sound/soc/codecs/wm8904.c b/sound/soc/codecs/wm8904.c index 53bbfac6a83..49c35c36935 100644 --- a/sound/soc/codecs/wm8904.c +++ b/sound/soc/codecs/wm8904.c @@ -552,18 +552,20 @@ static const char *input_mode_text[] = { "Single-Ended", "Differential Line", "Differential Mic" }; -static const struct soc_enum lin_mode = - SOC_ENUM_SINGLE(WM8904_ANALOGUE_LEFT_INPUT_1, 0, 3, input_mode_text); +static SOC_ENUM_SINGLE_DECL(lin_mode, + WM8904_ANALOGUE_LEFT_INPUT_1, 0, + input_mode_text); -static const struct soc_enum rin_mode = - SOC_ENUM_SINGLE(WM8904_ANALOGUE_RIGHT_INPUT_1, 0, 3, input_mode_text); +static SOC_ENUM_SINGLE_DECL(rin_mode, + WM8904_ANALOGUE_RIGHT_INPUT_1, 0, + input_mode_text); static const char *hpf_mode_text[] = { "Hi-fi", "Voice 1", "Voice 2", "Voice 3" }; -static const struct soc_enum hpf_mode = - SOC_ENUM_SINGLE(WM8904_ADC_DIGITAL_0, 5, 4, hpf_mode_text); +static SOC_ENUM_SINGLE_DECL(hpf_mode, WM8904_ADC_DIGITAL_0, 5, + hpf_mode_text); static int wm8904_adc_osr_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) @@ -611,8 +613,7 @@ static const char *drc_path_text[] = { "ADC", "DAC" }; -static const struct soc_enum drc_path = - SOC_ENUM_SINGLE(WM8904_DRC_0, 14, 2, drc_path_text); +static SOC_ENUM_SINGLE_DECL(drc_path, WM8904_DRC_0, 14, drc_path_text); static const struct snd_kcontrol_new wm8904_dac_snd_controls[] = { SOC_SINGLE_TLV("Digital Playback Boost Volume", @@ -858,14 +859,14 @@ static const char *lin_text[] = { "IN1L", "IN2L", "IN3L" }; -static const struct soc_enum lin_enum = - SOC_ENUM_SINGLE(WM8904_ANALOGUE_LEFT_INPUT_1, 2, 3, lin_text); +static SOC_ENUM_SINGLE_DECL(lin_enum, WM8904_ANALOGUE_LEFT_INPUT_1, 2, + lin_text); static const struct snd_kcontrol_new lin_mux = SOC_DAPM_ENUM("Left Capture Mux", lin_enum); -static const struct soc_enum lin_inv_enum = - SOC_ENUM_SINGLE(WM8904_ANALOGUE_LEFT_INPUT_1, 4, 3, lin_text); +static SOC_ENUM_SINGLE_DECL(lin_inv_enum, WM8904_ANALOGUE_LEFT_INPUT_1, 4, + lin_text); static const struct snd_kcontrol_new lin_inv_mux = SOC_DAPM_ENUM("Left Capture Inveting Mux", lin_inv_enum); @@ -874,14 +875,14 @@ static const char *rin_text[] = { "IN1R", "IN2R", "IN3R" }; -static const struct soc_enum rin_enum = - SOC_ENUM_SINGLE(WM8904_ANALOGUE_RIGHT_INPUT_1, 2, 3, rin_text); +static SOC_ENUM_SINGLE_DECL(rin_enum, WM8904_ANALOGUE_RIGHT_INPUT_1, 2, + rin_text); static const struct snd_kcontrol_new rin_mux = SOC_DAPM_ENUM("Right Capture Mux", rin_enum); -static const struct soc_enum rin_inv_enum = - SOC_ENUM_SINGLE(WM8904_ANALOGUE_RIGHT_INPUT_1, 4, 3, rin_text); +static SOC_ENUM_SINGLE_DECL(rin_inv_enum, WM8904_ANALOGUE_RIGHT_INPUT_1, 4, + rin_text); static const struct snd_kcontrol_new rin_inv_mux = SOC_DAPM_ENUM("Right Capture Inveting Mux", rin_inv_enum); @@ -890,26 +891,26 @@ static const char *aif_text[] = { "Left", "Right" }; -static const struct soc_enum aifoutl_enum = - SOC_ENUM_SINGLE(WM8904_AUDIO_INTERFACE_0, 7, 2, aif_text); +static SOC_ENUM_SINGLE_DECL(aifoutl_enum, WM8904_AUDIO_INTERFACE_0, 7, + aif_text); static const struct snd_kcontrol_new aifoutl_mux = SOC_DAPM_ENUM("AIFOUTL Mux", aifoutl_enum); -static const struct soc_enum aifoutr_enum = - SOC_ENUM_SINGLE(WM8904_AUDIO_INTERFACE_0, 6, 2, aif_text); +static SOC_ENUM_SINGLE_DECL(aifoutr_enum, WM8904_AUDIO_INTERFACE_0, 6, + aif_text); static const struct snd_kcontrol_new aifoutr_mux = SOC_DAPM_ENUM("AIFOUTR Mux", aifoutr_enum); -static const struct soc_enum aifinl_enum = - SOC_ENUM_SINGLE(WM8904_AUDIO_INTERFACE_0, 5, 2, aif_text); +static SOC_ENUM_SINGLE_DECL(aifinl_enum, WM8904_AUDIO_INTERFACE_0, 5, + aif_text); static const struct snd_kcontrol_new aifinl_mux = SOC_DAPM_ENUM("AIFINL Mux", aifinl_enum); -static const struct soc_enum aifinr_enum = - SOC_ENUM_SINGLE(WM8904_AUDIO_INTERFACE_0, 4, 2, aif_text); +static SOC_ENUM_SINGLE_DECL(aifinr_enum, WM8904_AUDIO_INTERFACE_0, 4, + aif_text); static const struct snd_kcontrol_new aifinr_mux = SOC_DAPM_ENUM("AIFINR Mux", aifinr_enum); @@ -991,26 +992,26 @@ static const char *out_mux_text[] = { "DAC", "Bypass" }; -static const struct soc_enum hpl_enum = - SOC_ENUM_SINGLE(WM8904_ANALOGUE_OUT12_ZC, 3, 2, out_mux_text); +static SOC_ENUM_SINGLE_DECL(hpl_enum, WM8904_ANALOGUE_OUT12_ZC, 3, + out_mux_text); static const struct snd_kcontrol_new hpl_mux = SOC_DAPM_ENUM("HPL Mux", hpl_enum); -static const struct soc_enum hpr_enum = - SOC_ENUM_SINGLE(WM8904_ANALOGUE_OUT12_ZC, 2, 2, out_mux_text); +static SOC_ENUM_SINGLE_DECL(hpr_enum, WM8904_ANALOGUE_OUT12_ZC, 2, + out_mux_text); static const struct snd_kcontrol_new hpr_mux = SOC_DAPM_ENUM("HPR Mux", hpr_enum); -static const struct soc_enum linel_enum = - SOC_ENUM_SINGLE(WM8904_ANALOGUE_OUT12_ZC, 1, 2, out_mux_text); +static SOC_ENUM_SINGLE_DECL(linel_enum, WM8904_ANALOGUE_OUT12_ZC, 1, + out_mux_text); static const struct snd_kcontrol_new linel_mux = SOC_DAPM_ENUM("LINEL Mux", linel_enum); -static const struct soc_enum liner_enum = - SOC_ENUM_SINGLE(WM8904_ANALOGUE_OUT12_ZC, 0, 2, out_mux_text); +static SOC_ENUM_SINGLE_DECL(liner_enum, WM8904_ANALOGUE_OUT12_ZC, 0, + out_mux_text); static const struct snd_kcontrol_new liner_mux = SOC_DAPM_ENUM("LINER Mux", liner_enum); @@ -1019,14 +1020,14 @@ static const char *sidetone_text[] = { "None", "Left", "Right" }; -static const struct soc_enum dacl_sidetone_enum = - SOC_ENUM_SINGLE(WM8904_DAC_DIGITAL_0, 2, 3, sidetone_text); +static SOC_ENUM_SINGLE_DECL(dacl_sidetone_enum, WM8904_DAC_DIGITAL_0, 2, + sidetone_text); static const struct snd_kcontrol_new dacl_sidetone_mux = SOC_DAPM_ENUM("Left Sidetone Mux", dacl_sidetone_enum); -static const struct soc_enum dacr_sidetone_enum = - SOC_ENUM_SINGLE(WM8904_DAC_DIGITAL_0, 0, 3, sidetone_text); +static SOC_ENUM_SINGLE_DECL(dacr_sidetone_enum, WM8904_DAC_DIGITAL_0, 0, + sidetone_text); static const struct snd_kcontrol_new dacr_sidetone_mux = SOC_DAPM_ENUM("Right Sidetone Mux", dacr_sidetone_enum); @@ -1981,7 +1982,7 @@ static void wm8904_handle_retune_mobile_pdata(struct snd_soc_codec *codec) dev_dbg(codec->dev, "Allocated %d unique ReTune Mobile names\n", wm8904->num_retune_mobile_texts); - wm8904->retune_mobile_enum.max = wm8904->num_retune_mobile_texts; + wm8904->retune_mobile_enum.items = wm8904->num_retune_mobile_texts; wm8904->retune_mobile_enum.texts = wm8904->retune_mobile_texts; ret = snd_soc_add_codec_controls(codec, &control, 1); @@ -2022,7 +2023,7 @@ static void wm8904_handle_pdata(struct snd_soc_codec *codec) for (i = 0; i < pdata->num_drc_cfgs; i++) wm8904->drc_texts[i] = pdata->drc_cfgs[i].name; - wm8904->drc_enum.max = pdata->num_drc_cfgs; + wm8904->drc_enum.items = pdata->num_drc_cfgs; wm8904->drc_enum.texts = wm8904->drc_texts; ret = snd_soc_add_codec_controls(codec, &control, 1); @@ -2047,9 +2048,6 @@ static void wm8904_handle_pdata(struct snd_soc_codec *codec) static int wm8904_probe(struct snd_soc_codec *codec) { struct wm8904_priv *wm8904 = snd_soc_codec_get_drvdata(codec); - int ret; - - codec->control_data = wm8904->regmap; switch (wm8904->devtype) { case WM8904: @@ -2063,12 +2061,6 @@ static int wm8904_probe(struct snd_soc_codec *codec) return -EINVAL; } - ret = snd_soc_codec_set_cache_io(codec, 8, 16, SND_SOC_REGMAP); - if (ret != 0) { - dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); - return ret; - } - wm8904_handle_pdata(codec); wm8904_add_widgets(codec); diff --git a/sound/soc/codecs/wm8940.c b/sound/soc/codecs/wm8940.c index b404c26c175..fc6eec9ad66 100644 --- a/sound/soc/codecs/wm8940.c +++ b/sound/soc/codecs/wm8940.c @@ -154,22 +154,22 @@ static const struct reg_default wm8940_reg_defaults[] = { }; static const char *wm8940_companding[] = { "Off", "NC", "u-law", "A-law" }; -static const struct soc_enum wm8940_adc_companding_enum -= SOC_ENUM_SINGLE(WM8940_COMPANDINGCTL, 1, 4, wm8940_companding); -static const struct soc_enum wm8940_dac_companding_enum -= SOC_ENUM_SINGLE(WM8940_COMPANDINGCTL, 3, 4, wm8940_companding); +static SOC_ENUM_SINGLE_DECL(wm8940_adc_companding_enum, + WM8940_COMPANDINGCTL, 1, wm8940_companding); +static SOC_ENUM_SINGLE_DECL(wm8940_dac_companding_enum, + WM8940_COMPANDINGCTL, 3, wm8940_companding); static const char *wm8940_alc_mode_text[] = {"ALC", "Limiter"}; -static const struct soc_enum wm8940_alc_mode_enum -= SOC_ENUM_SINGLE(WM8940_ALC3, 8, 2, wm8940_alc_mode_text); +static SOC_ENUM_SINGLE_DECL(wm8940_alc_mode_enum, + WM8940_ALC3, 8, wm8940_alc_mode_text); static const char *wm8940_mic_bias_level_text[] = {"0.9", "0.65"}; -static const struct soc_enum wm8940_mic_bias_level_enum -= SOC_ENUM_SINGLE(WM8940_INPUTCTL, 8, 2, wm8940_mic_bias_level_text); +static SOC_ENUM_SINGLE_DECL(wm8940_mic_bias_level_enum, + WM8940_INPUTCTL, 8, wm8940_mic_bias_level_text); static const char *wm8940_filter_mode_text[] = {"Audio", "Application"}; -static const struct soc_enum wm8940_filter_mode_enum -= SOC_ENUM_SINGLE(WM8940_ADC, 7, 2, wm8940_filter_mode_text); +static SOC_ENUM_SINGLE_DECL(wm8940_filter_mode_enum, + WM8940_ADC, 7, wm8940_filter_mode_text); static DECLARE_TLV_DB_SCALE(wm8940_spk_vol_tlv, -5700, 100, 1); static DECLARE_TLV_DB_SCALE(wm8940_att_tlv, -1000, 1000, 0); @@ -712,12 +712,6 @@ static int wm8940_probe(struct snd_soc_codec *codec) int ret; u16 reg; - ret = snd_soc_codec_set_cache_io(codec, 8, 16, SND_SOC_REGMAP); - if (ret < 0) { - dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); - return ret; - } - ret = wm8940_reset(codec); if (ret < 0) { dev_err(codec->dev, "Failed to issue reset\n"); diff --git a/sound/soc/codecs/wm8955.c b/sound/soc/codecs/wm8955.c index 82c8ba97572..fecd4e4f4c5 100644 --- a/sound/soc/codecs/wm8955.c +++ b/sound/soc/codecs/wm8955.c @@ -416,22 +416,21 @@ static const char *bass_mode_text[] = { "Linear", "Adaptive", }; -static const struct soc_enum bass_mode = - SOC_ENUM_SINGLE(WM8955_BASS_CONTROL, 7, 2, bass_mode_text); +static SOC_ENUM_SINGLE_DECL(bass_mode, WM8955_BASS_CONTROL, 7, bass_mode_text); static const char *bass_cutoff_text[] = { "Low", "High" }; -static const struct soc_enum bass_cutoff = - SOC_ENUM_SINGLE(WM8955_BASS_CONTROL, 6, 2, bass_cutoff_text); +static SOC_ENUM_SINGLE_DECL(bass_cutoff, WM8955_BASS_CONTROL, 6, + bass_cutoff_text); static const char *treble_cutoff_text[] = { "High", "Low" }; -static const struct soc_enum treble_cutoff = - SOC_ENUM_SINGLE(WM8955_TREBLE_CONTROL, 6, 2, treble_cutoff_text); +static SOC_ENUM_SINGLE_DECL(treble_cutoff, WM8955_TREBLE_CONTROL, 2, + treble_cutoff_text); static const DECLARE_TLV_DB_SCALE(digital_tlv, -12750, 50, 1); static const DECLARE_TLV_DB_SCALE(atten_tlv, -600, 600, 0); @@ -896,14 +895,6 @@ static int wm8955_probe(struct snd_soc_codec *codec) struct wm8955_pdata *pdata = dev_get_platdata(codec->dev); int ret, i; - codec->control_data = wm8955->regmap; - - ret = snd_soc_codec_set_cache_io(codec, 7, 9, SND_SOC_REGMAP); - if (ret != 0) { - dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); - return ret; - } - for (i = 0; i < ARRAY_SIZE(wm8955->supplies); i++) wm8955->supplies[i].supply = wm8955_supply_names[i]; diff --git a/sound/soc/codecs/wm8958-dsp2.c b/sound/soc/codecs/wm8958-dsp2.c index d4248e00160..7ac2e511403 100644 --- a/sound/soc/codecs/wm8958-dsp2.c +++ b/sound/soc/codecs/wm8958-dsp2.c @@ -944,7 +944,7 @@ void wm8958_dsp2_init(struct snd_soc_codec *codec) for (i = 0; i < pdata->num_mbc_cfgs; i++) wm8994->mbc_texts[i] = pdata->mbc_cfgs[i].name; - wm8994->mbc_enum.max = pdata->num_mbc_cfgs; + wm8994->mbc_enum.items = pdata->num_mbc_cfgs; wm8994->mbc_enum.texts = wm8994->mbc_texts; ret = snd_soc_add_codec_controls(wm8994->hubs.codec, @@ -973,7 +973,7 @@ void wm8958_dsp2_init(struct snd_soc_codec *codec) for (i = 0; i < pdata->num_vss_cfgs; i++) wm8994->vss_texts[i] = pdata->vss_cfgs[i].name; - wm8994->vss_enum.max = pdata->num_vss_cfgs; + wm8994->vss_enum.items = pdata->num_vss_cfgs; wm8994->vss_enum.texts = wm8994->vss_texts; ret = snd_soc_add_codec_controls(wm8994->hubs.codec, @@ -1003,7 +1003,7 @@ void wm8958_dsp2_init(struct snd_soc_codec *codec) for (i = 0; i < pdata->num_vss_hpf_cfgs; i++) wm8994->vss_hpf_texts[i] = pdata->vss_hpf_cfgs[i].name; - wm8994->vss_hpf_enum.max = pdata->num_vss_hpf_cfgs; + wm8994->vss_hpf_enum.items = pdata->num_vss_hpf_cfgs; wm8994->vss_hpf_enum.texts = wm8994->vss_hpf_texts; ret = snd_soc_add_codec_controls(wm8994->hubs.codec, @@ -1034,7 +1034,7 @@ void wm8958_dsp2_init(struct snd_soc_codec *codec) for (i = 0; i < pdata->num_enh_eq_cfgs; i++) wm8994->enh_eq_texts[i] = pdata->enh_eq_cfgs[i].name; - wm8994->enh_eq_enum.max = pdata->num_enh_eq_cfgs; + wm8994->enh_eq_enum.items = pdata->num_enh_eq_cfgs; wm8994->enh_eq_enum.texts = wm8994->enh_eq_texts; ret = snd_soc_add_codec_controls(wm8994->hubs.codec, diff --git a/sound/soc/codecs/wm8960.c b/sound/soc/codecs/wm8960.c index f156010e52b..d04e9cad445 100644 --- a/sound/soc/codecs/wm8960.c +++ b/sound/soc/codecs/wm8960.c @@ -976,12 +976,6 @@ static int wm8960_probe(struct snd_soc_codec *codec) wm8960->set_bias_level = wm8960_set_bias_level_capless; } - ret = snd_soc_codec_set_cache_io(codec, 7, 9, SND_SOC_REGMAP); - if (ret < 0) { - dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); - return ret; - } - ret = wm8960_reset(codec); if (ret < 0) { dev_err(codec->dev, "Failed to issue reset\n"); diff --git a/sound/soc/codecs/wm8961.c b/sound/soc/codecs/wm8961.c index 900328e28a1..9c88f04442b 100644 --- a/sound/soc/codecs/wm8961.c +++ b/sound/soc/codecs/wm8961.c @@ -317,15 +317,15 @@ static const char *adc_hpf_text[] = { "Hi-fi", "Voice 1", "Voice 2", "Voice 3", }; -static const struct soc_enum adc_hpf = - SOC_ENUM_SINGLE(WM8961_ADC_DAC_CONTROL_2, 7, 4, adc_hpf_text); +static SOC_ENUM_SINGLE_DECL(adc_hpf, + WM8961_ADC_DAC_CONTROL_2, 7, adc_hpf_text); static const char *dac_deemph_text[] = { "None", "32kHz", "44.1kHz", "48kHz", }; -static const struct soc_enum dac_deemph = - SOC_ENUM_SINGLE(WM8961_ADC_DAC_CONTROL_1, 1, 4, dac_deemph_text); +static SOC_ENUM_SINGLE_DECL(dac_deemph, + WM8961_ADC_DAC_CONTROL_1, 1, dac_deemph_text); static const DECLARE_TLV_DB_SCALE(out_tlv, -12100, 100, 1); static const DECLARE_TLV_DB_SCALE(hp_sec_tlv, -700, 100, 0); @@ -385,11 +385,11 @@ static const char *sidetone_text[] = { "None", "Left", "Right" }; -static const struct soc_enum dacl_sidetone = - SOC_ENUM_SINGLE(WM8961_DSP_SIDETONE_0, 2, 3, sidetone_text); +static SOC_ENUM_SINGLE_DECL(dacl_sidetone, + WM8961_DSP_SIDETONE_0, 2, sidetone_text); -static const struct soc_enum dacr_sidetone = - SOC_ENUM_SINGLE(WM8961_DSP_SIDETONE_1, 2, 3, sidetone_text); +static SOC_ENUM_SINGLE_DECL(dacr_sidetone, + WM8961_DSP_SIDETONE_1, 2, sidetone_text); static const struct snd_kcontrol_new dacl_mux = SOC_DAPM_ENUM("DACL Sidetone", dacl_sidetone); @@ -836,15 +836,8 @@ static struct snd_soc_dai_driver wm8961_dai = { static int wm8961_probe(struct snd_soc_codec *codec) { struct snd_soc_dapm_context *dapm = &codec->dapm; - int ret = 0; u16 reg; - ret = snd_soc_codec_set_cache_io(codec, 8, 16, SND_SOC_REGMAP); - if (ret != 0) { - dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); - return ret; - } - /* Enable class W */ reg = snd_soc_read(codec, WM8961_CHARGE_PUMP_B); reg |= WM8961_CP_DYN_PWR_MASK; diff --git a/sound/soc/codecs/wm8962.c b/sound/soc/codecs/wm8962.c index 97db3b45b41..5522d2566c6 100644 --- a/sound/soc/codecs/wm8962.c +++ b/sound/soc/codecs/wm8962.c @@ -1479,7 +1479,9 @@ static const DECLARE_TLV_DB_SCALE(eq_tlv, -1200, 100, 0); static int wm8962_dsp2_write_config(struct snd_soc_codec *codec) { - return regcache_sync_region(codec->control_data, + struct wm8962_priv *wm8962 = snd_soc_codec_get_drvdata(codec); + + return regcache_sync_region(wm8962->regmap, WM8962_HDBASS_AI_1, WM8962_MAX_REGISTER); } @@ -1658,16 +1660,16 @@ static const char *cap_hpf_mode_text[] = { "Hi-fi", "Application" }; -static const struct soc_enum cap_hpf_mode = - SOC_ENUM_SINGLE(WM8962_ADC_DAC_CONTROL_2, 10, 2, cap_hpf_mode_text); +static SOC_ENUM_SINGLE_DECL(cap_hpf_mode, + WM8962_ADC_DAC_CONTROL_2, 10, cap_hpf_mode_text); static const char *cap_lhpf_mode_text[] = { "LPF", "HPF" }; -static const struct soc_enum cap_lhpf_mode = - SOC_ENUM_SINGLE(WM8962_LHPF1, 1, 2, cap_lhpf_mode_text); +static SOC_ENUM_SINGLE_DECL(cap_lhpf_mode, + WM8962_LHPF1, 1, cap_lhpf_mode_text); static const struct snd_kcontrol_new wm8962_snd_controls[] = { SOC_DOUBLE("Input Mixer Switch", WM8962_INPUT_MIXER_CONTROL_1, 3, 2, 1, 1), @@ -2014,40 +2016,40 @@ static int dsp2_event(struct snd_soc_dapm_widget *w, static const char *st_text[] = { "None", "Left", "Right" }; -static const struct soc_enum str_enum = - SOC_ENUM_SINGLE(WM8962_DAC_DSP_MIXING_1, 2, 3, st_text); +static SOC_ENUM_SINGLE_DECL(str_enum, + WM8962_DAC_DSP_MIXING_1, 2, st_text); static const struct snd_kcontrol_new str_mux = SOC_DAPM_ENUM("Right Sidetone", str_enum); -static const struct soc_enum stl_enum = - SOC_ENUM_SINGLE(WM8962_DAC_DSP_MIXING_2, 2, 3, st_text); +static SOC_ENUM_SINGLE_DECL(stl_enum, + WM8962_DAC_DSP_MIXING_2, 2, st_text); static const struct snd_kcontrol_new stl_mux = SOC_DAPM_ENUM("Left Sidetone", stl_enum); static const char *outmux_text[] = { "DAC", "Mixer" }; -static const struct soc_enum spkoutr_enum = - SOC_ENUM_SINGLE(WM8962_SPEAKER_MIXER_2, 7, 2, outmux_text); +static SOC_ENUM_SINGLE_DECL(spkoutr_enum, + WM8962_SPEAKER_MIXER_2, 7, outmux_text); static const struct snd_kcontrol_new spkoutr_mux = SOC_DAPM_ENUM("SPKOUTR Mux", spkoutr_enum); -static const struct soc_enum spkoutl_enum = - SOC_ENUM_SINGLE(WM8962_SPEAKER_MIXER_1, 7, 2, outmux_text); +static SOC_ENUM_SINGLE_DECL(spkoutl_enum, + WM8962_SPEAKER_MIXER_1, 7, outmux_text); static const struct snd_kcontrol_new spkoutl_mux = SOC_DAPM_ENUM("SPKOUTL Mux", spkoutl_enum); -static const struct soc_enum hpoutr_enum = - SOC_ENUM_SINGLE(WM8962_HEADPHONE_MIXER_2, 7, 2, outmux_text); +static SOC_ENUM_SINGLE_DECL(hpoutr_enum, + WM8962_HEADPHONE_MIXER_2, 7, outmux_text); static const struct snd_kcontrol_new hpoutr_mux = SOC_DAPM_ENUM("HPOUTR Mux", hpoutr_enum); -static const struct soc_enum hpoutl_enum = - SOC_ENUM_SINGLE(WM8962_HEADPHONE_MIXER_1, 7, 2, outmux_text); +static SOC_ENUM_SINGLE_DECL(hpoutl_enum, + WM8962_HEADPHONE_MIXER_1, 7, outmux_text); static const struct snd_kcontrol_new hpoutl_mux = SOC_DAPM_ENUM("HPOUTL Mux", hpoutl_enum); @@ -2884,9 +2886,13 @@ static int wm8962_set_fll(struct snd_soc_codec *codec, int fll_id, int source, snd_soc_write(codec, WM8962_FLL_CONTROL_7, fll_div.lambda); snd_soc_write(codec, WM8962_FLL_CONTROL_8, fll_div.n); - try_wait_for_completion(&wm8962->fll_lock); + reinit_completion(&wm8962->fll_lock); - pm_runtime_get_sync(codec->dev); + ret = pm_runtime_get_sync(codec->dev); + if (ret < 0) { + dev_err(codec->dev, "Failed to resume device: %d\n", ret); + return ret; + } snd_soc_update_bits(codec, WM8962_FLL_CONTROL_1, WM8962_FLL_FRAC | WM8962_FLL_REFCLK_SRC_MASK | @@ -2894,8 +2900,6 @@ static int wm8962_set_fll(struct snd_soc_codec *codec, int fll_id, int source, dev_dbg(codec->dev, "FLL configured for %dHz->%dHz\n", Fref, Fout); - ret = 0; - /* This should be a massive overestimate but go even * higher if we'll error out */ @@ -2909,14 +2913,17 @@ static int wm8962_set_fll(struct snd_soc_codec *codec, int fll_id, int source, if (timeout == 0 && wm8962->irq) { dev_err(codec->dev, "FLL lock timed out"); - ret = -ETIMEDOUT; + snd_soc_update_bits(codec, WM8962_FLL_CONTROL_1, + WM8962_FLL_ENA, 0); + pm_runtime_put(codec->dev); + return -ETIMEDOUT; } wm8962->fll_fref = Fref; wm8962->fll_fout = Fout; wm8962->fll_src = source; - return ret; + return 0; } static int wm8962_mute(struct snd_soc_dai *dai, int mute) @@ -3003,9 +3010,16 @@ static irqreturn_t wm8962_irq(int irq, void *data) unsigned int active; int reg, ret; + ret = pm_runtime_get_sync(dev); + if (ret < 0) { + dev_err(dev, "Failed to resume: %d\n", ret); + return IRQ_NONE; + } + ret = regmap_read(wm8962->regmap, WM8962_INTERRUPT_STATUS_2_MASK, &mask); if (ret != 0) { + pm_runtime_put(dev); dev_err(dev, "Failed to read interrupt mask: %d\n", ret); return IRQ_NONE; @@ -3013,14 +3027,17 @@ static irqreturn_t wm8962_irq(int irq, void *data) ret = regmap_read(wm8962->regmap, WM8962_INTERRUPT_STATUS_2, &active); if (ret != 0) { + pm_runtime_put(dev); dev_err(dev, "Failed to read interrupt: %d\n", ret); return IRQ_NONE; } active &= ~mask; - if (!active) + if (!active) { + pm_runtime_put(dev); return IRQ_NONE; + } /* Acknowledge the interrupts */ ret = regmap_write(wm8962->regmap, WM8962_INTERRUPT_STATUS_2, active); @@ -3070,6 +3087,8 @@ static irqreturn_t wm8962_irq(int irq, void *data) msecs_to_jiffies(250)); } + pm_runtime_put(dev); + return IRQ_HANDLED; } @@ -3089,6 +3108,7 @@ static irqreturn_t wm8962_irq(int irq, void *data) int wm8962_mic_detect(struct snd_soc_codec *codec, struct snd_soc_jack *jack) { struct wm8962_priv *wm8962 = snd_soc_codec_get_drvdata(codec); + struct snd_soc_dapm_context *dapm = &codec->dapm; int irq_mask, enable; wm8962->jack = jack; @@ -3109,14 +3129,18 @@ int wm8962_mic_detect(struct snd_soc_codec *codec, struct snd_soc_jack *jack) snd_soc_jack_report(wm8962->jack, 0, SND_JACK_MICROPHONE | SND_JACK_BTN_0); + snd_soc_dapm_mutex_lock(dapm); + if (jack) { - snd_soc_dapm_force_enable_pin(&codec->dapm, "SYSCLK"); - snd_soc_dapm_force_enable_pin(&codec->dapm, "MICBIAS"); + snd_soc_dapm_force_enable_pin_unlocked(dapm, "SYSCLK"); + snd_soc_dapm_force_enable_pin_unlocked(dapm, "MICBIAS"); } else { - snd_soc_dapm_disable_pin(&codec->dapm, "SYSCLK"); - snd_soc_dapm_disable_pin(&codec->dapm, "MICBIAS"); + snd_soc_dapm_disable_pin_unlocked(dapm, "SYSCLK"); + snd_soc_dapm_disable_pin_unlocked(dapm, "MICBIAS"); } + snd_soc_dapm_mutex_unlock(dapm); + return 0; } EXPORT_SYMBOL_GPL(wm8962_mic_detect); @@ -3400,13 +3424,6 @@ static int wm8962_probe(struct snd_soc_codec *codec) bool dmicclk, dmicdat; wm8962->codec = codec; - codec->control_data = wm8962->regmap; - - ret = snd_soc_codec_set_cache_io(codec, 16, 16, SND_SOC_REGMAP); - if (ret != 0) { - dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); - return ret; - } wm8962->disable_nb[0].notifier_call = wm8962_regulator_event_0; wm8962->disable_nb[1].notifier_call = wm8962_regulator_event_1; diff --git a/sound/soc/codecs/wm8971.c b/sound/soc/codecs/wm8971.c index 67aba78a7ca..09b7b420022 100644 --- a/sound/soc/codecs/wm8971.c +++ b/sound/soc/codecs/wm8971.c @@ -648,12 +648,6 @@ static int wm8971_probe(struct snd_soc_codec *codec) int ret = 0; u16 reg; - ret = snd_soc_codec_set_cache_io(codec, 7, 9, SND_SOC_REGMAP); - if (ret < 0) { - printk(KERN_ERR "wm8971: failed to set cache I/O: %d\n", ret); - return ret; - } - INIT_DELAYED_WORK(&codec->dapm.delayed_work, wm8971_work); wm8971_workq = create_workqueue("wm8971"); if (wm8971_workq == NULL) diff --git a/sound/soc/codecs/wm8974.c b/sound/soc/codecs/wm8974.c index 15f45c7bd83..0627c56fa44 100644 --- a/sound/soc/codecs/wm8974.c +++ b/sound/soc/codecs/wm8974.c @@ -84,8 +84,8 @@ static const struct soc_enum wm8974_enum[] = { static const char *wm8974_auxmode_text[] = { "Buffer", "Mixer" }; -static const struct soc_enum wm8974_auxmode = - SOC_ENUM_SINGLE(WM8974_INPUT, 3, 2, wm8974_auxmode_text); +static SOC_ENUM_SINGLE_DECL(wm8974_auxmode, + WM8974_INPUT, 3, wm8974_auxmode_text); static const DECLARE_TLV_DB_SCALE(digital_tlv, -12750, 50, 1); static const DECLARE_TLV_DB_SCALE(eq_tlv, -1200, 100, 0); @@ -593,12 +593,6 @@ static int wm8974_probe(struct snd_soc_codec *codec) { int ret = 0; - ret = snd_soc_codec_set_cache_io(codec, 7, 9, SND_SOC_REGMAP); - if (ret < 0) { - dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); - return ret; - } - ret = wm8974_reset(codec); if (ret < 0) { dev_err(codec->dev, "Failed to issue reset\n"); diff --git a/sound/soc/codecs/wm8978.c b/sound/soc/codecs/wm8978.c index d8fc531c0e5..28ef46c91f6 100644 --- a/sound/soc/codecs/wm8978.c +++ b/sound/soc/codecs/wm8978.c @@ -117,21 +117,21 @@ static const char *wm8978_eq5[] = {"5.3kHz", "6.9kHz", "9kHz", "11.7kHz"}; static const char *wm8978_alc3[] = {"ALC", "Limiter"}; static const char *wm8978_alc1[] = {"Off", "Right", "Left", "Both"}; -static const SOC_ENUM_SINGLE_DECL(adc_compand, WM8978_COMPANDING_CONTROL, 1, - wm8978_companding); -static const SOC_ENUM_SINGLE_DECL(dac_compand, WM8978_COMPANDING_CONTROL, 3, - wm8978_companding); -static const SOC_ENUM_SINGLE_DECL(eqmode, WM8978_EQ1, 8, wm8978_eqmode); -static const SOC_ENUM_SINGLE_DECL(eq1, WM8978_EQ1, 5, wm8978_eq1); -static const SOC_ENUM_SINGLE_DECL(eq2bw, WM8978_EQ2, 8, wm8978_bw); -static const SOC_ENUM_SINGLE_DECL(eq2, WM8978_EQ2, 5, wm8978_eq2); -static const SOC_ENUM_SINGLE_DECL(eq3bw, WM8978_EQ3, 8, wm8978_bw); -static const SOC_ENUM_SINGLE_DECL(eq3, WM8978_EQ3, 5, wm8978_eq3); -static const SOC_ENUM_SINGLE_DECL(eq4bw, WM8978_EQ4, 8, wm8978_bw); -static const SOC_ENUM_SINGLE_DECL(eq4, WM8978_EQ4, 5, wm8978_eq4); -static const SOC_ENUM_SINGLE_DECL(eq5, WM8978_EQ5, 5, wm8978_eq5); -static const SOC_ENUM_SINGLE_DECL(alc3, WM8978_ALC_CONTROL_3, 8, wm8978_alc3); -static const SOC_ENUM_SINGLE_DECL(alc1, WM8978_ALC_CONTROL_1, 7, wm8978_alc1); +static SOC_ENUM_SINGLE_DECL(adc_compand, WM8978_COMPANDING_CONTROL, 1, + wm8978_companding); +static SOC_ENUM_SINGLE_DECL(dac_compand, WM8978_COMPANDING_CONTROL, 3, + wm8978_companding); +static SOC_ENUM_SINGLE_DECL(eqmode, WM8978_EQ1, 8, wm8978_eqmode); +static SOC_ENUM_SINGLE_DECL(eq1, WM8978_EQ1, 5, wm8978_eq1); +static SOC_ENUM_SINGLE_DECL(eq2bw, WM8978_EQ2, 8, wm8978_bw); +static SOC_ENUM_SINGLE_DECL(eq2, WM8978_EQ2, 5, wm8978_eq2); +static SOC_ENUM_SINGLE_DECL(eq3bw, WM8978_EQ3, 8, wm8978_bw); +static SOC_ENUM_SINGLE_DECL(eq3, WM8978_EQ3, 5, wm8978_eq3); +static SOC_ENUM_SINGLE_DECL(eq4bw, WM8978_EQ4, 8, wm8978_bw); +static SOC_ENUM_SINGLE_DECL(eq4, WM8978_EQ4, 5, wm8978_eq4); +static SOC_ENUM_SINGLE_DECL(eq5, WM8978_EQ5, 5, wm8978_eq5); +static SOC_ENUM_SINGLE_DECL(alc3, WM8978_ALC_CONTROL_3, 8, wm8978_alc3); +static SOC_ENUM_SINGLE_DECL(alc1, WM8978_ALC_CONTROL_1, 7, wm8978_alc1); static const DECLARE_TLV_DB_SCALE(digital_tlv, -12750, 50, 1); static const DECLARE_TLV_DB_SCALE(eq_tlv, -1200, 100, 0); @@ -975,19 +975,13 @@ static const int update_reg[] = { static int wm8978_probe(struct snd_soc_codec *codec) { struct wm8978_priv *wm8978 = snd_soc_codec_get_drvdata(codec); - int ret = 0, i; + int i; /* * Set default system clock to PLL, it is more precise, this is also the * default hardware setting */ wm8978->sysclk = WM8978_PLL; - codec->control_data = wm8978->regmap; - ret = snd_soc_codec_set_cache_io(codec, 7, 9, SND_SOC_REGMAP); - if (ret < 0) { - dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); - return ret; - } /* * Set the update bit in all registers, that have one. This way all diff --git a/sound/soc/codecs/wm8983.c b/sound/soc/codecs/wm8983.c index aa41ba0dfff..2b9bfa53efb 100644 --- a/sound/soc/codecs/wm8983.c +++ b/sound/soc/codecs/wm8983.c @@ -205,49 +205,44 @@ static const DECLARE_TLV_DB_SCALE(bypass_tlv, -1500, 300, 0); static const DECLARE_TLV_DB_SCALE(pga_boost_tlv, 0, 2000, 0); static const char *alc_sel_text[] = { "Off", "Right", "Left", "Stereo" }; -static const SOC_ENUM_SINGLE_DECL(alc_sel, WM8983_ALC_CONTROL_1, 7, - alc_sel_text); +static SOC_ENUM_SINGLE_DECL(alc_sel, WM8983_ALC_CONTROL_1, 7, alc_sel_text); static const char *alc_mode_text[] = { "ALC", "Limiter" }; -static const SOC_ENUM_SINGLE_DECL(alc_mode, WM8983_ALC_CONTROL_3, 8, - alc_mode_text); +static SOC_ENUM_SINGLE_DECL(alc_mode, WM8983_ALC_CONTROL_3, 8, alc_mode_text); static const char *filter_mode_text[] = { "Audio", "Application" }; -static const SOC_ENUM_SINGLE_DECL(filter_mode, WM8983_ADC_CONTROL, 7, - filter_mode_text); +static SOC_ENUM_SINGLE_DECL(filter_mode, WM8983_ADC_CONTROL, 7, + filter_mode_text); static const char *eq_bw_text[] = { "Narrow", "Wide" }; static const char *eqmode_text[] = { "Capture", "Playback" }; -static const SOC_ENUM_SINGLE_EXT_DECL(eqmode, eqmode_text); +static SOC_ENUM_SINGLE_EXT_DECL(eqmode, eqmode_text); static const char *eq1_cutoff_text[] = { "80Hz", "105Hz", "135Hz", "175Hz" }; -static const SOC_ENUM_SINGLE_DECL(eq1_cutoff, WM8983_EQ1_LOW_SHELF, 5, - eq1_cutoff_text); +static SOC_ENUM_SINGLE_DECL(eq1_cutoff, WM8983_EQ1_LOW_SHELF, 5, + eq1_cutoff_text); static const char *eq2_cutoff_text[] = { "230Hz", "300Hz", "385Hz", "500Hz" }; -static const SOC_ENUM_SINGLE_DECL(eq2_bw, WM8983_EQ2_PEAK_1, 8, eq_bw_text); -static const SOC_ENUM_SINGLE_DECL(eq2_cutoff, WM8983_EQ2_PEAK_1, 5, - eq2_cutoff_text); +static SOC_ENUM_SINGLE_DECL(eq2_bw, WM8983_EQ2_PEAK_1, 8, eq_bw_text); +static SOC_ENUM_SINGLE_DECL(eq2_cutoff, WM8983_EQ2_PEAK_1, 5, eq2_cutoff_text); static const char *eq3_cutoff_text[] = { "650Hz", "850Hz", "1.1kHz", "1.4kHz" }; -static const SOC_ENUM_SINGLE_DECL(eq3_bw, WM8983_EQ3_PEAK_2, 8, eq_bw_text); -static const SOC_ENUM_SINGLE_DECL(eq3_cutoff, WM8983_EQ3_PEAK_2, 5, - eq3_cutoff_text); +static SOC_ENUM_SINGLE_DECL(eq3_bw, WM8983_EQ3_PEAK_2, 8, eq_bw_text); +static SOC_ENUM_SINGLE_DECL(eq3_cutoff, WM8983_EQ3_PEAK_2, 5, eq3_cutoff_text); static const char *eq4_cutoff_text[] = { "1.8kHz", "2.4kHz", "3.2kHz", "4.1kHz" }; -static const SOC_ENUM_SINGLE_DECL(eq4_bw, WM8983_EQ4_PEAK_3, 8, eq_bw_text); -static const SOC_ENUM_SINGLE_DECL(eq4_cutoff, WM8983_EQ4_PEAK_3, 5, - eq4_cutoff_text); +static SOC_ENUM_SINGLE_DECL(eq4_bw, WM8983_EQ4_PEAK_3, 8, eq_bw_text); +static SOC_ENUM_SINGLE_DECL(eq4_cutoff, WM8983_EQ4_PEAK_3, 5, eq4_cutoff_text); static const char *eq5_cutoff_text[] = { "5.3kHz", "6.9kHz", "9kHz", "11.7kHz" }; -static const SOC_ENUM_SINGLE_DECL(eq5_cutoff, WM8983_EQ5_HIGH_SHELF, 5, - eq5_cutoff_text); +static SOC_ENUM_SINGLE_DECL(eq5_cutoff, WM8983_EQ5_HIGH_SHELF, 5, + eq5_cutoff_text); static const char *depth_3d_text[] = { "Off", @@ -267,8 +262,8 @@ static const char *depth_3d_text[] = { "93.3%", "100%" }; -static const SOC_ENUM_SINGLE_DECL(depth_3d, WM8983_3D_CONTROL, 0, - depth_3d_text); +static SOC_ENUM_SINGLE_DECL(depth_3d, WM8983_3D_CONTROL, 0, + depth_3d_text); static const struct snd_kcontrol_new wm8983_snd_controls[] = { SOC_SINGLE("Digital Loopback Switch", WM8983_COMPANDING_CONTROL, @@ -1000,12 +995,6 @@ static int wm8983_probe(struct snd_soc_codec *codec) int ret; int i; - ret = snd_soc_codec_set_cache_io(codec, 7, 9, SND_SOC_REGMAP); - if (ret < 0) { - dev_err(codec->dev, "Failed to set cache i/o: %d\n", ret); - return ret; - } - ret = snd_soc_write(codec, WM8983_SOFTWARE_RESET, 0); if (ret < 0) { dev_err(codec->dev, "Failed to issue reset: %d\n", ret); @@ -1129,7 +1118,7 @@ static struct spi_driver wm8983_spi_driver = { }; #endif -#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) +#if IS_ENABLED(CONFIG_I2C) static int wm8983_i2c_probe(struct i2c_client *i2c, const struct i2c_device_id *id) { @@ -1182,7 +1171,7 @@ static int __init wm8983_modinit(void) { int ret = 0; -#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) +#if IS_ENABLED(CONFIG_I2C) ret = i2c_add_driver(&wm8983_i2c_driver); if (ret) { printk(KERN_ERR "Failed to register wm8983 I2C driver: %d\n", @@ -1202,7 +1191,7 @@ module_init(wm8983_modinit); static void __exit wm8983_exit(void) { -#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) +#if IS_ENABLED(CONFIG_I2C) i2c_del_driver(&wm8983_i2c_driver); #endif #if defined(CONFIG_SPI_MASTER) diff --git a/sound/soc/codecs/wm8985.c b/sound/soc/codecs/wm8985.c index 271b517911a..5473dc96958 100644 --- a/sound/soc/codecs/wm8985.c +++ b/sound/soc/codecs/wm8985.c @@ -226,52 +226,48 @@ static const DECLARE_TLV_DB_SCALE(bypass_tlv, -1500, 300, 0); static const DECLARE_TLV_DB_SCALE(pga_boost_tlv, 0, 2000, 0); static const char *alc_sel_text[] = { "Off", "Right", "Left", "Stereo" }; -static const SOC_ENUM_SINGLE_DECL(alc_sel, WM8985_ALC_CONTROL_1, 7, - alc_sel_text); +static SOC_ENUM_SINGLE_DECL(alc_sel, WM8985_ALC_CONTROL_1, 7, alc_sel_text); static const char *alc_mode_text[] = { "ALC", "Limiter" }; -static const SOC_ENUM_SINGLE_DECL(alc_mode, WM8985_ALC_CONTROL_3, 8, - alc_mode_text); +static SOC_ENUM_SINGLE_DECL(alc_mode, WM8985_ALC_CONTROL_3, 8, alc_mode_text); static const char *filter_mode_text[] = { "Audio", "Application" }; -static const SOC_ENUM_SINGLE_DECL(filter_mode, WM8985_ADC_CONTROL, 7, - filter_mode_text); +static SOC_ENUM_SINGLE_DECL(filter_mode, WM8985_ADC_CONTROL, 7, + filter_mode_text); static const char *eq_bw_text[] = { "Narrow", "Wide" }; static const char *eqmode_text[] = { "Capture", "Playback" }; -static const SOC_ENUM_SINGLE_EXT_DECL(eqmode, eqmode_text); +static SOC_ENUM_SINGLE_EXT_DECL(eqmode, eqmode_text); static const char *eq1_cutoff_text[] = { "80Hz", "105Hz", "135Hz", "175Hz" }; -static const SOC_ENUM_SINGLE_DECL(eq1_cutoff, WM8985_EQ1_LOW_SHELF, 5, - eq1_cutoff_text); +static SOC_ENUM_SINGLE_DECL(eq1_cutoff, WM8985_EQ1_LOW_SHELF, 5, + eq1_cutoff_text); static const char *eq2_cutoff_text[] = { "230Hz", "300Hz", "385Hz", "500Hz" }; -static const SOC_ENUM_SINGLE_DECL(eq2_bw, WM8985_EQ2_PEAK_1, 8, eq_bw_text); -static const SOC_ENUM_SINGLE_DECL(eq2_cutoff, WM8985_EQ2_PEAK_1, 5, - eq2_cutoff_text); +static SOC_ENUM_SINGLE_DECL(eq2_bw, WM8985_EQ2_PEAK_1, 8, eq_bw_text); +static SOC_ENUM_SINGLE_DECL(eq2_cutoff, WM8985_EQ2_PEAK_1, 5, eq2_cutoff_text); static const char *eq3_cutoff_text[] = { "650Hz", "850Hz", "1.1kHz", "1.4kHz" }; -static const SOC_ENUM_SINGLE_DECL(eq3_bw, WM8985_EQ3_PEAK_2, 8, eq_bw_text); -static const SOC_ENUM_SINGLE_DECL(eq3_cutoff, WM8985_EQ3_PEAK_2, 5, - eq3_cutoff_text); +static SOC_ENUM_SINGLE_DECL(eq3_bw, WM8985_EQ3_PEAK_2, 8, eq_bw_text); +static SOC_ENUM_SINGLE_DECL(eq3_cutoff, WM8985_EQ3_PEAK_2, 5, + eq3_cutoff_text); static const char *eq4_cutoff_text[] = { "1.8kHz", "2.4kHz", "3.2kHz", "4.1kHz" }; -static const SOC_ENUM_SINGLE_DECL(eq4_bw, WM8985_EQ4_PEAK_3, 8, eq_bw_text); -static const SOC_ENUM_SINGLE_DECL(eq4_cutoff, WM8985_EQ4_PEAK_3, 5, - eq4_cutoff_text); +static SOC_ENUM_SINGLE_DECL(eq4_bw, WM8985_EQ4_PEAK_3, 8, eq_bw_text); +static SOC_ENUM_SINGLE_DECL(eq4_cutoff, WM8985_EQ4_PEAK_3, 5, eq4_cutoff_text); static const char *eq5_cutoff_text[] = { "5.3kHz", "6.9kHz", "9kHz", "11.7kHz" }; -static const SOC_ENUM_SINGLE_DECL(eq5_cutoff, WM8985_EQ5_HIGH_SHELF, 5, +static SOC_ENUM_SINGLE_DECL(eq5_cutoff, WM8985_EQ5_HIGH_SHELF, 5, eq5_cutoff_text); static const char *speaker_mode_text[] = { "Class A/B", "Class D" }; -static const SOC_ENUM_SINGLE_DECL(speaker_mode, 0x17, 8, speaker_mode_text); +static SOC_ENUM_SINGLE_DECL(speaker_mode, 0x17, 8, speaker_mode_text); static const char *depth_3d_text[] = { "Off", @@ -291,8 +287,7 @@ static const char *depth_3d_text[] = { "93.3%", "100%" }; -static const SOC_ENUM_SINGLE_DECL(depth_3d, WM8985_3D_CONTROL, 0, - depth_3d_text); +static SOC_ENUM_SINGLE_DECL(depth_3d, WM8985_3D_CONTROL, 0, depth_3d_text); static const struct snd_kcontrol_new wm8985_snd_controls[] = { SOC_SINGLE("Digital Loopback Switch", WM8985_COMPANDING_CONTROL, @@ -1000,13 +995,6 @@ static int wm8985_probe(struct snd_soc_codec *codec) int ret; wm8985 = snd_soc_codec_get_drvdata(codec); - codec->control_data = wm8985->regmap; - - ret = snd_soc_codec_set_cache_io(codec, 7, 9, SND_SOC_REGMAP); - if (ret < 0) { - dev_err(codec->dev, "Failed to set cache i/o: %d\n", ret); - return ret; - } for (i = 0; i < ARRAY_SIZE(wm8985->supplies); i++) wm8985->supplies[i].supply = wm8985_supply_names[i]; diff --git a/sound/soc/codecs/wm8988.c b/sound/soc/codecs/wm8988.c index a55e1c2c382..3a1ae4f5164 100644 --- a/sound/soc/codecs/wm8988.c +++ b/sound/soc/codecs/wm8988.c @@ -116,7 +116,7 @@ static bool wm8988_writeable(struct device *dev, unsigned int reg) struct wm8988_priv { struct regmap *regmap; unsigned int sysclk; - struct snd_pcm_hw_constraint_list *sysclk_constraints; + const struct snd_pcm_hw_constraint_list *sysclk_constraints; }; #define wm8988_reset(c) snd_soc_write(c, WM8988_RESET, 0) @@ -126,46 +126,46 @@ struct wm8988_priv { */ static const char *bass_boost_txt[] = {"Linear Control", "Adaptive Boost"}; -static const struct soc_enum bass_boost = - SOC_ENUM_SINGLE(WM8988_BASS, 7, 2, bass_boost_txt); +static SOC_ENUM_SINGLE_DECL(bass_boost, + WM8988_BASS, 7, bass_boost_txt); static const char *bass_filter_txt[] = { "130Hz @ 48kHz", "200Hz @ 48kHz" }; -static const struct soc_enum bass_filter = - SOC_ENUM_SINGLE(WM8988_BASS, 6, 2, bass_filter_txt); +static SOC_ENUM_SINGLE_DECL(bass_filter, + WM8988_BASS, 6, bass_filter_txt); static const char *treble_txt[] = {"8kHz", "4kHz"}; -static const struct soc_enum treble = - SOC_ENUM_SINGLE(WM8988_TREBLE, 6, 2, treble_txt); +static SOC_ENUM_SINGLE_DECL(treble, + WM8988_TREBLE, 6, treble_txt); static const char *stereo_3d_lc_txt[] = {"200Hz", "500Hz"}; -static const struct soc_enum stereo_3d_lc = - SOC_ENUM_SINGLE(WM8988_3D, 5, 2, stereo_3d_lc_txt); +static SOC_ENUM_SINGLE_DECL(stereo_3d_lc, + WM8988_3D, 5, stereo_3d_lc_txt); static const char *stereo_3d_uc_txt[] = {"2.2kHz", "1.5kHz"}; -static const struct soc_enum stereo_3d_uc = - SOC_ENUM_SINGLE(WM8988_3D, 6, 2, stereo_3d_uc_txt); +static SOC_ENUM_SINGLE_DECL(stereo_3d_uc, + WM8988_3D, 6, stereo_3d_uc_txt); static const char *stereo_3d_func_txt[] = {"Capture", "Playback"}; -static const struct soc_enum stereo_3d_func = - SOC_ENUM_SINGLE(WM8988_3D, 7, 2, stereo_3d_func_txt); +static SOC_ENUM_SINGLE_DECL(stereo_3d_func, + WM8988_3D, 7, stereo_3d_func_txt); static const char *alc_func_txt[] = {"Off", "Right", "Left", "Stereo"}; -static const struct soc_enum alc_func = - SOC_ENUM_SINGLE(WM8988_ALC1, 7, 4, alc_func_txt); +static SOC_ENUM_SINGLE_DECL(alc_func, + WM8988_ALC1, 7, alc_func_txt); static const char *ng_type_txt[] = {"Constant PGA Gain", "Mute ADC Output"}; -static const struct soc_enum ng_type = - SOC_ENUM_SINGLE(WM8988_NGATE, 1, 2, ng_type_txt); +static SOC_ENUM_SINGLE_DECL(ng_type, + WM8988_NGATE, 1, ng_type_txt); static const char *deemph_txt[] = {"None", "32Khz", "44.1Khz", "48Khz"}; -static const struct soc_enum deemph = - SOC_ENUM_SINGLE(WM8988_ADCDAC, 1, 4, deemph_txt); +static SOC_ENUM_SINGLE_DECL(deemph, + WM8988_ADCDAC, 1, deemph_txt); static const char *adcpol_txt[] = {"Normal", "L Invert", "R Invert", "L + R Invert"}; -static const struct soc_enum adcpol = - SOC_ENUM_SINGLE(WM8988_ADCDAC, 5, 4, adcpol_txt); +static SOC_ENUM_SINGLE_DECL(adcpol, + WM8988_ADCDAC, 5, adcpol_txt); static const DECLARE_TLV_DB_SCALE(pga_tlv, -1725, 75, 0); static const DECLARE_TLV_DB_SCALE(adc_tlv, -9750, 50, 1); @@ -317,16 +317,16 @@ static const struct snd_kcontrol_new wm8988_right_pga_controls = /* Differential Mux */ static const char *wm8988_diff_sel[] = {"Line 1", "Line 2"}; -static const struct soc_enum diffmux = - SOC_ENUM_SINGLE(WM8988_ADCIN, 8, 2, wm8988_diff_sel); +static SOC_ENUM_SINGLE_DECL(diffmux, + WM8988_ADCIN, 8, wm8988_diff_sel); static const struct snd_kcontrol_new wm8988_diffmux_controls = SOC_DAPM_ENUM("Route", diffmux); /* Mono ADC Mux */ static const char *wm8988_mono_mux[] = {"Stereo", "Mono (Left)", "Mono (Right)", "Digital Mono"}; -static const struct soc_enum monomux = - SOC_ENUM_SINGLE(WM8988_ADCIN, 6, 4, wm8988_mono_mux); +static SOC_ENUM_SINGLE_DECL(monomux, + WM8988_ADCIN, 6, wm8988_mono_mux); static const struct snd_kcontrol_new wm8988_monomux_controls = SOC_DAPM_ENUM("Route", monomux); @@ -521,30 +521,30 @@ static inline int get_coeff(int mclk, int rate) /* The set of rates we can generate from the above for each SYSCLK */ -static unsigned int rates_12288[] = { +static const unsigned int rates_12288[] = { 8000, 12000, 16000, 24000, 24000, 32000, 48000, 96000, }; -static struct snd_pcm_hw_constraint_list constraints_12288 = { +static const struct snd_pcm_hw_constraint_list constraints_12288 = { .count = ARRAY_SIZE(rates_12288), .list = rates_12288, }; -static unsigned int rates_112896[] = { +static const unsigned int rates_112896[] = { 8000, 11025, 22050, 44100, }; -static struct snd_pcm_hw_constraint_list constraints_112896 = { +static const struct snd_pcm_hw_constraint_list constraints_112896 = { .count = ARRAY_SIZE(rates_112896), .list = rates_112896, }; -static unsigned int rates_12[] = { +static const unsigned int rates_12[] = { 8000, 11025, 12000, 16000, 22050, 2400, 32000, 41100, 48000, 48000, 88235, 96000, }; -static struct snd_pcm_hw_constraint_list constraints_12 = { +static const struct snd_pcm_hw_constraint_list constraints_12 = { .count = ARRAY_SIZE(rates_12), .list = rates_12, }; @@ -810,16 +810,8 @@ static int wm8988_resume(struct snd_soc_codec *codec) static int wm8988_probe(struct snd_soc_codec *codec) { - struct wm8988_priv *wm8988 = snd_soc_codec_get_drvdata(codec); int ret = 0; - codec->control_data = wm8988->regmap; - ret = snd_soc_codec_set_cache_io(codec, 7, 9, SND_SOC_REGMAP); - if (ret < 0) { - dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); - return ret; - } - ret = wm8988_reset(codec); if (ret < 0) { dev_err(codec->dev, "Failed to issue reset\n"); diff --git a/sound/soc/codecs/wm8990.c b/sound/soc/codecs/wm8990.c index 0ccd4d8d043..c413c199145 100644 --- a/sound/soc/codecs/wm8990.c +++ b/sound/soc/codecs/wm8990.c @@ -157,26 +157,23 @@ static int wm899x_outpga_put_volsw_vu(struct snd_kcontrol *kcontrol, static const char *wm8990_digital_sidetone[] = {"None", "Left ADC", "Right ADC", "Reserved"}; -static const struct soc_enum wm8990_left_digital_sidetone_enum = -SOC_ENUM_SINGLE(WM8990_DIGITAL_SIDE_TONE, - WM8990_ADC_TO_DACL_SHIFT, - WM8990_ADC_TO_DACL_MASK, - wm8990_digital_sidetone); - -static const struct soc_enum wm8990_right_digital_sidetone_enum = -SOC_ENUM_SINGLE(WM8990_DIGITAL_SIDE_TONE, - WM8990_ADC_TO_DACR_SHIFT, - WM8990_ADC_TO_DACR_MASK, - wm8990_digital_sidetone); +static SOC_ENUM_SINGLE_DECL(wm8990_left_digital_sidetone_enum, + WM8990_DIGITAL_SIDE_TONE, + WM8990_ADC_TO_DACL_SHIFT, + wm8990_digital_sidetone); + +static SOC_ENUM_SINGLE_DECL(wm8990_right_digital_sidetone_enum, + WM8990_DIGITAL_SIDE_TONE, + WM8990_ADC_TO_DACR_SHIFT, + wm8990_digital_sidetone); static const char *wm8990_adcmode[] = {"Hi-fi mode", "Voice mode 1", "Voice mode 2", "Voice mode 3"}; -static const struct soc_enum wm8990_right_adcmode_enum = -SOC_ENUM_SINGLE(WM8990_ADC_CTRL, - WM8990_ADC_HPF_CUT_SHIFT, - WM8990_ADC_HPF_CUT_MASK, - wm8990_adcmode); +static SOC_ENUM_SINGLE_DECL(wm8990_right_adcmode_enum, + WM8990_ADC_CTRL, + WM8990_ADC_HPF_CUT_SHIFT, + wm8990_adcmode); static const struct snd_kcontrol_new wm8990_snd_controls[] = { /* INMIXL */ @@ -475,9 +472,9 @@ SOC_DAPM_SINGLE("RINPGA34 Switch", WM8990_INPUT_MIXER3, WM8990_L34MNB_BIT, static const char *wm8990_ainlmux[] = {"INMIXL Mix", "RXVOICE Mix", "DIFFINL Mix"}; -static const struct soc_enum wm8990_ainlmux_enum = -SOC_ENUM_SINGLE(WM8990_INPUT_MIXER1, WM8990_AINLMODE_SHIFT, - ARRAY_SIZE(wm8990_ainlmux), wm8990_ainlmux); +static SOC_ENUM_SINGLE_DECL(wm8990_ainlmux_enum, + WM8990_INPUT_MIXER1, WM8990_AINLMODE_SHIFT, + wm8990_ainlmux); static const struct snd_kcontrol_new wm8990_dapm_ainlmux_controls = SOC_DAPM_ENUM("Route", wm8990_ainlmux_enum); @@ -488,9 +485,9 @@ SOC_DAPM_ENUM("Route", wm8990_ainlmux_enum); static const char *wm8990_ainrmux[] = {"INMIXR Mix", "RXVOICE Mix", "DIFFINR Mix"}; -static const struct soc_enum wm8990_ainrmux_enum = -SOC_ENUM_SINGLE(WM8990_INPUT_MIXER1, WM8990_AINRMODE_SHIFT, - ARRAY_SIZE(wm8990_ainrmux), wm8990_ainrmux); +static SOC_ENUM_SINGLE_DECL(wm8990_ainrmux_enum, + WM8990_INPUT_MIXER1, WM8990_AINRMODE_SHIFT, + wm8990_ainrmux); static const struct snd_kcontrol_new wm8990_dapm_ainrmux_controls = SOC_DAPM_ENUM("Route", wm8990_ainrmux_enum); @@ -1292,14 +1289,6 @@ static int wm8990_resume(struct snd_soc_codec *codec) */ static int wm8990_probe(struct snd_soc_codec *codec) { - int ret; - - ret = snd_soc_codec_set_cache_io(codec, 8, 16, SND_SOC_REGMAP); - if (ret < 0) { - printk(KERN_ERR "wm8990: failed to set cache I/O: %d\n", ret); - return ret; - } - wm8990_reset(codec); /* charge output caps */ diff --git a/sound/soc/codecs/wm8991.c b/sound/soc/codecs/wm8991.c index dba0306c42a..844cc4a60d6 100644 --- a/sound/soc/codecs/wm8991.c +++ b/sound/soc/codecs/wm8991.c @@ -171,26 +171,23 @@ static int wm899x_outpga_put_volsw_vu(struct snd_kcontrol *kcontrol, static const char *wm8991_digital_sidetone[] = {"None", "Left ADC", "Right ADC", "Reserved"}; -static const struct soc_enum wm8991_left_digital_sidetone_enum = - SOC_ENUM_SINGLE(WM8991_DIGITAL_SIDE_TONE, - WM8991_ADC_TO_DACL_SHIFT, - WM8991_ADC_TO_DACL_MASK, - wm8991_digital_sidetone); - -static const struct soc_enum wm8991_right_digital_sidetone_enum = - SOC_ENUM_SINGLE(WM8991_DIGITAL_SIDE_TONE, - WM8991_ADC_TO_DACR_SHIFT, - WM8991_ADC_TO_DACR_MASK, - wm8991_digital_sidetone); +static SOC_ENUM_SINGLE_DECL(wm8991_left_digital_sidetone_enum, + WM8991_DIGITAL_SIDE_TONE, + WM8991_ADC_TO_DACL_SHIFT, + wm8991_digital_sidetone); + +static SOC_ENUM_SINGLE_DECL(wm8991_right_digital_sidetone_enum, + WM8991_DIGITAL_SIDE_TONE, + WM8991_ADC_TO_DACR_SHIFT, + wm8991_digital_sidetone); static const char *wm8991_adcmode[] = {"Hi-fi mode", "Voice mode 1", "Voice mode 2", "Voice mode 3"}; -static const struct soc_enum wm8991_right_adcmode_enum = - SOC_ENUM_SINGLE(WM8991_ADC_CTRL, - WM8991_ADC_HPF_CUT_SHIFT, - WM8991_ADC_HPF_CUT_MASK, - wm8991_adcmode); +static SOC_ENUM_SINGLE_DECL(wm8991_right_adcmode_enum, + WM8991_ADC_CTRL, + WM8991_ADC_HPF_CUT_SHIFT, + wm8991_adcmode); static const struct snd_kcontrol_new wm8991_snd_controls[] = { /* INMIXL */ @@ -486,9 +483,9 @@ static const struct snd_kcontrol_new wm8991_dapm_inmixr_controls[] = { static const char *wm8991_ainlmux[] = {"INMIXL Mix", "RXVOICE Mix", "DIFFINL Mix"}; -static const struct soc_enum wm8991_ainlmux_enum = - SOC_ENUM_SINGLE(WM8991_INPUT_MIXER1, WM8991_AINLMODE_SHIFT, - ARRAY_SIZE(wm8991_ainlmux), wm8991_ainlmux); +static SOC_ENUM_SINGLE_DECL(wm8991_ainlmux_enum, + WM8991_INPUT_MIXER1, WM8991_AINLMODE_SHIFT, + wm8991_ainlmux); static const struct snd_kcontrol_new wm8991_dapm_ainlmux_controls = SOC_DAPM_ENUM("Route", wm8991_ainlmux_enum); @@ -499,9 +496,9 @@ static const struct snd_kcontrol_new wm8991_dapm_ainlmux_controls = static const char *wm8991_ainrmux[] = {"INMIXR Mix", "RXVOICE Mix", "DIFFINR Mix"}; -static const struct soc_enum wm8991_ainrmux_enum = - SOC_ENUM_SINGLE(WM8991_INPUT_MIXER1, WM8991_AINRMODE_SHIFT, - ARRAY_SIZE(wm8991_ainrmux), wm8991_ainrmux); +static SOC_ENUM_SINGLE_DECL(wm8991_ainrmux_enum, + WM8991_INPUT_MIXER1, WM8991_AINRMODE_SHIFT, + wm8991_ainrmux); static const struct snd_kcontrol_new wm8991_dapm_ainrmux_controls = SOC_DAPM_ENUM("Route", wm8991_ainrmux_enum); @@ -1251,17 +1248,6 @@ static int wm8991_remove(struct snd_soc_codec *codec) static int wm8991_probe(struct snd_soc_codec *codec) { - struct wm8991_priv *wm8991; - int ret; - - wm8991 = snd_soc_codec_get_drvdata(codec); - - ret = snd_soc_codec_set_cache_io(codec, 8, 16, SND_SOC_REGMAP); - if (ret < 0) { - dev_err(codec->dev, "Failed to set cache i/o: %d\n", ret); - return ret; - } - wm8991_set_bias_level(codec, SND_SOC_BIAS_STANDBY); return 0; diff --git a/sound/soc/codecs/wm8993.c b/sound/soc/codecs/wm8993.c index 2ee23a39622..f825dc04ebe 100644 --- a/sound/soc/codecs/wm8993.c +++ b/sound/soc/codecs/wm8993.c @@ -646,8 +646,8 @@ static const char *dac_deemph_text[] = { "48kHz", }; -static const struct soc_enum dac_deemph = - SOC_ENUM_SINGLE(WM8993_DAC_CTRL, 4, 4, dac_deemph_text); +static SOC_ENUM_SINGLE_DECL(dac_deemph, + WM8993_DAC_CTRL, 4, dac_deemph_text); static const char *adc_hpf_text[] = { "Hi-Fi", @@ -656,16 +656,16 @@ static const char *adc_hpf_text[] = { "Voice 3", }; -static const struct soc_enum adc_hpf = - SOC_ENUM_SINGLE(WM8993_ADC_CTRL, 5, 4, adc_hpf_text); +static SOC_ENUM_SINGLE_DECL(adc_hpf, + WM8993_ADC_CTRL, 5, adc_hpf_text); static const char *drc_path_text[] = { "ADC", "DAC" }; -static const struct soc_enum drc_path = - SOC_ENUM_SINGLE(WM8993_DRC_CONTROL_1, 14, 2, drc_path_text); +static SOC_ENUM_SINGLE_DECL(drc_path, + WM8993_DRC_CONTROL_1, 14, drc_path_text); static const char *drc_r0_text[] = { "1", @@ -676,8 +676,8 @@ static const char *drc_r0_text[] = { "0", }; -static const struct soc_enum drc_r0 = - SOC_ENUM_SINGLE(WM8993_DRC_CONTROL_3, 8, 6, drc_r0_text); +static SOC_ENUM_SINGLE_DECL(drc_r0, + WM8993_DRC_CONTROL_3, 8, drc_r0_text); static const char *drc_r1_text[] = { "1", @@ -687,8 +687,8 @@ static const char *drc_r1_text[] = { "0", }; -static const struct soc_enum drc_r1 = - SOC_ENUM_SINGLE(WM8993_DRC_CONTROL_4, 13, 5, drc_r1_text); +static SOC_ENUM_SINGLE_DECL(drc_r1, + WM8993_DRC_CONTROL_4, 13, drc_r1_text); static const char *drc_attack_text[] = { "Reserved", @@ -705,8 +705,8 @@ static const char *drc_attack_text[] = { "185.6ms", }; -static const struct soc_enum drc_attack = - SOC_ENUM_SINGLE(WM8993_DRC_CONTROL_2, 12, 12, drc_attack_text); +static SOC_ENUM_SINGLE_DECL(drc_attack, + WM8993_DRC_CONTROL_2, 12, drc_attack_text); static const char *drc_decay_text[] = { "186ms", @@ -720,16 +720,16 @@ static const char *drc_decay_text[] = { "47.56ms", }; -static const struct soc_enum drc_decay = - SOC_ENUM_SINGLE(WM8993_DRC_CONTROL_2, 8, 9, drc_decay_text); +static SOC_ENUM_SINGLE_DECL(drc_decay, + WM8993_DRC_CONTROL_2, 8, drc_decay_text); static const char *drc_ff_text[] = { "5 samples", "9 samples", }; -static const struct soc_enum drc_ff = - SOC_ENUM_SINGLE(WM8993_DRC_CONTROL_3, 7, 2, drc_ff_text); +static SOC_ENUM_SINGLE_DECL(drc_ff, + WM8993_DRC_CONTROL_3, 7, drc_ff_text); static const char *drc_qr_rate_text[] = { "0.725ms", @@ -737,8 +737,8 @@ static const char *drc_qr_rate_text[] = { "5.8ms", }; -static const struct soc_enum drc_qr_rate = - SOC_ENUM_SINGLE(WM8993_DRC_CONTROL_3, 0, 3, drc_qr_rate_text); +static SOC_ENUM_SINGLE_DECL(drc_qr_rate, + WM8993_DRC_CONTROL_3, 0, drc_qr_rate_text); static const char *drc_smooth_text[] = { "Low", @@ -746,8 +746,8 @@ static const char *drc_smooth_text[] = { "High", }; -static const struct soc_enum drc_smooth = - SOC_ENUM_SINGLE(WM8993_DRC_CONTROL_1, 4, 3, drc_smooth_text); +static SOC_ENUM_SINGLE_DECL(drc_smooth, + WM8993_DRC_CONTROL_1, 4, drc_smooth_text); static const struct snd_kcontrol_new wm8993_snd_controls[] = { SOC_DOUBLE_TLV("Digital Sidetone Volume", WM8993_DIGITAL_SIDE_TONE, @@ -841,26 +841,26 @@ static const char *aif_text[] = { "Left", "Right" }; -static const struct soc_enum aifoutl_enum = - SOC_ENUM_SINGLE(WM8993_AUDIO_INTERFACE_1, 15, 2, aif_text); +static SOC_ENUM_SINGLE_DECL(aifoutl_enum, + WM8993_AUDIO_INTERFACE_1, 15, aif_text); static const struct snd_kcontrol_new aifoutl_mux = SOC_DAPM_ENUM("AIFOUTL Mux", aifoutl_enum); -static const struct soc_enum aifoutr_enum = - SOC_ENUM_SINGLE(WM8993_AUDIO_INTERFACE_1, 14, 2, aif_text); +static SOC_ENUM_SINGLE_DECL(aifoutr_enum, + WM8993_AUDIO_INTERFACE_1, 14, aif_text); static const struct snd_kcontrol_new aifoutr_mux = SOC_DAPM_ENUM("AIFOUTR Mux", aifoutr_enum); -static const struct soc_enum aifinl_enum = - SOC_ENUM_SINGLE(WM8993_AUDIO_INTERFACE_2, 15, 2, aif_text); +static SOC_ENUM_SINGLE_DECL(aifinl_enum, + WM8993_AUDIO_INTERFACE_2, 15, aif_text); static const struct snd_kcontrol_new aifinl_mux = SOC_DAPM_ENUM("AIFINL Mux", aifinl_enum); -static const struct soc_enum aifinr_enum = - SOC_ENUM_SINGLE(WM8993_AUDIO_INTERFACE_2, 14, 2, aif_text); +static SOC_ENUM_SINGLE_DECL(aifinr_enum, + WM8993_AUDIO_INTERFACE_2, 14, aif_text); static const struct snd_kcontrol_new aifinr_mux = SOC_DAPM_ENUM("AIFINR Mux", aifinr_enum); @@ -869,14 +869,14 @@ static const char *sidetone_text[] = { "None", "Left", "Right" }; -static const struct soc_enum sidetonel_enum = - SOC_ENUM_SINGLE(WM8993_DIGITAL_SIDE_TONE, 2, 3, sidetone_text); +static SOC_ENUM_SINGLE_DECL(sidetonel_enum, + WM8993_DIGITAL_SIDE_TONE, 2, sidetone_text); static const struct snd_kcontrol_new sidetonel_mux = SOC_DAPM_ENUM("Left Sidetone", sidetonel_enum); -static const struct soc_enum sidetoner_enum = - SOC_ENUM_SINGLE(WM8993_DIGITAL_SIDE_TONE, 0, 3, sidetone_text); +static SOC_ENUM_SINGLE_DECL(sidetoner_enum, + WM8993_DIGITAL_SIDE_TONE, 0, sidetone_text); static const struct snd_kcontrol_new sidetoner_mux = SOC_DAPM_ENUM("Right Sidetone", sidetoner_enum); @@ -1493,13 +1493,6 @@ static int wm8993_probe(struct snd_soc_codec *codec) wm8993->hubs_data.dcs_codes_r = -2; wm8993->hubs_data.series_startup = 1; - codec->control_data = wm8993->regmap; - ret = snd_soc_codec_set_cache_io(codec, 8, 16, SND_SOC_REGMAP); - if (ret != 0) { - dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); - return ret; - } - /* Latch volume update bits and default ZC on */ snd_soc_update_bits(codec, WM8993_RIGHT_DAC_DIGITAL_VOLUME, WM8993_DAC_VU, WM8993_DAC_VU); @@ -1559,8 +1552,6 @@ static int wm8993_probe(struct snd_soc_codec *codec) static int wm8993_remove(struct snd_soc_codec *codec) { - struct wm8993_priv *wm8993 = snd_soc_codec_get_drvdata(codec); - wm8993_set_bias_level(codec, SND_SOC_BIAS_OFF); return 0; } diff --git a/sound/soc/codecs/wm8994.c b/sound/soc/codecs/wm8994.c index adb72063d44..6303537f54c 100644 --- a/sound/soc/codecs/wm8994.c +++ b/sound/soc/codecs/wm8994.c @@ -1344,8 +1344,7 @@ static const char *adc_mux_text[] = { "DMIC", }; -static SOC_ENUM_SINGLE_DECL(adc_enum, - 0, 0, adc_mux_text); +static SOC_ENUM_SINGLE_VIRT_DECL(adc_enum, adc_mux_text); static const struct snd_kcontrol_new adcl_mux = SOC_DAPM_ENUM_VIRT("ADCL Mux", adc_enum); @@ -2554,43 +2553,52 @@ static int wm8994_set_bias_level(struct snd_soc_codec *codec, int wm8994_vmid_mode(struct snd_soc_codec *codec, enum wm8994_vmid_mode mode) { struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec); + struct snd_soc_dapm_context *dapm = &codec->dapm; switch (mode) { case WM8994_VMID_NORMAL: + snd_soc_dapm_mutex_lock(dapm); + if (wm8994->hubs.lineout1_se) { - snd_soc_dapm_disable_pin(&codec->dapm, - "LINEOUT1N Driver"); - snd_soc_dapm_disable_pin(&codec->dapm, - "LINEOUT1P Driver"); + snd_soc_dapm_disable_pin_unlocked(dapm, + "LINEOUT1N Driver"); + snd_soc_dapm_disable_pin_unlocked(dapm, + "LINEOUT1P Driver"); } if (wm8994->hubs.lineout2_se) { - snd_soc_dapm_disable_pin(&codec->dapm, - "LINEOUT2N Driver"); - snd_soc_dapm_disable_pin(&codec->dapm, - "LINEOUT2P Driver"); + snd_soc_dapm_disable_pin_unlocked(dapm, + "LINEOUT2N Driver"); + snd_soc_dapm_disable_pin_unlocked(dapm, + "LINEOUT2P Driver"); } /* Do the sync with the old mode to allow it to clean up */ - snd_soc_dapm_sync(&codec->dapm); + snd_soc_dapm_sync_unlocked(dapm); wm8994->vmid_mode = mode; + + snd_soc_dapm_mutex_unlock(dapm); break; case WM8994_VMID_FORCE: + snd_soc_dapm_mutex_lock(dapm); + if (wm8994->hubs.lineout1_se) { - snd_soc_dapm_force_enable_pin(&codec->dapm, - "LINEOUT1N Driver"); - snd_soc_dapm_force_enable_pin(&codec->dapm, - "LINEOUT1P Driver"); + snd_soc_dapm_force_enable_pin_unlocked(dapm, + "LINEOUT1N Driver"); + snd_soc_dapm_force_enable_pin_unlocked(dapm, + "LINEOUT1P Driver"); } if (wm8994->hubs.lineout2_se) { - snd_soc_dapm_force_enable_pin(&codec->dapm, - "LINEOUT2N Driver"); - snd_soc_dapm_force_enable_pin(&codec->dapm, - "LINEOUT2P Driver"); + snd_soc_dapm_force_enable_pin_unlocked(dapm, + "LINEOUT2N Driver"); + snd_soc_dapm_force_enable_pin_unlocked(dapm, + "LINEOUT2P Driver"); } wm8994->vmid_mode = mode; - snd_soc_dapm_sync(&codec->dapm); + snd_soc_dapm_sync_unlocked(dapm); + + snd_soc_dapm_mutex_unlock(dapm); break; default: @@ -3242,7 +3250,7 @@ static void wm8994_handle_retune_mobile_pdata(struct wm8994_priv *wm8994) dev_dbg(codec->dev, "Allocated %d unique ReTune Mobile names\n", wm8994->num_retune_mobile_texts); - wm8994->retune_mobile_enum.max = wm8994->num_retune_mobile_texts; + wm8994->retune_mobile_enum.items = wm8994->num_retune_mobile_texts; wm8994->retune_mobile_enum.texts = wm8994->retune_mobile_texts; ret = snd_soc_add_codec_controls(wm8994->hubs.codec, controls, @@ -3298,7 +3306,7 @@ static void wm8994_handle_pdata(struct wm8994_priv *wm8994) for (i = 0; i < pdata->num_drc_cfgs; i++) wm8994->drc_texts[i] = pdata->drc_cfgs[i].name; - wm8994->drc_enum.max = pdata->num_drc_cfgs; + wm8994->drc_enum.items = pdata->num_drc_cfgs; wm8994->drc_enum.texts = wm8994->drc_texts; ret = snd_soc_add_codec_controls(wm8994->hubs.codec, controls, @@ -3990,9 +3998,8 @@ static int wm8994_codec_probe(struct snd_soc_codec *codec) int ret, i; wm8994->hubs.codec = codec; - codec->control_data = control->regmap; - snd_soc_codec_set_cache_io(codec, 16, 16, SND_SOC_REGMAP); + snd_soc_codec_set_cache_io(codec, control->regmap); mutex_init(&wm8994->accdet_lock); INIT_DELAYED_WORK(&wm8994->jackdet_bootstrap, diff --git a/sound/soc/codecs/wm8995.c b/sound/soc/codecs/wm8995.c index 4300caff178..d3152cf5bd5 100644 --- a/sound/soc/codecs/wm8995.c +++ b/sound/soc/codecs/wm8995.c @@ -423,24 +423,24 @@ static const char *in1l_text[] = { "Differential", "Single-ended IN1LN", "Single-ended IN1LP" }; -static const SOC_ENUM_SINGLE_DECL(in1l_enum, WM8995_LEFT_LINE_INPUT_CONTROL, - 2, in1l_text); +static SOC_ENUM_SINGLE_DECL(in1l_enum, WM8995_LEFT_LINE_INPUT_CONTROL, + 2, in1l_text); static const char *in1r_text[] = { "Differential", "Single-ended IN1RN", "Single-ended IN1RP" }; -static const SOC_ENUM_SINGLE_DECL(in1r_enum, WM8995_LEFT_LINE_INPUT_CONTROL, - 0, in1r_text); +static SOC_ENUM_SINGLE_DECL(in1r_enum, WM8995_LEFT_LINE_INPUT_CONTROL, + 0, in1r_text); static const char *dmic_src_text[] = { "DMICDAT1", "DMICDAT2", "DMICDAT3" }; -static const SOC_ENUM_SINGLE_DECL(dmic_src1_enum, WM8995_POWER_MANAGEMENT_5, - 8, dmic_src_text); -static const SOC_ENUM_SINGLE_DECL(dmic_src2_enum, WM8995_POWER_MANAGEMENT_5, - 6, dmic_src_text); +static SOC_ENUM_SINGLE_DECL(dmic_src1_enum, WM8995_POWER_MANAGEMENT_5, + 8, dmic_src_text); +static SOC_ENUM_SINGLE_DECL(dmic_src2_enum, WM8995_POWER_MANAGEMENT_5, + 6, dmic_src_text); static const struct snd_kcontrol_new wm8995_snd_controls[] = { SOC_DOUBLE_R_TLV("DAC1 Volume", WM8995_DAC1_LEFT_VOLUME, @@ -561,10 +561,8 @@ static int hp_supply_event(struct snd_soc_dapm_widget *w, struct snd_kcontrol *kcontrol, int event) { struct snd_soc_codec *codec; - struct wm8995_priv *wm8995; codec = w->codec; - wm8995 = snd_soc_codec_get_drvdata(codec); switch (event) { case SND_SOC_DAPM_PRE_PMU: @@ -783,14 +781,12 @@ static const char *sidetone_text[] = { "ADC/DMIC1", "DMIC2", }; -static const struct soc_enum sidetone1_enum = - SOC_ENUM_SINGLE(WM8995_SIDETONE, 0, 2, sidetone_text); +static SOC_ENUM_SINGLE_DECL(sidetone1_enum, WM8995_SIDETONE, 0, sidetone_text); static const struct snd_kcontrol_new sidetone1_mux = SOC_DAPM_ENUM("Left Sidetone Mux", sidetone1_enum); -static const struct soc_enum sidetone2_enum = - SOC_ENUM_SINGLE(WM8995_SIDETONE, 1, 2, sidetone_text); +static SOC_ENUM_SINGLE_DECL(sidetone2_enum, WM8995_SIDETONE, 1, sidetone_text); static const struct snd_kcontrol_new sidetone2_mux = SOC_DAPM_ENUM("Right Sidetone Mux", sidetone2_enum); @@ -886,8 +882,7 @@ static const char *adc_mux_text[] = { "DMIC", }; -static const struct soc_enum adc_enum = - SOC_ENUM_SINGLE(0, 0, 2, adc_mux_text); +static SOC_ENUM_SINGLE_VIRT_DECL(adc_enum, adc_mux_text); static const struct snd_kcontrol_new adcl_mux = SOC_DAPM_ENUM_VIRT("ADCL Mux", adc_enum); @@ -899,14 +894,14 @@ static const char *spk_src_text[] = { "DAC1L", "DAC1R", "DAC2L", "DAC2R" }; -static const SOC_ENUM_SINGLE_DECL(spk1l_src_enum, WM8995_LEFT_PDM_SPEAKER_1, - 0, spk_src_text); -static const SOC_ENUM_SINGLE_DECL(spk1r_src_enum, WM8995_RIGHT_PDM_SPEAKER_1, - 0, spk_src_text); -static const SOC_ENUM_SINGLE_DECL(spk2l_src_enum, WM8995_LEFT_PDM_SPEAKER_2, - 0, spk_src_text); -static const SOC_ENUM_SINGLE_DECL(spk2r_src_enum, WM8995_RIGHT_PDM_SPEAKER_2, - 0, spk_src_text); +static SOC_ENUM_SINGLE_DECL(spk1l_src_enum, WM8995_LEFT_PDM_SPEAKER_1, + 0, spk_src_text); +static SOC_ENUM_SINGLE_DECL(spk1r_src_enum, WM8995_RIGHT_PDM_SPEAKER_1, + 0, spk_src_text); +static SOC_ENUM_SINGLE_DECL(spk2l_src_enum, WM8995_LEFT_PDM_SPEAKER_2, + 0, spk_src_text); +static SOC_ENUM_SINGLE_DECL(spk2r_src_enum, WM8995_RIGHT_PDM_SPEAKER_2, + 0, spk_src_text); static const struct snd_kcontrol_new spk1l_mux = SOC_DAPM_ENUM("SPK1L SRC", spk1l_src_enum); @@ -2047,13 +2042,6 @@ static int wm8995_probe(struct snd_soc_codec *codec) wm8995 = snd_soc_codec_get_drvdata(codec); wm8995->codec = codec; - codec->control_data = wm8995->regmap; - ret = snd_soc_codec_set_cache_io(codec, 16, 16, SND_SOC_REGMAP); - if (ret < 0) { - dev_err(codec->dev, "Failed to set cache i/o: %d\n", ret); - return ret; - } - for (i = 0; i < ARRAY_SIZE(wm8995->supplies); i++) wm8995->supplies[i].supply = wm8995_supply_names[i]; diff --git a/sound/soc/codecs/wm8996.c b/sound/soc/codecs/wm8996.c index 1a7655b0aa2..c6cbb3b8ace 100644 --- a/sound/soc/codecs/wm8996.c +++ b/sound/soc/codecs/wm8996.c @@ -311,28 +311,28 @@ static const char *sidetone_hpf_text[] = { "2.9kHz", "1.5kHz", "735Hz", "403Hz", "196Hz", "98Hz", "49Hz" }; -static const struct soc_enum sidetone_hpf = - SOC_ENUM_SINGLE(WM8996_SIDETONE, 7, 7, sidetone_hpf_text); +static SOC_ENUM_SINGLE_DECL(sidetone_hpf, + WM8996_SIDETONE, 7, sidetone_hpf_text); static const char *hpf_mode_text[] = { "HiFi", "Custom", "Voice" }; -static const struct soc_enum dsp1tx_hpf_mode = - SOC_ENUM_SINGLE(WM8996_DSP1_TX_FILTERS, 3, 3, hpf_mode_text); +static SOC_ENUM_SINGLE_DECL(dsp1tx_hpf_mode, + WM8996_DSP1_TX_FILTERS, 3, hpf_mode_text); -static const struct soc_enum dsp2tx_hpf_mode = - SOC_ENUM_SINGLE(WM8996_DSP2_TX_FILTERS, 3, 3, hpf_mode_text); +static SOC_ENUM_SINGLE_DECL(dsp2tx_hpf_mode, + WM8996_DSP2_TX_FILTERS, 3, hpf_mode_text); static const char *hpf_cutoff_text[] = { "50Hz", "75Hz", "100Hz", "150Hz", "200Hz", "300Hz", "400Hz" }; -static const struct soc_enum dsp1tx_hpf_cutoff = - SOC_ENUM_SINGLE(WM8996_DSP1_TX_FILTERS, 0, 7, hpf_cutoff_text); +static SOC_ENUM_SINGLE_DECL(dsp1tx_hpf_cutoff, + WM8996_DSP1_TX_FILTERS, 0, hpf_cutoff_text); -static const struct soc_enum dsp2tx_hpf_cutoff = - SOC_ENUM_SINGLE(WM8996_DSP2_TX_FILTERS, 0, 7, hpf_cutoff_text); +static SOC_ENUM_SINGLE_DECL(dsp2tx_hpf_cutoff, + WM8996_DSP2_TX_FILTERS, 0, hpf_cutoff_text); static void wm8996_set_retune_mobile(struct snd_soc_codec *codec, int block) { @@ -780,14 +780,14 @@ static const char *sidetone_text[] = { "IN1", "IN2", }; -static const struct soc_enum left_sidetone_enum = - SOC_ENUM_SINGLE(WM8996_SIDETONE, 0, 2, sidetone_text); +static SOC_ENUM_SINGLE_DECL(left_sidetone_enum, + WM8996_SIDETONE, 0, sidetone_text); static const struct snd_kcontrol_new left_sidetone = SOC_DAPM_ENUM("Left Sidetone", left_sidetone_enum); -static const struct soc_enum right_sidetone_enum = - SOC_ENUM_SINGLE(WM8996_SIDETONE, 1, 2, sidetone_text); +static SOC_ENUM_SINGLE_DECL(right_sidetone_enum, + WM8996_SIDETONE, 1, sidetone_text); static const struct snd_kcontrol_new right_sidetone = SOC_DAPM_ENUM("Right Sidetone", right_sidetone_enum); @@ -796,14 +796,14 @@ static const char *spk_text[] = { "DAC1L", "DAC1R", "DAC2L", "DAC2R" }; -static const struct soc_enum spkl_enum = - SOC_ENUM_SINGLE(WM8996_LEFT_PDM_SPEAKER, 0, 4, spk_text); +static SOC_ENUM_SINGLE_DECL(spkl_enum, + WM8996_LEFT_PDM_SPEAKER, 0, spk_text); static const struct snd_kcontrol_new spkl_mux = SOC_DAPM_ENUM("SPKL", spkl_enum); -static const struct soc_enum spkr_enum = - SOC_ENUM_SINGLE(WM8996_RIGHT_PDM_SPEAKER, 0, 4, spk_text); +static SOC_ENUM_SINGLE_DECL(spkr_enum, + WM8996_RIGHT_PDM_SPEAKER, 0, spk_text); static const struct snd_kcontrol_new spkr_mux = SOC_DAPM_ENUM("SPKR", spkr_enum); @@ -812,8 +812,8 @@ static const char *dsp1rx_text[] = { "AIF1", "AIF2" }; -static const struct soc_enum dsp1rx_enum = - SOC_ENUM_SINGLE(WM8996_POWER_MANAGEMENT_8, 0, 2, dsp1rx_text); +static SOC_ENUM_SINGLE_DECL(dsp1rx_enum, + WM8996_POWER_MANAGEMENT_8, 0, dsp1rx_text); static const struct snd_kcontrol_new dsp1rx = SOC_DAPM_ENUM("DSP1RX", dsp1rx_enum); @@ -822,8 +822,8 @@ static const char *dsp2rx_text[] = { "AIF2", "AIF1" }; -static const struct soc_enum dsp2rx_enum = - SOC_ENUM_SINGLE(WM8996_POWER_MANAGEMENT_8, 4, 2, dsp2rx_text); +static SOC_ENUM_SINGLE_DECL(dsp2rx_enum, + WM8996_POWER_MANAGEMENT_8, 4, dsp2rx_text); static const struct snd_kcontrol_new dsp2rx = SOC_DAPM_ENUM("DSP2RX", dsp2rx_enum); @@ -832,8 +832,8 @@ static const char *aif2tx_text[] = { "DSP2", "DSP1", "AIF1" }; -static const struct soc_enum aif2tx_enum = - SOC_ENUM_SINGLE(WM8996_POWER_MANAGEMENT_8, 6, 3, aif2tx_text); +static SOC_ENUM_SINGLE_DECL(aif2tx_enum, + WM8996_POWER_MANAGEMENT_8, 6, aif2tx_text); static const struct snd_kcontrol_new aif2tx = SOC_DAPM_ENUM("AIF2TX", aif2tx_enum); @@ -842,14 +842,14 @@ static const char *inmux_text[] = { "ADC", "DMIC1", "DMIC2" }; -static const struct soc_enum in1_enum = - SOC_ENUM_SINGLE(WM8996_POWER_MANAGEMENT_7, 0, 3, inmux_text); +static SOC_ENUM_SINGLE_DECL(in1_enum, + WM8996_POWER_MANAGEMENT_7, 0, inmux_text); static const struct snd_kcontrol_new in1_mux = SOC_DAPM_ENUM("IN1 Mux", in1_enum); -static const struct soc_enum in2_enum = - SOC_ENUM_SINGLE(WM8996_POWER_MANAGEMENT_7, 4, 3, inmux_text); +static SOC_ENUM_SINGLE_DECL(in2_enum, + WM8996_POWER_MANAGEMENT_7, 4, inmux_text); static const struct snd_kcontrol_new in2_mux = SOC_DAPM_ENUM("IN2 Mux", in2_enum); @@ -1608,8 +1608,8 @@ static int wm8996_set_bias_level(struct snd_soc_codec *codec, msleep(5); } - regcache_cache_only(codec->control_data, false); - regcache_sync(codec->control_data); + regcache_cache_only(wm8996->regmap, false); + regcache_sync(wm8996->regmap); } /* Bypass the MICBIASes for lowest power */ @@ -1620,10 +1620,10 @@ static int wm8996_set_bias_level(struct snd_soc_codec *codec, break; case SND_SOC_BIAS_OFF: - regcache_cache_only(codec->control_data, true); + regcache_cache_only(wm8996->regmap, true); if (wm8996->pdata.ldo_ena >= 0) { gpio_set_value_cansleep(wm8996->pdata.ldo_ena, 0); - regcache_cache_only(codec->control_data, true); + regcache_cache_only(wm8996->regmap, true); } regulator_bulk_disable(ARRAY_SIZE(wm8996->supplies), wm8996->supplies); @@ -2251,6 +2251,7 @@ int wm8996_detect(struct snd_soc_codec *codec, struct snd_soc_jack *jack, wm8996_polarity_fn polarity_cb) { struct wm8996_priv *wm8996 = snd_soc_codec_get_drvdata(codec); + struct snd_soc_dapm_context *dapm = &codec->dapm; wm8996->jack = jack; wm8996->detecting = true; @@ -2267,8 +2268,12 @@ int wm8996_detect(struct snd_soc_codec *codec, struct snd_soc_jack *jack, WM8996_MICB2_DISCH, 0); /* LDO2 powers the microphones, SYSCLK clocks detection */ - snd_soc_dapm_force_enable_pin(&codec->dapm, "LDO2"); - snd_soc_dapm_force_enable_pin(&codec->dapm, "SYSCLK"); + snd_soc_dapm_mutex_lock(dapm); + + snd_soc_dapm_force_enable_pin_unlocked(dapm, "LDO2"); + snd_soc_dapm_force_enable_pin_unlocked(dapm, "SYSCLK"); + + snd_soc_dapm_mutex_unlock(dapm); /* We start off just enabling microphone detection - even a * plain headphone will trigger detection. @@ -2595,7 +2600,7 @@ static void wm8996_retune_mobile_pdata(struct snd_soc_codec *codec) dev_dbg(codec->dev, "Allocated %d unique ReTune Mobile names\n", wm8996->num_retune_mobile_texts); - wm8996->retune_mobile_enum.max = wm8996->num_retune_mobile_texts; + wm8996->retune_mobile_enum.items = wm8996->num_retune_mobile_texts; wm8996->retune_mobile_enum.texts = wm8996->retune_mobile_texts; ret = snd_soc_add_codec_controls(codec, controls, ARRAY_SIZE(controls)); @@ -2628,14 +2633,6 @@ static int wm8996_probe(struct snd_soc_codec *codec) init_completion(&wm8996->dcs_done); init_completion(&wm8996->fll_lock); - codec->control_data = wm8996->regmap; - - ret = snd_soc_codec_set_cache_io(codec, 16, 16, SND_SOC_REGMAP); - if (ret != 0) { - dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); - goto err; - } - if (wm8996->pdata.num_retune_mobile_cfgs) wm8996_retune_mobile_pdata(codec); else @@ -2674,13 +2671,11 @@ static int wm8996_probe(struct snd_soc_codec *codec) } else { dev_err(codec->dev, "Failed to request IRQ: %d\n", ret); + return ret; } } return 0; - -err: - return ret; } static int wm8996_remove(struct snd_soc_codec *codec) diff --git a/sound/soc/codecs/wm8997.c b/sound/soc/codecs/wm8997.c index 555115ee215..004186b6bd4 100644 --- a/sound/soc/codecs/wm8997.c +++ b/sound/soc/codecs/wm8997.c @@ -86,7 +86,7 @@ static int wm8997_sysclk_ev(struct snd_soc_dapm_widget *w, { struct snd_soc_codec *codec = w->codec; struct arizona *arizona = dev_get_drvdata(codec->dev->parent); - struct regmap *regmap = codec->control_data; + struct regmap *regmap = arizona->regmap; const struct reg_default *patch = NULL; int i, patch_size; @@ -123,10 +123,12 @@ static const unsigned int wm8997_osr_val[] = { static const struct soc_enum wm8997_hpout_osr[] = { SOC_VALUE_ENUM_SINGLE(ARIZONA_OUTPUT_PATH_CONFIG_1L, - ARIZONA_OUT1_OSR_SHIFT, 0x7, 3, + ARIZONA_OUT1_OSR_SHIFT, 0x7, + ARRAY_SIZE(wm8997_osr_text), wm8997_osr_text, wm8997_osr_val), SOC_VALUE_ENUM_SINGLE(ARIZONA_OUTPUT_PATH_CONFIG_3L, - ARIZONA_OUT3_OSR_SHIFT, 0x7, 3, + ARIZONA_OUT3_OSR_SHIFT, 0x7, + ARRAY_SIZE(wm8997_osr_text), wm8997_osr_text, wm8997_osr_val), }; @@ -170,15 +172,8 @@ ARIZONA_MIXER_CONTROLS("EQ2", ARIZONA_EQ2MIX_INPUT_1_SOURCE), ARIZONA_MIXER_CONTROLS("EQ3", ARIZONA_EQ3MIX_INPUT_1_SOURCE), ARIZONA_MIXER_CONTROLS("EQ4", ARIZONA_EQ4MIX_INPUT_1_SOURCE), -SND_SOC_BYTES_MASK("EQ1 Coefficients", ARIZONA_EQ1_1, 21, - ARIZONA_EQ1_ENA_MASK), -SND_SOC_BYTES_MASK("EQ2 Coefficients", ARIZONA_EQ2_1, 21, - ARIZONA_EQ2_ENA_MASK), -SND_SOC_BYTES_MASK("EQ3 Coefficients", ARIZONA_EQ3_1, 21, - ARIZONA_EQ3_ENA_MASK), -SND_SOC_BYTES_MASK("EQ4 Coefficients", ARIZONA_EQ4_1, 21, - ARIZONA_EQ4_ENA_MASK), - +SND_SOC_BYTES("EQ1 Coefficients", ARIZONA_EQ1_3, 19), +SOC_SINGLE("EQ1 Mode Switch", ARIZONA_EQ1_2, ARIZONA_EQ1_B1_MODE, 1, 0), SOC_SINGLE_TLV("EQ1 B1 Volume", ARIZONA_EQ1_1, ARIZONA_EQ1_B1_GAIN_SHIFT, 24, 0, eq_tlv), SOC_SINGLE_TLV("EQ1 B2 Volume", ARIZONA_EQ1_1, ARIZONA_EQ1_B2_GAIN_SHIFT, @@ -190,6 +185,8 @@ SOC_SINGLE_TLV("EQ1 B4 Volume", ARIZONA_EQ1_2, ARIZONA_EQ1_B4_GAIN_SHIFT, SOC_SINGLE_TLV("EQ1 B5 Volume", ARIZONA_EQ1_2, ARIZONA_EQ1_B5_GAIN_SHIFT, 24, 0, eq_tlv), +SND_SOC_BYTES("EQ2 Coefficients", ARIZONA_EQ2_3, 19), +SOC_SINGLE("EQ2 Mode Switch", ARIZONA_EQ2_2, ARIZONA_EQ2_B1_MODE, 1, 0), SOC_SINGLE_TLV("EQ2 B1 Volume", ARIZONA_EQ2_1, ARIZONA_EQ2_B1_GAIN_SHIFT, 24, 0, eq_tlv), SOC_SINGLE_TLV("EQ2 B2 Volume", ARIZONA_EQ2_1, ARIZONA_EQ2_B2_GAIN_SHIFT, @@ -201,6 +198,8 @@ SOC_SINGLE_TLV("EQ2 B4 Volume", ARIZONA_EQ2_2, ARIZONA_EQ2_B4_GAIN_SHIFT, SOC_SINGLE_TLV("EQ2 B5 Volume", ARIZONA_EQ2_2, ARIZONA_EQ2_B5_GAIN_SHIFT, 24, 0, eq_tlv), +SND_SOC_BYTES("EQ3 Coefficients", ARIZONA_EQ3_3, 19), +SOC_SINGLE("EQ3 Mode Switch", ARIZONA_EQ3_2, ARIZONA_EQ3_B1_MODE, 1, 0), SOC_SINGLE_TLV("EQ3 B1 Volume", ARIZONA_EQ3_1, ARIZONA_EQ3_B1_GAIN_SHIFT, 24, 0, eq_tlv), SOC_SINGLE_TLV("EQ3 B2 Volume", ARIZONA_EQ3_1, ARIZONA_EQ3_B2_GAIN_SHIFT, @@ -212,6 +211,8 @@ SOC_SINGLE_TLV("EQ3 B4 Volume", ARIZONA_EQ3_2, ARIZONA_EQ3_B4_GAIN_SHIFT, SOC_SINGLE_TLV("EQ3 B5 Volume", ARIZONA_EQ3_2, ARIZONA_EQ3_B5_GAIN_SHIFT, 24, 0, eq_tlv), +SND_SOC_BYTES("EQ4 Coefficients", ARIZONA_EQ4_3, 19), +SOC_SINGLE("EQ4 Mode Switch", ARIZONA_EQ4_2, ARIZONA_EQ4_B1_MODE, 1, 0), SOC_SINGLE_TLV("EQ4 B1 Volume", ARIZONA_EQ4_1, ARIZONA_EQ4_B1_GAIN_SHIFT, 24, 0, eq_tlv), SOC_SINGLE_TLV("EQ4 B2 Volume", ARIZONA_EQ4_1, ARIZONA_EQ4_B2_GAIN_SHIFT, @@ -1052,9 +1053,7 @@ static int wm8997_codec_probe(struct snd_soc_codec *codec) struct wm8997_priv *priv = snd_soc_codec_get_drvdata(codec); int ret; - codec->control_data = priv->core.arizona->regmap; - - ret = snd_soc_codec_set_cache_io(codec, 32, 16, SND_SOC_REGMAP); + ret = snd_soc_codec_set_cache_io(codec, priv->core.arizona->regmap); if (ret != 0) return ret; diff --git a/sound/soc/codecs/wm9081.c b/sound/soc/codecs/wm9081.c index 0982c1d38ec..d18eff31fbb 100644 --- a/sound/soc/codecs/wm9081.c +++ b/sound/soc/codecs/wm9081.c @@ -268,8 +268,7 @@ static const char *drc_high_text[] = { "0", }; -static const struct soc_enum drc_high = - SOC_ENUM_SINGLE(WM9081_DRC_3, 3, 6, drc_high_text); +static SOC_ENUM_SINGLE_DECL(drc_high, WM9081_DRC_3, 3, drc_high_text); static const char *drc_low_text[] = { "1", @@ -279,8 +278,7 @@ static const char *drc_low_text[] = { "0", }; -static const struct soc_enum drc_low = - SOC_ENUM_SINGLE(WM9081_DRC_3, 0, 5, drc_low_text); +static SOC_ENUM_SINGLE_DECL(drc_low, WM9081_DRC_3, 0, drc_low_text); static const char *drc_atk_text[] = { "181us", @@ -297,8 +295,7 @@ static const char *drc_atk_text[] = { "185.6ms", }; -static const struct soc_enum drc_atk = - SOC_ENUM_SINGLE(WM9081_DRC_2, 12, 12, drc_atk_text); +static SOC_ENUM_SINGLE_DECL(drc_atk, WM9081_DRC_2, 12, drc_atk_text); static const char *drc_dcy_text[] = { "186ms", @@ -312,8 +309,7 @@ static const char *drc_dcy_text[] = { "47.56s", }; -static const struct soc_enum drc_dcy = - SOC_ENUM_SINGLE(WM9081_DRC_2, 8, 9, drc_dcy_text); +static SOC_ENUM_SINGLE_DECL(drc_dcy, WM9081_DRC_2, 8, drc_dcy_text); static const char *drc_qr_dcy_text[] = { "0.725ms", @@ -321,8 +317,7 @@ static const char *drc_qr_dcy_text[] = { "5.8ms", }; -static const struct soc_enum drc_qr_dcy = - SOC_ENUM_SINGLE(WM9081_DRC_2, 4, 3, drc_qr_dcy_text); +static SOC_ENUM_SINGLE_DECL(drc_qr_dcy, WM9081_DRC_2, 4, drc_qr_dcy_text); static const char *dac_deemph_text[] = { "None", @@ -331,16 +326,16 @@ static const char *dac_deemph_text[] = { "48kHz", }; -static const struct soc_enum dac_deemph = - SOC_ENUM_SINGLE(WM9081_DAC_DIGITAL_2, 1, 4, dac_deemph_text); +static SOC_ENUM_SINGLE_DECL(dac_deemph, WM9081_DAC_DIGITAL_2, 1, + dac_deemph_text); static const char *speaker_mode_text[] = { "Class D", "Class AB", }; -static const struct soc_enum speaker_mode = - SOC_ENUM_SINGLE(WM9081_ANALOGUE_SPEAKER_2, 6, 2, speaker_mode_text); +static SOC_ENUM_SINGLE_DECL(speaker_mode, WM9081_ANALOGUE_SPEAKER_2, 6, + speaker_mode_text); static int speaker_mode_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) @@ -1265,15 +1260,6 @@ static struct snd_soc_dai_driver wm9081_dai = { static int wm9081_probe(struct snd_soc_codec *codec) { struct wm9081_priv *wm9081 = snd_soc_codec_get_drvdata(codec); - int ret; - - codec->control_data = wm9081->regmap; - - ret = snd_soc_codec_set_cache_io(codec, 8, 16, SND_SOC_REGMAP); - if (ret != 0) { - dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); - return ret; - } /* Enable zero cross by default */ snd_soc_update_bits(codec, WM9081_ANALOGUE_LINEOUT, @@ -1288,7 +1274,7 @@ static int wm9081_probe(struct snd_soc_codec *codec) ARRAY_SIZE(wm9081_eq_controls)); } - return ret; + return 0; } static int wm9081_remove(struct snd_soc_codec *codec) diff --git a/sound/soc/codecs/wm9090.c b/sound/soc/codecs/wm9090.c index a07fe1618ee..87934171f06 100644 --- a/sound/soc/codecs/wm9090.c +++ b/sound/soc/codecs/wm9090.c @@ -522,16 +522,6 @@ static int wm9090_set_bias_level(struct snd_soc_codec *codec, static int wm9090_probe(struct snd_soc_codec *codec) { - struct wm9090_priv *wm9090 = dev_get_drvdata(codec->dev); - int ret; - - codec->control_data = wm9090->regmap; - ret = snd_soc_codec_set_cache_io(codec, 8, 16, SND_SOC_REGMAP); - if (ret != 0) { - dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); - return ret; - } - /* Configure some defaults; they will be written out when we * bring the bias up. */ diff --git a/sound/soc/codecs/wm9705.c b/sound/soc/codecs/wm9705.c index 70ce6793c5b..c0b7f45dfa3 100644 --- a/sound/soc/codecs/wm9705.c +++ b/sound/soc/codecs/wm9705.c @@ -67,12 +67,12 @@ static const char *wm9705_mic[] = {"Mic 1", "Mic 2"}; static const char *wm9705_rec_sel[] = {"Mic", "CD", "NC", "NC", "Line", "Stereo Mix", "Mono Mix", "Phone"}; -static const struct soc_enum wm9705_enum_mic = - SOC_ENUM_SINGLE(AC97_GENERAL_PURPOSE, 8, 2, wm9705_mic); -static const struct soc_enum wm9705_enum_rec_l = - SOC_ENUM_SINGLE(AC97_REC_SEL, 8, 8, wm9705_rec_sel); -static const struct soc_enum wm9705_enum_rec_r = - SOC_ENUM_SINGLE(AC97_REC_SEL, 0, 8, wm9705_rec_sel); +static SOC_ENUM_SINGLE_DECL(wm9705_enum_mic, + AC97_GENERAL_PURPOSE, 8, wm9705_mic); +static SOC_ENUM_SINGLE_DECL(wm9705_enum_rec_l, + AC97_REC_SEL, 8, wm9705_rec_sel); +static SOC_ENUM_SINGLE_DECL(wm9705_enum_rec_r, + AC97_REC_SEL, 0, wm9705_rec_sel); /* Headphone Mixer */ static const struct snd_kcontrol_new wm9705_hp_mixer_controls[] = { diff --git a/sound/soc/codecs/wm_adsp.c b/sound/soc/codecs/wm_adsp.c index 444626fcab4..bb5f7b4e3eb 100644 --- a/sound/soc/codecs/wm_adsp.c +++ b/sound/soc/codecs/wm_adsp.c @@ -684,24 +684,38 @@ static int wm_adsp_load(struct wm_adsp *dsp) } if (reg) { - buf = wm_adsp_buf_alloc(region->data, - le32_to_cpu(region->len), - &buf_list); - if (!buf) { - adsp_err(dsp, "Out of memory\n"); - ret = -ENOMEM; - goto out_fw; - } + size_t to_write = PAGE_SIZE; + size_t remain = le32_to_cpu(region->len); + const u8 *data = region->data; + + while (remain > 0) { + if (remain < PAGE_SIZE) + to_write = remain; + + buf = wm_adsp_buf_alloc(data, + to_write, + &buf_list); + if (!buf) { + adsp_err(dsp, "Out of memory\n"); + ret = -ENOMEM; + goto out_fw; + } - ret = regmap_raw_write_async(regmap, reg, buf->buf, - le32_to_cpu(region->len)); - if (ret != 0) { - adsp_err(dsp, - "%s.%d: Failed to write %d bytes at %d in %s: %d\n", - file, regions, - le32_to_cpu(region->len), offset, - region_name, ret); - goto out_fw; + ret = regmap_raw_write_async(regmap, reg, + buf->buf, + to_write); + if (ret != 0) { + adsp_err(dsp, + "%s.%d: Failed to write %zd bytes at %d in %s: %d\n", + file, regions, + to_write, offset, + region_name, ret); + goto out_fw; + } + + data += to_write; + reg += to_write / 2; + remain -= to_write; } } @@ -1679,6 +1693,8 @@ int wm_adsp2_event(struct snd_soc_dapm_widget *w, list_del(&alg_region->list); kfree(alg_region); } + + adsp_dbg(dsp, "Shutdown complete\n"); break; default: diff --git a/sound/soc/codecs/wm_hubs.c b/sound/soc/codecs/wm_hubs.c index b371066dd5b..b6209662ab1 100644 --- a/sound/soc/codecs/wm_hubs.c +++ b/sound/soc/codecs/wm_hubs.c @@ -50,16 +50,16 @@ static const char *speaker_ref_text[] = { "VMID", }; -static const struct soc_enum speaker_ref = - SOC_ENUM_SINGLE(WM8993_SPEAKER_MIXER, 8, 2, speaker_ref_text); +static SOC_ENUM_SINGLE_DECL(speaker_ref, + WM8993_SPEAKER_MIXER, 8, speaker_ref_text); static const char *speaker_mode_text[] = { "Class D", "Class AB", }; -static const struct soc_enum speaker_mode = - SOC_ENUM_SINGLE(WM8993_SPKMIXR_ATTENUATION, 8, 2, speaker_mode_text); +static SOC_ENUM_SINGLE_DECL(speaker_mode, + WM8993_SPKMIXR_ATTENUATION, 8, speaker_mode_text); static void wait_for_dc_servo(struct snd_soc_codec *codec, unsigned int op) { @@ -735,15 +735,15 @@ static const char *hp_mux_text[] = { "DAC", }; -static const struct soc_enum hpl_enum = - SOC_ENUM_SINGLE(WM8993_OUTPUT_MIXER1, 8, 2, hp_mux_text); +static SOC_ENUM_SINGLE_DECL(hpl_enum, + WM8993_OUTPUT_MIXER1, 8, hp_mux_text); const struct snd_kcontrol_new wm_hubs_hpl_mux = WM_HUBS_ENUM_W("Left Headphone Mux", hpl_enum); EXPORT_SYMBOL_GPL(wm_hubs_hpl_mux); -static const struct soc_enum hpr_enum = - SOC_ENUM_SINGLE(WM8993_OUTPUT_MIXER2, 8, 2, hp_mux_text); +static SOC_ENUM_SINGLE_DECL(hpr_enum, + WM8993_OUTPUT_MIXER2, 8, hp_mux_text); const struct snd_kcontrol_new wm_hubs_hpr_mux = WM_HUBS_ENUM_W("Right Headphone Mux", hpr_enum); diff --git a/sound/soc/davinci/davinci-evm.c b/sound/soc/davinci/davinci-evm.c index 5e3bc3c6801..cab98a58005 100644 --- a/sound/soc/davinci/davinci-evm.c +++ b/sound/soc/davinci/davinci-evm.c @@ -17,6 +17,7 @@ #include <linux/platform_data/edma.h> #include <linux/i2c.h> #include <linux/of_platform.h> +#include <linux/clk.h> #include <sound/core.h> #include <sound/pcm.h> #include <sound/soc.h> @@ -30,9 +31,34 @@ #include "davinci-i2s.h" struct snd_soc_card_drvdata_davinci { + struct clk *mclk; unsigned sysclk; }; +static int evm_startup(struct snd_pcm_substream *substream) +{ + struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_card *soc_card = rtd->codec->card; + struct snd_soc_card_drvdata_davinci *drvdata = + snd_soc_card_get_drvdata(soc_card); + + if (drvdata->mclk) + return clk_prepare_enable(drvdata->mclk); + + return 0; +} + +static void evm_shutdown(struct snd_pcm_substream *substream) +{ + struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_card *soc_card = rtd->codec->card; + struct snd_soc_card_drvdata_davinci *drvdata = + snd_soc_card_get_drvdata(soc_card); + + if (drvdata->mclk) + clk_disable_unprepare(drvdata->mclk); +} + static int evm_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { @@ -59,6 +85,8 @@ static int evm_hw_params(struct snd_pcm_substream *substream, } static struct snd_soc_ops evm_ops = { + .startup = evm_startup, + .shutdown = evm_shutdown, .hw_params = evm_hw_params, }; @@ -95,35 +123,29 @@ static const struct snd_soc_dapm_route audio_map[] = { /* Logic for a aic3x as connected on a davinci-evm */ static int evm_aic3x_init(struct snd_soc_pcm_runtime *rtd) { + struct snd_soc_card *card = rtd->card; struct snd_soc_codec *codec = rtd->codec; - struct snd_soc_dapm_context *dapm = &codec->dapm; struct device_node *np = codec->card->dev->of_node; int ret; /* Add davinci-evm specific widgets */ - snd_soc_dapm_new_controls(dapm, aic3x_dapm_widgets, + snd_soc_dapm_new_controls(&card->dapm, aic3x_dapm_widgets, ARRAY_SIZE(aic3x_dapm_widgets)); if (np) { - ret = snd_soc_of_parse_audio_routing(codec->card, - "ti,audio-routing"); + ret = snd_soc_of_parse_audio_routing(card, "ti,audio-routing"); if (ret) return ret; } else { /* Set up davinci-evm specific audio path audio_map */ - snd_soc_dapm_add_routes(dapm, audio_map, ARRAY_SIZE(audio_map)); + snd_soc_dapm_add_routes(&card->dapm, audio_map, + ARRAY_SIZE(audio_map)); } /* not connected */ - snd_soc_dapm_disable_pin(dapm, "MONO_LOUT"); - snd_soc_dapm_disable_pin(dapm, "HPLCOM"); - snd_soc_dapm_disable_pin(dapm, "HPRCOM"); - - /* always connected */ - snd_soc_dapm_enable_pin(dapm, "Headphone Jack"); - snd_soc_dapm_enable_pin(dapm, "Line Out"); - snd_soc_dapm_enable_pin(dapm, "Mic Jack"); - snd_soc_dapm_enable_pin(dapm, "Line In"); + snd_soc_dapm_nc_pin(&codec->dapm, "MONO_LOUT"); + snd_soc_dapm_nc_pin(&codec->dapm, "HPLCOM"); + snd_soc_dapm_nc_pin(&codec->dapm, "HPRCOM"); return 0; } @@ -348,6 +370,7 @@ static int davinci_evm_probe(struct platform_device *pdev) of_match_device(of_match_ptr(davinci_evm_dt_ids), &pdev->dev); struct snd_soc_dai_link *dai = (struct snd_soc_dai_link *) match->data; struct snd_soc_card_drvdata_davinci *drvdata = NULL; + struct clk *mclk; int ret = 0; evm_soc_card.dai_link = dai; @@ -367,13 +390,38 @@ static int davinci_evm_probe(struct platform_device *pdev) if (ret) return ret; + mclk = devm_clk_get(&pdev->dev, "mclk"); + if (PTR_ERR(mclk) == -EPROBE_DEFER) { + return -EPROBE_DEFER; + } else if (IS_ERR(mclk)) { + dev_dbg(&pdev->dev, "mclk not found.\n"); + mclk = NULL; + } + drvdata = devm_kzalloc(&pdev->dev, sizeof(*drvdata), GFP_KERNEL); if (!drvdata) return -ENOMEM; + drvdata->mclk = mclk; + ret = of_property_read_u32(np, "ti,codec-clock-rate", &drvdata->sysclk); - if (ret < 0) - return -EINVAL; + + if (ret < 0) { + if (!drvdata->mclk) { + dev_err(&pdev->dev, + "No clock or clock rate defined.\n"); + return -EINVAL; + } + drvdata->sysclk = clk_get_rate(drvdata->mclk); + } else if (drvdata->mclk) { + unsigned int requestd_rate = drvdata->sysclk; + clk_set_rate(drvdata->mclk, drvdata->sysclk); + drvdata->sysclk = clk_get_rate(drvdata->mclk); + if (drvdata->sysclk != requestd_rate) + dev_warn(&pdev->dev, + "Could not get requested rate %u using %u.\n", + requestd_rate, drvdata->sysclk); + } snd_soc_card_set_drvdata(&evm_soc_card, drvdata); ret = devm_snd_soc_register_card(&pdev->dev, &evm_soc_card); diff --git a/sound/soc/davinci/davinci-mcasp.c b/sound/soc/davinci/davinci-mcasp.c index 670afa29e30..a01ae97c90a 100644 --- a/sound/soc/davinci/davinci-mcasp.c +++ b/sound/soc/davinci/davinci-mcasp.c @@ -37,6 +37,16 @@ #include "davinci-pcm.h" #include "davinci-mcasp.h" +struct davinci_mcasp_context { + u32 txfmtctl; + u32 rxfmtctl; + u32 txfmt; + u32 rxfmt; + u32 aclkxctl; + u32 aclkrctl; + u32 pdir; +}; + struct davinci_mcasp { struct davinci_pcm_dma_params dma_params[2]; struct snd_dmaengine_dai_dma_data dma_data[2]; @@ -53,6 +63,9 @@ struct davinci_mcasp { u16 bclk_lrclk_ratio; int streams; + int sysclk_freq; + bool bclk_master; + /* McASP FIFO related */ u8 txnumevt; u8 rxnumevt; @@ -60,15 +73,7 @@ struct davinci_mcasp { bool dat_port; #ifdef CONFIG_PM_SLEEP - struct { - u32 txfmtctl; - u32 rxfmtctl; - u32 txfmt; - u32 rxfmt; - u32 aclkxctl; - u32 aclkrctl; - u32 pdir; - } context; + struct davinci_mcasp_context context; #endif }; @@ -294,6 +299,7 @@ static int davinci_mcasp_set_dai_fmt(struct snd_soc_dai *cpu_dai, mcasp_set_bits(mcasp, DAVINCI_MCASP_PDIR_REG, ACLKX | ACLKR); mcasp_set_bits(mcasp, DAVINCI_MCASP_PDIR_REG, AFSX | AFSR); + mcasp->bclk_master = 1; break; case SND_SOC_DAIFMT_CBM_CFS: /* codec is clock master and frame slave */ @@ -305,6 +311,7 @@ static int davinci_mcasp_set_dai_fmt(struct snd_soc_dai *cpu_dai, mcasp_clr_bits(mcasp, DAVINCI_MCASP_PDIR_REG, ACLKX | ACLKR); mcasp_set_bits(mcasp, DAVINCI_MCASP_PDIR_REG, AFSX | AFSR); + mcasp->bclk_master = 0; break; case SND_SOC_DAIFMT_CBM_CFM: /* codec is clock and frame master */ @@ -316,6 +323,7 @@ static int davinci_mcasp_set_dai_fmt(struct snd_soc_dai *cpu_dai, mcasp_clr_bits(mcasp, DAVINCI_MCASP_PDIR_REG, ACLKX | AHCLKX | AFSX | ACLKR | AHCLKR | AFSR); + mcasp->bclk_master = 0; break; default: @@ -410,6 +418,8 @@ static int davinci_mcasp_set_sysclk(struct snd_soc_dai *dai, int clk_id, mcasp_clr_bits(mcasp, DAVINCI_MCASP_PDIR_REG, AHCLKX); } + mcasp->sysclk_freq = freq; + return 0; } @@ -603,20 +613,23 @@ static int davinci_mcasp_hw_params(struct snd_pcm_substream *substream, u8 fifo_level; u8 slots = mcasp->tdm_slots; u8 active_serializers; - int channels; + int channels = params_channels(params); int ret; - struct snd_interval *pcm_channels = hw_param_interval(params, - SNDRV_PCM_HW_PARAM_CHANNELS); - channels = pcm_channels->min; - active_serializers = (channels + slots - 1) / slots; + /* If mcasp is BCLK master we need to set BCLK divider */ + if (mcasp->bclk_master) { + unsigned int bclk_freq = snd_soc_params_to_bclk(params); + if (mcasp->sysclk_freq % bclk_freq != 0) { + dev_err(mcasp->dev, "Can't produce requred BCLK\n"); + return -EINVAL; + } + davinci_mcasp_set_clkdiv( + cpu_dai, 1, mcasp->sysclk_freq / bclk_freq); + } - if (mcasp_common_hw_param(mcasp, substream->stream, channels) == -EINVAL) - return -EINVAL; - if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) - fifo_level = mcasp->txnumevt * active_serializers; - else - fifo_level = mcasp->rxnumevt * active_serializers; + ret = mcasp_common_hw_param(mcasp, substream->stream, channels); + if (ret) + return ret; if (mcasp->op_mode == DAVINCI_MCASP_DIT_MODE) ret = mcasp_dit_hw_param(mcasp); @@ -658,6 +671,13 @@ static int davinci_mcasp_hw_params(struct snd_pcm_substream *substream, return -EINVAL; } + /* Calculate FIFO level */ + active_serializers = (channels + slots - 1) / slots; + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) + fifo_level = mcasp->txnumevt * active_serializers; + else + fifo_level = mcasp->rxnumevt * active_serializers; + if (mcasp->version == MCASP_VERSION_2 && !fifo_level) dma_params->acnt = 4; else @@ -719,6 +739,43 @@ static const struct snd_soc_dai_ops davinci_mcasp_dai_ops = { .set_sysclk = davinci_mcasp_set_sysclk, }; +#ifdef CONFIG_PM_SLEEP +static int davinci_mcasp_suspend(struct snd_soc_dai *dai) +{ + struct davinci_mcasp *mcasp = snd_soc_dai_get_drvdata(dai); + struct davinci_mcasp_context *context = &mcasp->context; + + context->txfmtctl = mcasp_get_reg(mcasp, DAVINCI_MCASP_TXFMCTL_REG); + context->rxfmtctl = mcasp_get_reg(mcasp, DAVINCI_MCASP_RXFMCTL_REG); + context->txfmt = mcasp_get_reg(mcasp, DAVINCI_MCASP_TXFMT_REG); + context->rxfmt = mcasp_get_reg(mcasp, DAVINCI_MCASP_RXFMT_REG); + context->aclkxctl = mcasp_get_reg(mcasp, DAVINCI_MCASP_ACLKXCTL_REG); + context->aclkrctl = mcasp_get_reg(mcasp, DAVINCI_MCASP_ACLKRCTL_REG); + context->pdir = mcasp_get_reg(mcasp, DAVINCI_MCASP_PDIR_REG); + + return 0; +} + +static int davinci_mcasp_resume(struct snd_soc_dai *dai) +{ + struct davinci_mcasp *mcasp = snd_soc_dai_get_drvdata(dai); + struct davinci_mcasp_context *context = &mcasp->context; + + mcasp_set_reg(mcasp, DAVINCI_MCASP_TXFMCTL_REG, context->txfmtctl); + mcasp_set_reg(mcasp, DAVINCI_MCASP_RXFMCTL_REG, context->rxfmtctl); + mcasp_set_reg(mcasp, DAVINCI_MCASP_TXFMT_REG, context->txfmt); + mcasp_set_reg(mcasp, DAVINCI_MCASP_RXFMT_REG, context->rxfmt); + mcasp_set_reg(mcasp, DAVINCI_MCASP_ACLKXCTL_REG, context->aclkxctl); + mcasp_set_reg(mcasp, DAVINCI_MCASP_ACLKRCTL_REG, context->aclkrctl); + mcasp_set_reg(mcasp, DAVINCI_MCASP_PDIR_REG, context->pdir); + + return 0; +} +#else +#define davinci_mcasp_suspend NULL +#define davinci_mcasp_resume NULL +#endif + #define DAVINCI_MCASP_RATES SNDRV_PCM_RATE_8000_192000 #define DAVINCI_MCASP_PCM_FMTS (SNDRV_PCM_FMTBIT_S8 | \ @@ -735,6 +792,8 @@ static const struct snd_soc_dai_ops davinci_mcasp_dai_ops = { static struct snd_soc_dai_driver davinci_mcasp_dai[] = { { .name = "davinci-mcasp.0", + .suspend = davinci_mcasp_suspend, + .resume = davinci_mcasp_resume, .playback = { .channels_min = 2, .channels_max = 32 * 16, @@ -768,28 +827,28 @@ static const struct snd_soc_component_driver davinci_mcasp_component = { }; /* Some HW specific values and defaults. The rest is filled in from DT. */ -static struct snd_platform_data dm646x_mcasp_pdata = { +static struct davinci_mcasp_pdata dm646x_mcasp_pdata = { .tx_dma_offset = 0x400, .rx_dma_offset = 0x400, .asp_chan_q = EVENTQ_0, .version = MCASP_VERSION_1, }; -static struct snd_platform_data da830_mcasp_pdata = { +static struct davinci_mcasp_pdata da830_mcasp_pdata = { .tx_dma_offset = 0x2000, .rx_dma_offset = 0x2000, .asp_chan_q = EVENTQ_0, .version = MCASP_VERSION_2, }; -static struct snd_platform_data am33xx_mcasp_pdata = { +static struct davinci_mcasp_pdata am33xx_mcasp_pdata = { .tx_dma_offset = 0, .rx_dma_offset = 0, .asp_chan_q = EVENTQ_0, .version = MCASP_VERSION_3, }; -static struct snd_platform_data dra7_mcasp_pdata = { +static struct davinci_mcasp_pdata dra7_mcasp_pdata = { .tx_dma_offset = 0x200, .rx_dma_offset = 0x284, .asp_chan_q = EVENTQ_0, @@ -857,11 +916,11 @@ err1: return ret; } -static struct snd_platform_data *davinci_mcasp_set_pdata_from_of( +static struct davinci_mcasp_pdata *davinci_mcasp_set_pdata_from_of( struct platform_device *pdev) { struct device_node *np = pdev->dev.of_node; - struct snd_platform_data *pdata = NULL; + struct davinci_mcasp_pdata *pdata = NULL; const struct of_device_id *match = of_match_device(mcasp_dt_ids, &pdev->dev); struct of_phandle_args dma_spec; @@ -874,7 +933,7 @@ static struct snd_platform_data *davinci_mcasp_set_pdata_from_of( pdata = pdev->dev.platform_data; return pdata; } else if (match) { - pdata = (struct snd_platform_data *) match->data; + pdata = (struct davinci_mcasp_pdata*) match->data; } else { /* control shouldn't reach here. something is wrong */ ret = -EINVAL; @@ -966,9 +1025,10 @@ nodata: static int davinci_mcasp_probe(struct platform_device *pdev) { - struct davinci_pcm_dma_params *dma_data; + struct davinci_pcm_dma_params *dma_params; + struct snd_dmaengine_dai_dma_data *dma_data; struct resource *mem, *ioarea, *res, *dat; - struct snd_platform_data *pdata; + struct davinci_mcasp_pdata *pdata; struct davinci_mcasp *mcasp; int ret; @@ -1035,41 +1095,49 @@ static int davinci_mcasp_probe(struct platform_device *pdev) if (dat) mcasp->dat_port = true; - dma_data = &mcasp->dma_params[SNDRV_PCM_STREAM_PLAYBACK]; - dma_data->asp_chan_q = pdata->asp_chan_q; - dma_data->ram_chan_q = pdata->ram_chan_q; - dma_data->sram_pool = pdata->sram_pool; - dma_data->sram_size = pdata->sram_size_playback; + dma_params = &mcasp->dma_params[SNDRV_PCM_STREAM_PLAYBACK]; + dma_data = &mcasp->dma_data[SNDRV_PCM_STREAM_PLAYBACK]; + dma_params->asp_chan_q = pdata->asp_chan_q; + dma_params->ram_chan_q = pdata->ram_chan_q; + dma_params->sram_pool = pdata->sram_pool; + dma_params->sram_size = pdata->sram_size_playback; if (dat) - dma_data->dma_addr = dat->start; + dma_params->dma_addr = dat->start; else - dma_data->dma_addr = mem->start + pdata->tx_dma_offset; + dma_params->dma_addr = mem->start + pdata->tx_dma_offset; /* Unconditional dmaengine stuff */ - mcasp->dma_data[SNDRV_PCM_STREAM_PLAYBACK].addr = dma_data->dma_addr; + dma_data->addr = dma_params->dma_addr; res = platform_get_resource(pdev, IORESOURCE_DMA, 0); if (res) - dma_data->channel = res->start; + dma_params->channel = res->start; else - dma_data->channel = pdata->tx_dma_channel; + dma_params->channel = pdata->tx_dma_channel; - dma_data = &mcasp->dma_params[SNDRV_PCM_STREAM_CAPTURE]; - dma_data->asp_chan_q = pdata->asp_chan_q; - dma_data->ram_chan_q = pdata->ram_chan_q; - dma_data->sram_pool = pdata->sram_pool; - dma_data->sram_size = pdata->sram_size_capture; + /* dmaengine filter data for DT and non-DT boot */ + if (pdev->dev.of_node) + dma_data->filter_data = "tx"; + else + dma_data->filter_data = &dma_params->channel; + + dma_params = &mcasp->dma_params[SNDRV_PCM_STREAM_CAPTURE]; + dma_data = &mcasp->dma_data[SNDRV_PCM_STREAM_CAPTURE]; + dma_params->asp_chan_q = pdata->asp_chan_q; + dma_params->ram_chan_q = pdata->ram_chan_q; + dma_params->sram_pool = pdata->sram_pool; + dma_params->sram_size = pdata->sram_size_capture; if (dat) - dma_data->dma_addr = dat->start; + dma_params->dma_addr = dat->start; else - dma_data->dma_addr = mem->start + pdata->rx_dma_offset; + dma_params->dma_addr = mem->start + pdata->rx_dma_offset; /* Unconditional dmaengine stuff */ - mcasp->dma_data[SNDRV_PCM_STREAM_CAPTURE].addr = dma_data->dma_addr; + dma_data->addr = dma_params->dma_addr; if (mcasp->version < MCASP_VERSION_3) { mcasp->fifo_base = DAVINCI_MCASP_V2_AFIFO_BASE; - /* dma_data->dma_addr is pointing to the data port address */ + /* dma_params->dma_addr is pointing to the data port address */ mcasp->dat_port = true; } else { mcasp->fifo_base = DAVINCI_MCASP_V3_AFIFO_BASE; @@ -1077,13 +1145,15 @@ static int davinci_mcasp_probe(struct platform_device *pdev) res = platform_get_resource(pdev, IORESOURCE_DMA, 1); if (res) - dma_data->channel = res->start; + dma_params->channel = res->start; else - dma_data->channel = pdata->rx_dma_channel; + dma_params->channel = pdata->rx_dma_channel; - /* Unconditional dmaengine stuff */ - mcasp->dma_data[SNDRV_PCM_STREAM_PLAYBACK].filter_data = "tx"; - mcasp->dma_data[SNDRV_PCM_STREAM_CAPTURE].filter_data = "rx"; + /* dmaengine filter data for DT and non-DT boot */ + if (pdev->dev.of_node) + dma_data->filter_data = "rx"; + else + dma_data->filter_data = &dma_params->channel; dev_set_drvdata(&pdev->dev, mcasp); @@ -1127,49 +1197,12 @@ static int davinci_mcasp_remove(struct platform_device *pdev) return 0; } -#ifdef CONFIG_PM_SLEEP -static int davinci_mcasp_suspend(struct device *dev) -{ - struct davinci_mcasp *mcasp = dev_get_drvdata(dev); - - mcasp->context.txfmtctl = mcasp_get_reg(mcasp, DAVINCI_MCASP_TXFMCTL_REG); - mcasp->context.rxfmtctl = mcasp_get_reg(mcasp, DAVINCI_MCASP_RXFMCTL_REG); - mcasp->context.txfmt = mcasp_get_reg(mcasp, DAVINCI_MCASP_TXFMT_REG); - mcasp->context.rxfmt = mcasp_get_reg(mcasp, DAVINCI_MCASP_RXFMT_REG); - mcasp->context.aclkxctl = mcasp_get_reg(mcasp, DAVINCI_MCASP_ACLKXCTL_REG); - mcasp->context.aclkrctl = mcasp_get_reg(mcasp, DAVINCI_MCASP_ACLKRCTL_REG); - mcasp->context.pdir = mcasp_get_reg(mcasp, DAVINCI_MCASP_PDIR_REG); - - return 0; -} - -static int davinci_mcasp_resume(struct device *dev) -{ - struct davinci_mcasp *mcasp = dev_get_drvdata(dev); - - mcasp_set_reg(mcasp, DAVINCI_MCASP_TXFMCTL_REG, mcasp->context.txfmtctl); - mcasp_set_reg(mcasp, DAVINCI_MCASP_RXFMCTL_REG, mcasp->context.rxfmtctl); - mcasp_set_reg(mcasp, DAVINCI_MCASP_TXFMT_REG, mcasp->context.txfmt); - mcasp_set_reg(mcasp, DAVINCI_MCASP_RXFMT_REG, mcasp->context.rxfmt); - mcasp_set_reg(mcasp, DAVINCI_MCASP_ACLKXCTL_REG, mcasp->context.aclkxctl); - mcasp_set_reg(mcasp, DAVINCI_MCASP_ACLKRCTL_REG, mcasp->context.aclkrctl); - mcasp_set_reg(mcasp, DAVINCI_MCASP_PDIR_REG, mcasp->context.pdir); - - return 0; -} -#endif - -SIMPLE_DEV_PM_OPS(davinci_mcasp_pm_ops, - davinci_mcasp_suspend, - davinci_mcasp_resume); - static struct platform_driver davinci_mcasp_driver = { .probe = davinci_mcasp_probe, .remove = davinci_mcasp_remove, .driver = { .name = "davinci-mcasp", .owner = THIS_MODULE, - .pm = &davinci_mcasp_pm_ops, .of_match_table = mcasp_dt_ids, }, }; diff --git a/sound/soc/davinci/edma-pcm.c b/sound/soc/davinci/edma-pcm.c new file mode 100644 index 00000000000..d38afb1c61a --- /dev/null +++ b/sound/soc/davinci/edma-pcm.c @@ -0,0 +1,57 @@ +/* + * edma-pcm.c - eDMA PCM driver using dmaengine for AM3xxx, AM4xxx + * + * Copyright (C) 2014 Texas Instruments, Inc. + * + * Author: Peter Ujfalusi <peter.ujfalusi@ti.com> + * + * Based on: sound/soc/tegra/tegra_pcm.c + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + */ + +#include <linux/module.h> +#include <sound/core.h> +#include <sound/pcm.h> +#include <sound/pcm_params.h> +#include <sound/soc.h> +#include <sound/dmaengine_pcm.h> +#include <linux/edma.h> + +static const struct snd_pcm_hardware edma_pcm_hardware = { + .info = SNDRV_PCM_INFO_MMAP | + SNDRV_PCM_INFO_MMAP_VALID | + SNDRV_PCM_INFO_BATCH | + SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_RESUME | + SNDRV_PCM_INFO_INTERLEAVED, + .buffer_bytes_max = 128 * 1024, + .period_bytes_min = 32, + .period_bytes_max = 64 * 1024, + .periods_min = 2, + .periods_max = 19, /* Limit by edma dmaengine driver */ +}; + +static const struct snd_dmaengine_pcm_config edma_dmaengine_pcm_config = { + .pcm_hardware = &edma_pcm_hardware, + .prepare_slave_config = snd_dmaengine_pcm_prepare_slave_config, + .compat_filter_fn = edma_filter_fn, + .prealloc_buffer_size = 128 * 1024, +}; + +int edma_pcm_platform_register(struct device *dev) +{ + return devm_snd_dmaengine_pcm_register(dev, &edma_dmaengine_pcm_config, + SND_DMAENGINE_PCM_FLAG_COMPAT); +} +EXPORT_SYMBOL_GPL(edma_pcm_platform_register); + +MODULE_AUTHOR("Peter Ujfalusi <peter.ujfalusi@ti.com>"); +MODULE_DESCRIPTION("eDMA PCM ASoC platform driver"); +MODULE_LICENSE("GPL"); diff --git a/sound/soc/davinci/edma-pcm.h b/sound/soc/davinci/edma-pcm.h new file mode 100644 index 00000000000..894c378c0f7 --- /dev/null +++ b/sound/soc/davinci/edma-pcm.h @@ -0,0 +1,25 @@ +/* + * edma-pcm.h - eDMA PCM driver using dmaengine for AM3xxx, AM4xxx + * + * Copyright (C) 2014 Texas Instruments, Inc. + * + * Author: Peter Ujfalusi <peter.ujfalusi@ti.com> + * + * Based on: sound/soc/tegra/tegra_pcm.h + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + */ + +#ifndef __EDMA_PCM_H__ +#define __EDMA_PCM_H__ + +int edma_pcm_platform_register(struct device *dev); + +#endif /* __EDMA_PCM_H__ */ diff --git a/sound/soc/fsl/Kconfig b/sound/soc/fsl/Kconfig index 07f8f141727..338a9164247 100644 --- a/sound/soc/fsl/Kconfig +++ b/sound/soc/fsl/Kconfig @@ -1,5 +1,6 @@ config SND_SOC_FSL_SAI tristate + select REGMAP_MMIO select SND_SOC_GENERIC_DMAENGINE_PCM config SND_SOC_FSL_SSI @@ -7,9 +8,12 @@ config SND_SOC_FSL_SSI config SND_SOC_FSL_SPDIF tristate + select REGMAP_MMIO config SND_SOC_FSL_ESAI tristate + select REGMAP_MMIO + select SND_SOC_FSL_UTILS config SND_SOC_FSL_UTILS tristate @@ -117,6 +121,7 @@ if SND_IMX_SOC config SND_SOC_IMX_SSI tristate + select SND_SOC_FSL_UTILS config SND_SOC_IMX_PCM_FIQ tristate @@ -168,12 +173,14 @@ config SND_SOC_EUKREA_TLV320 depends on MACH_EUKREA_MBIMX27_BASEBOARD \ || MACH_EUKREA_MBIMXSD25_BASEBOARD \ || MACH_EUKREA_MBIMXSD35_BASEBOARD \ - || MACH_EUKREA_MBIMXSD51_BASEBOARD + || MACH_EUKREA_MBIMXSD51_BASEBOARD \ + || (OF && ARM) depends on I2C - select SND_SOC_TLV320AIC23 - select SND_SOC_IMX_PCM_FIQ + select SND_SOC_TLV320AIC23_I2C select SND_SOC_IMX_AUDMUX select SND_SOC_IMX_SSI + select SND_SOC_FSL_SSI + select SND_SOC_IMX_PCM_DMA help Enable I2S based access to the TLV320AIC23B codec attached to the SSI interface @@ -204,7 +211,6 @@ config SND_SOC_IMX_SPDIF tristate "SoC Audio support for i.MX boards with S/PDIF" select SND_SOC_IMX_PCM_DMA select SND_SOC_FSL_SPDIF - select REGMAP_MMIO help SoC Audio support for i.MX boards with S/PDIF Say Y if you want to add support for SoC audio on an i.MX board with diff --git a/sound/soc/fsl/eukrea-tlv320.c b/sound/soc/fsl/eukrea-tlv320.c index 5983740be12..eb093d5b85c 100644 --- a/sound/soc/fsl/eukrea-tlv320.c +++ b/sound/soc/fsl/eukrea-tlv320.c @@ -15,8 +15,11 @@ * */ +#include <linux/errno.h> #include <linux/module.h> #include <linux/moduleparam.h> +#include <linux/of.h> +#include <linux/of_platform.h> #include <linux/device.h> #include <linux/i2c.h> #include <sound/core.h> @@ -26,6 +29,7 @@ #include "../codecs/tlv320aic23.h" #include "imx-ssi.h" +#include "fsl_ssi.h" #include "imx-audmux.h" #define CODEC_CLOCK 12000000 @@ -41,7 +45,8 @@ static int eukrea_tlv320_hw_params(struct snd_pcm_substream *substream, ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM); - if (ret) { + /* fsl_ssi lacks the set_fmt ops. */ + if (ret && ret != -ENOTSUPP) { dev_err(cpu_dai->dev, "Failed to set the cpu dai format.\n"); return ret; @@ -63,11 +68,13 @@ static int eukrea_tlv320_hw_params(struct snd_pcm_substream *substream, "Failed to set the codec sysclk.\n"); return ret; } + snd_soc_dai_set_tdm_slot(cpu_dai, 0xffffffc, 0xffffffc, 2, 0); ret = snd_soc_dai_set_sysclk(cpu_dai, IMX_SSP_SYS_CLK, 0, SND_SOC_CLOCK_IN); - if (ret) { + /* fsl_ssi lacks the set_sysclk ops */ + if (ret && ret != -EINVAL) { dev_err(cpu_dai->dev, "Can't set the IMX_SSP_SYS_CLK CPU system clock.\n"); return ret; @@ -84,14 +91,10 @@ static struct snd_soc_dai_link eukrea_tlv320_dai = { .name = "tlv320aic23", .stream_name = "TLV320AIC23", .codec_dai_name = "tlv320aic23-hifi", - .platform_name = "imx-ssi.0", - .codec_name = "tlv320aic23-codec.0-001a", - .cpu_dai_name = "imx-ssi.0", .ops = &eukrea_tlv320_snd_ops, }; static struct snd_soc_card eukrea_tlv320 = { - .name = "cpuimx-audio", .owner = THIS_MODULE, .dai_link = &eukrea_tlv320_dai, .num_links = 1, @@ -101,8 +104,65 @@ static int eukrea_tlv320_probe(struct platform_device *pdev) { int ret; int int_port = 0, ext_port; + struct device_node *np = pdev->dev.of_node; + struct device_node *ssi_np, *codec_np; - if (machine_is_eukrea_cpuimx27()) { + eukrea_tlv320.dev = &pdev->dev; + if (np) { + ret = snd_soc_of_parse_card_name(&eukrea_tlv320, + "eukrea,model"); + if (ret) { + dev_err(&pdev->dev, + "eukrea,model node missing or invalid.\n"); + goto err; + } + + ssi_np = of_parse_phandle(pdev->dev.of_node, + "ssi-controller", 0); + if (!ssi_np) { + dev_err(&pdev->dev, + "ssi-controller missing or invalid.\n"); + ret = -ENODEV; + goto err; + } + + codec_np = of_parse_phandle(ssi_np, "codec-handle", 0); + if (codec_np) + eukrea_tlv320_dai.codec_of_node = codec_np; + else + dev_err(&pdev->dev, "codec-handle node missing or invalid.\n"); + + ret = of_property_read_u32(np, "fsl,mux-int-port", &int_port); + if (ret) { + dev_err(&pdev->dev, + "fsl,mux-int-port node missing or invalid.\n"); + return ret; + } + ret = of_property_read_u32(np, "fsl,mux-ext-port", &ext_port); + if (ret) { + dev_err(&pdev->dev, + "fsl,mux-ext-port node missing or invalid.\n"); + return ret; + } + + /* + * The port numbering in the hardware manual starts at 1, while + * the audmux API expects it starts at 0. + */ + int_port--; + ext_port--; + + eukrea_tlv320_dai.cpu_of_node = ssi_np; + eukrea_tlv320_dai.platform_of_node = ssi_np; + } else { + eukrea_tlv320_dai.cpu_dai_name = "imx-ssi.0"; + eukrea_tlv320_dai.platform_name = "imx-ssi.0"; + eukrea_tlv320_dai.codec_name = "tlv320aic23-codec.0-001a"; + eukrea_tlv320.name = "cpuimx-audio"; + } + + if (machine_is_eukrea_cpuimx27() || + of_find_compatible_node(NULL, NULL, "fsl,imx21-audmux")) { imx_audmux_v1_configure_port(MX27_AUDMUX_HPCR1_SSI0, IMX_AUDMUX_V1_PCR_SYN | IMX_AUDMUX_V1_PCR_TFSDIR | @@ -119,8 +179,12 @@ static int eukrea_tlv320_probe(struct platform_device *pdev) ); } else if (machine_is_eukrea_cpuimx25sd() || machine_is_eukrea_cpuimx35sd() || - machine_is_eukrea_cpuimx51sd()) { - ext_port = machine_is_eukrea_cpuimx25sd() ? 4 : 3; + machine_is_eukrea_cpuimx51sd() || + of_find_compatible_node(NULL, NULL, "fsl,imx31-audmux")) { + if (!np) + ext_port = machine_is_eukrea_cpuimx25sd() ? + 4 : 3; + imx_audmux_v2_configure_port(int_port, IMX_AUDMUX_V2_PTCR_SYN | IMX_AUDMUX_V2_PTCR_TFSDIR | @@ -134,14 +198,27 @@ static int eukrea_tlv320_probe(struct platform_device *pdev) IMX_AUDMUX_V2_PDCR_RXDSEL(int_port) ); } else { - /* return happy. We might run on a totally different machine */ - return 0; + if (np) { + /* The eukrea,asoc-tlv320 driver was explicitely + * requested (through the device tree). + */ + dev_err(&pdev->dev, + "Missing or invalid audmux DT node.\n"); + return -ENODEV; + } else { + /* Return happy. + * We might run on a totally different machine. + */ + return 0; + } } - eukrea_tlv320.dev = &pdev->dev; ret = snd_soc_register_card(&eukrea_tlv320); +err: if (ret) dev_err(&pdev->dev, "snd_soc_register_card failed (%d)\n", ret); + if (np) + of_node_put(ssi_np); return ret; } @@ -153,10 +230,17 @@ static int eukrea_tlv320_remove(struct platform_device *pdev) return 0; } +static const struct of_device_id imx_tlv320_dt_ids[] = { + { .compatible = "eukrea,asoc-tlv320"}, + { /* sentinel */ } +}; +MODULE_DEVICE_TABLE(of, imx_tlv320_dt_ids); + static struct platform_driver eukrea_tlv320_driver = { .driver = { .name = "eukrea_tlv320", .owner = THIS_MODULE, + .of_match_table = imx_tlv320_dt_ids, }, .probe = eukrea_tlv320_probe, .remove = eukrea_tlv320_remove, diff --git a/sound/soc/fsl/fsl_esai.c b/sound/soc/fsl/fsl_esai.c index c84026c9913..c8e5db1414d 100644 --- a/sound/soc/fsl/fsl_esai.c +++ b/sound/soc/fsl/fsl_esai.c @@ -18,6 +18,7 @@ #include "fsl_esai.h" #include "imx-pcm.h" +#include "fsl_utils.h" #define FSL_ESAI_RATES SNDRV_PCM_RATE_8000_192000 #define FSL_ESAI_FORMATS (SNDRV_PCM_FMTBIT_S8 | \ @@ -431,17 +432,26 @@ static int fsl_esai_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt) static int fsl_esai_startup(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) { + int ret; struct fsl_esai *esai_priv = snd_soc_dai_get_drvdata(dai); /* * Some platforms might use the same bit to gate all three or two of * clocks, so keep all clocks open/close at the same time for safety */ - clk_prepare_enable(esai_priv->coreclk); - if (!IS_ERR(esai_priv->extalclk)) - clk_prepare_enable(esai_priv->extalclk); - if (!IS_ERR(esai_priv->fsysclk)) - clk_prepare_enable(esai_priv->fsysclk); + ret = clk_prepare_enable(esai_priv->coreclk); + if (ret) + return ret; + if (!IS_ERR(esai_priv->extalclk)) { + ret = clk_prepare_enable(esai_priv->extalclk); + if (ret) + goto err_extalck; + } + if (!IS_ERR(esai_priv->fsysclk)) { + ret = clk_prepare_enable(esai_priv->fsysclk); + if (ret) + goto err_fsysclk; + } if (!dai->active) { /* Reset Port C */ @@ -463,6 +473,14 @@ static int fsl_esai_startup(struct snd_pcm_substream *substream, } return 0; + +err_fsysclk: + if (!IS_ERR(esai_priv->extalclk)) + clk_disable_unprepare(esai_priv->extalclk); +err_extalck: + clk_disable_unprepare(esai_priv->coreclk); + + return ret; } static int fsl_esai_hw_params(struct snd_pcm_substream *substream, @@ -564,6 +582,7 @@ static struct snd_soc_dai_ops fsl_esai_dai_ops = { .hw_params = fsl_esai_hw_params, .set_sysclk = fsl_esai_set_dai_sysclk, .set_fmt = fsl_esai_set_dai_fmt, + .xlate_tdm_slot_mask = fsl_asoc_xlate_tdm_slot_mask, .set_tdm_slot = fsl_esai_set_dai_tdm_slot, }; @@ -661,7 +680,7 @@ static bool fsl_esai_writeable_reg(struct device *dev, unsigned int reg) } } -static const struct regmap_config fsl_esai_regmap_config = { +static struct regmap_config fsl_esai_regmap_config = { .reg_bits = 32, .reg_stride = 4, .val_bits = 32, @@ -687,6 +706,9 @@ static int fsl_esai_probe(struct platform_device *pdev) esai_priv->pdev = pdev; strcpy(esai_priv->name, np->name); + if (of_property_read_bool(np, "big-endian")) + fsl_esai_regmap_config.val_format_endian = REGMAP_ENDIAN_BIG; + /* Get the addresses and IRQ */ res = platform_get_resource(pdev, IORESOURCE_MEM, 0); regs = devm_ioremap_resource(&pdev->dev, res); diff --git a/sound/soc/fsl/fsl_sai.c b/sound/soc/fsl/fsl_sai.c index cdd3fa83070..c4a42311167 100644 --- a/sound/soc/fsl/fsl_sai.c +++ b/sound/soc/fsl/fsl_sai.c @@ -15,6 +15,7 @@ #include <linux/dmaengine.h> #include <linux/module.h> #include <linux/of_address.h> +#include <linux/regmap.h> #include <linux/slab.h> #include <sound/core.h> #include <sound/dmaengine_pcm.h> @@ -22,34 +23,6 @@ #include "fsl_sai.h" -static inline u32 sai_readl(struct fsl_sai *sai, - const void __iomem *addr) -{ - u32 val; - - val = __raw_readl(addr); - - if (likely(sai->big_endian_regs)) - val = be32_to_cpu(val); - else - val = le32_to_cpu(val); - rmb(); - - return val; -} - -static inline void sai_writel(struct fsl_sai *sai, - u32 val, void __iomem *addr) -{ - wmb(); - if (likely(sai->big_endian_regs)) - val = cpu_to_be32(val); - else - val = cpu_to_le32(val); - - __raw_writel(val, addr); -} - static int fsl_sai_set_dai_sysclk_tr(struct snd_soc_dai *cpu_dai, int clk_id, unsigned int freq, int fsl_dir) { @@ -61,7 +34,8 @@ static int fsl_sai_set_dai_sysclk_tr(struct snd_soc_dai *cpu_dai, else reg_cr2 = FSL_SAI_RCR2; - val_cr2 = sai_readl(sai, sai->base + reg_cr2); + regmap_read(sai->regmap, reg_cr2, &val_cr2); + val_cr2 &= ~FSL_SAI_CR2_MSEL_MASK; switch (clk_id) { @@ -81,7 +55,7 @@ static int fsl_sai_set_dai_sysclk_tr(struct snd_soc_dai *cpu_dai, return -EINVAL; } - sai_writel(sai, val_cr2, sai->base + reg_cr2); + regmap_write(sai->regmap, reg_cr2, val_cr2); return 0; } @@ -89,32 +63,22 @@ static int fsl_sai_set_dai_sysclk_tr(struct snd_soc_dai *cpu_dai, static int fsl_sai_set_dai_sysclk(struct snd_soc_dai *cpu_dai, int clk_id, unsigned int freq, int dir) { - struct fsl_sai *sai = snd_soc_dai_get_drvdata(cpu_dai); int ret; if (dir == SND_SOC_CLOCK_IN) return 0; - ret = clk_prepare_enable(sai->clk); - if (ret) - return ret; - ret = fsl_sai_set_dai_sysclk_tr(cpu_dai, clk_id, freq, FSL_FMT_TRANSMITTER); if (ret) { dev_err(cpu_dai->dev, "Cannot set tx sysclk: %d\n", ret); - goto err_clk; + return ret; } ret = fsl_sai_set_dai_sysclk_tr(cpu_dai, clk_id, freq, FSL_FMT_RECEIVER); - if (ret) { + if (ret) dev_err(cpu_dai->dev, "Cannot set rx sysclk: %d\n", ret); - goto err_clk; - } - -err_clk: - clk_disable_unprepare(sai->clk); return ret; } @@ -133,43 +97,84 @@ static int fsl_sai_set_dai_fmt_tr(struct snd_soc_dai *cpu_dai, reg_cr4 = FSL_SAI_RCR4; } - val_cr2 = sai_readl(sai, sai->base + reg_cr2); - val_cr4 = sai_readl(sai, sai->base + reg_cr4); + regmap_read(sai->regmap, reg_cr2, &val_cr2); + regmap_read(sai->regmap, reg_cr4, &val_cr4); if (sai->big_endian_data) val_cr4 &= ~FSL_SAI_CR4_MF; else val_cr4 |= FSL_SAI_CR4_MF; + /* DAI mode */ switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { case SND_SOC_DAIFMT_I2S: + /* + * Frame low, 1clk before data, one word length for frame sync, + * frame sync starts one serial clock cycle earlier, + * that is, together with the last bit of the previous + * data word. + */ + val_cr2 &= ~FSL_SAI_CR2_BCP; + val_cr4 |= FSL_SAI_CR4_FSE | FSL_SAI_CR4_FSP; + break; + case SND_SOC_DAIFMT_LEFT_J: + /* + * Frame high, one word length for frame sync, + * frame sync asserts with the first bit of the frame. + */ + val_cr2 &= ~FSL_SAI_CR2_BCP; + val_cr4 &= ~(FSL_SAI_CR4_FSE | FSL_SAI_CR4_FSP); + break; + case SND_SOC_DAIFMT_DSP_A: + /* + * Frame high, 1clk before data, one bit for frame sync, + * frame sync starts one serial clock cycle earlier, + * that is, together with the last bit of the previous + * data word. + */ + val_cr2 &= ~FSL_SAI_CR2_BCP; + val_cr4 &= ~FSL_SAI_CR4_FSP; val_cr4 |= FSL_SAI_CR4_FSE; + sai->is_dsp_mode = true; + break; + case SND_SOC_DAIFMT_DSP_B: + /* + * Frame high, one bit for frame sync, + * frame sync asserts with the first bit of the frame. + */ + val_cr2 &= ~FSL_SAI_CR2_BCP; + val_cr4 &= ~(FSL_SAI_CR4_FSE | FSL_SAI_CR4_FSP); + sai->is_dsp_mode = true; break; + case SND_SOC_DAIFMT_RIGHT_J: + /* To be done */ default: return -EINVAL; } + /* DAI clock inversion */ switch (fmt & SND_SOC_DAIFMT_INV_MASK) { case SND_SOC_DAIFMT_IB_IF: - val_cr4 |= FSL_SAI_CR4_FSP; - val_cr2 &= ~FSL_SAI_CR2_BCP; + /* Invert both clocks */ + val_cr2 ^= FSL_SAI_CR2_BCP; + val_cr4 ^= FSL_SAI_CR4_FSP; break; case SND_SOC_DAIFMT_IB_NF: - val_cr4 &= ~FSL_SAI_CR4_FSP; - val_cr2 &= ~FSL_SAI_CR2_BCP; + /* Invert bit clock */ + val_cr2 ^= FSL_SAI_CR2_BCP; break; case SND_SOC_DAIFMT_NB_IF: - val_cr4 |= FSL_SAI_CR4_FSP; - val_cr2 |= FSL_SAI_CR2_BCP; + /* Invert frame clock */ + val_cr4 ^= FSL_SAI_CR4_FSP; break; case SND_SOC_DAIFMT_NB_NF: - val_cr4 &= ~FSL_SAI_CR4_FSP; - val_cr2 |= FSL_SAI_CR2_BCP; + /* Nothing to do for both normal cases */ break; default: return -EINVAL; } + /* DAI clock master masks */ switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { case SND_SOC_DAIFMT_CBS_CFS: val_cr2 |= FSL_SAI_CR2_BCD_MSTR; @@ -179,39 +184,37 @@ static int fsl_sai_set_dai_fmt_tr(struct snd_soc_dai *cpu_dai, val_cr2 &= ~FSL_SAI_CR2_BCD_MSTR; val_cr4 &= ~FSL_SAI_CR4_FSD_MSTR; break; + case SND_SOC_DAIFMT_CBS_CFM: + val_cr2 |= FSL_SAI_CR2_BCD_MSTR; + val_cr4 &= ~FSL_SAI_CR4_FSD_MSTR; + break; + case SND_SOC_DAIFMT_CBM_CFS: + val_cr2 &= ~FSL_SAI_CR2_BCD_MSTR; + val_cr4 |= FSL_SAI_CR4_FSD_MSTR; + break; default: return -EINVAL; } - sai_writel(sai, val_cr2, sai->base + reg_cr2); - sai_writel(sai, val_cr4, sai->base + reg_cr4); + regmap_write(sai->regmap, reg_cr2, val_cr2); + regmap_write(sai->regmap, reg_cr4, val_cr4); return 0; } static int fsl_sai_set_dai_fmt(struct snd_soc_dai *cpu_dai, unsigned int fmt) { - struct fsl_sai *sai = snd_soc_dai_get_drvdata(cpu_dai); int ret; - ret = clk_prepare_enable(sai->clk); - if (ret) - return ret; - ret = fsl_sai_set_dai_fmt_tr(cpu_dai, fmt, FSL_FMT_TRANSMITTER); if (ret) { dev_err(cpu_dai->dev, "Cannot set tx format: %d\n", ret); - goto err_clk; + return ret; } ret = fsl_sai_set_dai_fmt_tr(cpu_dai, fmt, FSL_FMT_RECEIVER); - if (ret) { + if (ret) dev_err(cpu_dai->dev, "Cannot set rx format: %d\n", ret); - goto err_clk; - } - -err_clk: - clk_disable_unprepare(sai->clk); return ret; } @@ -235,16 +238,19 @@ static int fsl_sai_hw_params(struct snd_pcm_substream *substream, reg_mr = FSL_SAI_RMR; } - val_cr4 = sai_readl(sai, sai->base + reg_cr4); + regmap_read(sai->regmap, reg_cr4, &val_cr4); + regmap_read(sai->regmap, reg_cr4, &val_cr5); + val_cr4 &= ~FSL_SAI_CR4_SYWD_MASK; val_cr4 &= ~FSL_SAI_CR4_FRSZ_MASK; - val_cr5 = sai_readl(sai, sai->base + reg_cr5); val_cr5 &= ~FSL_SAI_CR5_WNW_MASK; val_cr5 &= ~FSL_SAI_CR5_W0W_MASK; val_cr5 &= ~FSL_SAI_CR5_FBT_MASK; - val_cr4 |= FSL_SAI_CR4_SYWD(word_width); + if (!sai->is_dsp_mode) + val_cr4 |= FSL_SAI_CR4_SYWD(word_width); + val_cr5 |= FSL_SAI_CR5_WNW(word_width); val_cr5 |= FSL_SAI_CR5_W0W(word_width); @@ -257,9 +263,9 @@ static int fsl_sai_hw_params(struct snd_pcm_substream *substream, val_cr4 |= FSL_SAI_CR4_FRSZ(channels); val_mr = ~0UL - ((1 << channels) - 1); - sai_writel(sai, val_cr4, sai->base + reg_cr4); - sai_writel(sai, val_cr5, sai->base + reg_cr5); - sai_writel(sai, val_mr, sai->base + reg_mr); + regmap_write(sai->regmap, reg_cr4, val_cr4); + regmap_write(sai->regmap, reg_cr5, val_cr5); + regmap_write(sai->regmap, reg_mr, val_mr); return 0; } @@ -268,44 +274,42 @@ static int fsl_sai_trigger(struct snd_pcm_substream *substream, int cmd, struct snd_soc_dai *cpu_dai) { struct fsl_sai *sai = snd_soc_dai_get_drvdata(cpu_dai); - u32 tcsr, rcsr, val_cr2, val_cr3, reg_cr3; - - val_cr2 = sai_readl(sai, sai->base + FSL_SAI_TCR2); - val_cr2 &= ~FSL_SAI_CR2_SYNC; - sai_writel(sai, val_cr2, sai->base + FSL_SAI_TCR2); + u32 tcsr, rcsr; - val_cr2 = sai_readl(sai, sai->base + FSL_SAI_RCR2); - val_cr2 |= FSL_SAI_CR2_SYNC; - sai_writel(sai, val_cr2, sai->base + FSL_SAI_RCR2); + /* + * The transmitter bit clock and frame sync are to be + * used by both the transmitter and receiver. + */ + regmap_update_bits(sai->regmap, FSL_SAI_TCR2, FSL_SAI_CR2_SYNC, + ~FSL_SAI_CR2_SYNC); + regmap_update_bits(sai->regmap, FSL_SAI_RCR2, FSL_SAI_CR2_SYNC, + FSL_SAI_CR2_SYNC); - tcsr = sai_readl(sai, sai->base + FSL_SAI_TCSR); - rcsr = sai_readl(sai, sai->base + FSL_SAI_RCSR); + regmap_read(sai->regmap, FSL_SAI_TCSR, &tcsr); + regmap_read(sai->regmap, FSL_SAI_RCSR, &rcsr); if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { tcsr |= FSL_SAI_CSR_FRDE; rcsr &= ~FSL_SAI_CSR_FRDE; - reg_cr3 = FSL_SAI_TCR3; } else { rcsr |= FSL_SAI_CSR_FRDE; tcsr &= ~FSL_SAI_CSR_FRDE; - reg_cr3 = FSL_SAI_RCR3; } - val_cr3 = sai_readl(sai, sai->base + reg_cr3); - + /* + * It is recommended that the transmitter is the last enabled + * and the first disabled. + */ switch (cmd) { case SNDRV_PCM_TRIGGER_START: case SNDRV_PCM_TRIGGER_RESUME: case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: tcsr |= FSL_SAI_CSR_TERE; rcsr |= FSL_SAI_CSR_TERE; - val_cr3 |= FSL_SAI_CR3_TRCE; - sai_writel(sai, val_cr3, sai->base + reg_cr3); - sai_writel(sai, rcsr, sai->base + FSL_SAI_RCSR); - sai_writel(sai, tcsr, sai->base + FSL_SAI_TCSR); + regmap_write(sai->regmap, FSL_SAI_RCSR, rcsr); + regmap_write(sai->regmap, FSL_SAI_TCSR, tcsr); break; - case SNDRV_PCM_TRIGGER_STOP: case SNDRV_PCM_TRIGGER_SUSPEND: case SNDRV_PCM_TRIGGER_PAUSE_PUSH: @@ -314,11 +318,8 @@ static int fsl_sai_trigger(struct snd_pcm_substream *substream, int cmd, rcsr &= ~FSL_SAI_CSR_TERE; } - val_cr3 &= ~FSL_SAI_CR3_TRCE; - - sai_writel(sai, tcsr, sai->base + FSL_SAI_TCSR); - sai_writel(sai, rcsr, sai->base + FSL_SAI_RCSR); - sai_writel(sai, val_cr3, sai->base + reg_cr3); + regmap_write(sai->regmap, FSL_SAI_TCSR, tcsr); + regmap_write(sai->regmap, FSL_SAI_RCSR, rcsr); break; default: return -EINVAL; @@ -331,16 +332,32 @@ static int fsl_sai_startup(struct snd_pcm_substream *substream, struct snd_soc_dai *cpu_dai) { struct fsl_sai *sai = snd_soc_dai_get_drvdata(cpu_dai); + u32 reg; + + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) + reg = FSL_SAI_TCR3; + else + reg = FSL_SAI_RCR3; + + regmap_update_bits(sai->regmap, reg, FSL_SAI_CR3_TRCE, + FSL_SAI_CR3_TRCE); - return clk_prepare_enable(sai->clk); + return 0; } static void fsl_sai_shutdown(struct snd_pcm_substream *substream, struct snd_soc_dai *cpu_dai) { struct fsl_sai *sai = snd_soc_dai_get_drvdata(cpu_dai); + u32 reg; + + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) + reg = FSL_SAI_TCR3; + else + reg = FSL_SAI_RCR3; - clk_disable_unprepare(sai->clk); + regmap_update_bits(sai->regmap, reg, FSL_SAI_CR3_TRCE, + ~FSL_SAI_CR3_TRCE); } static const struct snd_soc_dai_ops fsl_sai_pcm_dai_ops = { @@ -355,18 +372,13 @@ static const struct snd_soc_dai_ops fsl_sai_pcm_dai_ops = { static int fsl_sai_dai_probe(struct snd_soc_dai *cpu_dai) { struct fsl_sai *sai = dev_get_drvdata(cpu_dai->dev); - int ret; - ret = clk_prepare_enable(sai->clk); - if (ret) - return ret; - - sai_writel(sai, 0x0, sai->base + FSL_SAI_RCSR); - sai_writel(sai, 0x0, sai->base + FSL_SAI_TCSR); - sai_writel(sai, FSL_SAI_MAXBURST_TX * 2, sai->base + FSL_SAI_TCR1); - sai_writel(sai, FSL_SAI_MAXBURST_RX - 1, sai->base + FSL_SAI_RCR1); - - clk_disable_unprepare(sai->clk); + regmap_update_bits(sai->regmap, FSL_SAI_TCSR, 0xffffffff, 0x0); + regmap_update_bits(sai->regmap, FSL_SAI_RCSR, 0xffffffff, 0x0); + regmap_update_bits(sai->regmap, FSL_SAI_TCR1, FSL_SAI_CR1_RFW_MASK, + FSL_SAI_MAXBURST_TX * 2); + regmap_update_bits(sai->regmap, FSL_SAI_RCR1, FSL_SAI_CR1_RFW_MASK, + FSL_SAI_MAXBURST_RX - 1); snd_soc_dai_init_dma_data(cpu_dai, &sai->dma_params_tx, &sai->dma_params_rx); @@ -397,26 +409,109 @@ static const struct snd_soc_component_driver fsl_component = { .name = "fsl-sai", }; +static bool fsl_sai_readable_reg(struct device *dev, unsigned int reg) +{ + switch (reg) { + case FSL_SAI_TCSR: + case FSL_SAI_TCR1: + case FSL_SAI_TCR2: + case FSL_SAI_TCR3: + case FSL_SAI_TCR4: + case FSL_SAI_TCR5: + case FSL_SAI_TFR: + case FSL_SAI_TMR: + case FSL_SAI_RCSR: + case FSL_SAI_RCR1: + case FSL_SAI_RCR2: + case FSL_SAI_RCR3: + case FSL_SAI_RCR4: + case FSL_SAI_RCR5: + case FSL_SAI_RDR: + case FSL_SAI_RFR: + case FSL_SAI_RMR: + return true; + default: + return false; + } +} + +static bool fsl_sai_volatile_reg(struct device *dev, unsigned int reg) +{ + switch (reg) { + case FSL_SAI_TFR: + case FSL_SAI_RFR: + case FSL_SAI_TDR: + case FSL_SAI_RDR: + return true; + default: + return false; + } + +} + +static bool fsl_sai_writeable_reg(struct device *dev, unsigned int reg) +{ + switch (reg) { + case FSL_SAI_TCSR: + case FSL_SAI_TCR1: + case FSL_SAI_TCR2: + case FSL_SAI_TCR3: + case FSL_SAI_TCR4: + case FSL_SAI_TCR5: + case FSL_SAI_TDR: + case FSL_SAI_TMR: + case FSL_SAI_RCSR: + case FSL_SAI_RCR1: + case FSL_SAI_RCR2: + case FSL_SAI_RCR3: + case FSL_SAI_RCR4: + case FSL_SAI_RCR5: + case FSL_SAI_RMR: + return true; + default: + return false; + } +} + +static struct regmap_config fsl_sai_regmap_config = { + .reg_bits = 32, + .reg_stride = 4, + .val_bits = 32, + + .max_register = FSL_SAI_RMR, + .readable_reg = fsl_sai_readable_reg, + .volatile_reg = fsl_sai_volatile_reg, + .writeable_reg = fsl_sai_writeable_reg, +}; + static int fsl_sai_probe(struct platform_device *pdev) { struct device_node *np = pdev->dev.of_node; struct fsl_sai *sai; struct resource *res; + void __iomem *base; int ret; sai = devm_kzalloc(&pdev->dev, sizeof(*sai), GFP_KERNEL); if (!sai) return -ENOMEM; + sai->big_endian_regs = of_property_read_bool(np, "big-endian-regs"); + if (sai->big_endian_regs) + fsl_sai_regmap_config.val_format_endian = REGMAP_ENDIAN_BIG; + + sai->big_endian_data = of_property_read_bool(np, "big-endian-data"); + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - sai->base = devm_ioremap_resource(&pdev->dev, res); - if (IS_ERR(sai->base)) - return PTR_ERR(sai->base); - - sai->clk = devm_clk_get(&pdev->dev, "sai"); - if (IS_ERR(sai->clk)) { - dev_err(&pdev->dev, "Cannot get SAI's clock\n"); - return PTR_ERR(sai->clk); + base = devm_ioremap_resource(&pdev->dev, res); + if (IS_ERR(base)) + return PTR_ERR(base); + + sai->regmap = devm_regmap_init_mmio_clk(&pdev->dev, + "sai", base, &fsl_sai_regmap_config); + if (IS_ERR(sai->regmap)) { + dev_err(&pdev->dev, "regmap init failed\n"); + return PTR_ERR(sai->regmap); } sai->dma_params_rx.addr = res->start + FSL_SAI_RDR; @@ -424,9 +519,6 @@ static int fsl_sai_probe(struct platform_device *pdev) sai->dma_params_rx.maxburst = FSL_SAI_MAXBURST_RX; sai->dma_params_tx.maxburst = FSL_SAI_MAXBURST_TX; - sai->big_endian_regs = of_property_read_bool(np, "big-endian-regs"); - sai->big_endian_data = of_property_read_bool(np, "big-endian-data"); - platform_set_drvdata(pdev, sai); ret = devm_snd_soc_register_component(&pdev->dev, &fsl_component, diff --git a/sound/soc/fsl/fsl_sai.h b/sound/soc/fsl/fsl_sai.h index 41bb62e6936..e432260be59 100644 --- a/sound/soc/fsl/fsl_sai.h +++ b/sound/soc/fsl/fsl_sai.h @@ -15,31 +15,36 @@ SNDRV_PCM_FMTBIT_S20_3LE |\ SNDRV_PCM_FMTBIT_S24_LE) +/* SAI Register Map Register */ +#define FSL_SAI_TCSR 0x00 /* SAI Transmit Control */ +#define FSL_SAI_TCR1 0x04 /* SAI Transmit Configuration 1 */ +#define FSL_SAI_TCR2 0x08 /* SAI Transmit Configuration 2 */ +#define FSL_SAI_TCR3 0x0c /* SAI Transmit Configuration 3 */ +#define FSL_SAI_TCR4 0x10 /* SAI Transmit Configuration 4 */ +#define FSL_SAI_TCR5 0x14 /* SAI Transmit Configuration 5 */ +#define FSL_SAI_TDR 0x20 /* SAI Transmit Data */ +#define FSL_SAI_TFR 0x40 /* SAI Transmit FIFO */ +#define FSL_SAI_TMR 0x60 /* SAI Transmit Mask */ +#define FSL_SAI_RCSR 0x80 /* SAI Receive Control */ +#define FSL_SAI_RCR1 0x84 /* SAI Receive Configuration 1 */ +#define FSL_SAI_RCR2 0x88 /* SAI Receive Configuration 2 */ +#define FSL_SAI_RCR3 0x8c /* SAI Receive Configuration 3 */ +#define FSL_SAI_RCR4 0x90 /* SAI Receive Configuration 4 */ +#define FSL_SAI_RCR5 0x94 /* SAI Receive Configuration 5 */ +#define FSL_SAI_RDR 0xa0 /* SAI Receive Data */ +#define FSL_SAI_RFR 0xc0 /* SAI Receive FIFO */ +#define FSL_SAI_RMR 0xe0 /* SAI Receive Mask */ + /* SAI Transmit/Recieve Control Register */ -#define FSL_SAI_TCSR 0x00 -#define FSL_SAI_RCSR 0x80 #define FSL_SAI_CSR_TERE BIT(31) #define FSL_SAI_CSR_FWF BIT(17) #define FSL_SAI_CSR_FRIE BIT(8) #define FSL_SAI_CSR_FRDE BIT(0) -/* SAI Transmit Data/FIFO/MASK Register */ -#define FSL_SAI_TDR 0x20 -#define FSL_SAI_TFR 0x40 -#define FSL_SAI_TMR 0x60 - -/* SAI Recieve Data/FIFO/MASK Register */ -#define FSL_SAI_RDR 0xa0 -#define FSL_SAI_RFR 0xc0 -#define FSL_SAI_RMR 0xe0 - /* SAI Transmit and Recieve Configuration 1 Register */ -#define FSL_SAI_TCR1 0x04 -#define FSL_SAI_RCR1 0x84 +#define FSL_SAI_CR1_RFW_MASK 0x1f /* SAI Transmit and Recieve Configuration 2 Register */ -#define FSL_SAI_TCR2 0x08 -#define FSL_SAI_RCR2 0x88 #define FSL_SAI_CR2_SYNC BIT(30) #define FSL_SAI_CR2_MSEL_MASK (0xff << 26) #define FSL_SAI_CR2_MSEL_BUS 0 @@ -50,15 +55,11 @@ #define FSL_SAI_CR2_BCD_MSTR BIT(24) /* SAI Transmit and Recieve Configuration 3 Register */ -#define FSL_SAI_TCR3 0x0c -#define FSL_SAI_RCR3 0x8c #define FSL_SAI_CR3_TRCE BIT(16) #define FSL_SAI_CR3_WDFL(x) (x) #define FSL_SAI_CR3_WDFL_MASK 0x1f /* SAI Transmit and Recieve Configuration 4 Register */ -#define FSL_SAI_TCR4 0x10 -#define FSL_SAI_RCR4 0x90 #define FSL_SAI_CR4_FRSZ(x) (((x) - 1) << 16) #define FSL_SAI_CR4_FRSZ_MASK (0x1f << 16) #define FSL_SAI_CR4_SYWD(x) (((x) - 1) << 8) @@ -69,8 +70,6 @@ #define FSL_SAI_CR4_FSD_MSTR BIT(0) /* SAI Transmit and Recieve Configuration 5 Register */ -#define FSL_SAI_TCR5 0x14 -#define FSL_SAI_RCR5 0x94 #define FSL_SAI_CR5_WNW(x) (((x) - 1) << 24) #define FSL_SAI_CR5_WNW_MASK (0x1f << 24) #define FSL_SAI_CR5_W0W(x) (((x) - 1) << 16) @@ -100,12 +99,11 @@ #define FSL_SAI_MAXBURST_RX 6 struct fsl_sai { - struct clk *clk; - - void __iomem *base; + struct regmap *regmap; bool big_endian_regs; bool big_endian_data; + bool is_dsp_mode; struct snd_dmaengine_dai_dma_data dma_params_rx; struct snd_dmaengine_dai_dma_data dma_params_tx; diff --git a/sound/soc/fsl/fsl_spdif.c b/sound/soc/fsl/fsl_spdif.c index 4d075f1abe7..6452ca83d88 100644 --- a/sound/soc/fsl/fsl_spdif.c +++ b/sound/soc/fsl/fsl_spdif.c @@ -911,8 +911,8 @@ static int fsl_spdif_dai_probe(struct snd_soc_dai *dai) { struct fsl_spdif_priv *spdif_private = snd_soc_dai_get_drvdata(dai); - dai->playback_dma_data = &spdif_private->dma_params_tx; - dai->capture_dma_data = &spdif_private->dma_params_rx; + snd_soc_dai_init_dma_data(dai, &spdif_private->dma_params_tx, + &spdif_private->dma_params_rx); snd_soc_add_dai_controls(dai, fsl_spdif_ctrls, ARRAY_SIZE(fsl_spdif_ctrls)); @@ -985,7 +985,7 @@ static bool fsl_spdif_writeable_reg(struct device *dev, unsigned int reg) } } -static const struct regmap_config fsl_spdif_regmap_config = { +static struct regmap_config fsl_spdif_regmap_config = { .reg_bits = 32, .reg_stride = 4, .val_bits = 32, @@ -1105,6 +1105,9 @@ static int fsl_spdif_probe(struct platform_device *pdev) memcpy(&spdif_priv->cpu_dai_drv, &fsl_spdif_dai, sizeof(fsl_spdif_dai)); spdif_priv->cpu_dai_drv.name = spdif_priv->name; + if (of_property_read_bool(np, "big-endian")) + fsl_spdif_regmap_config.val_format_endian = REGMAP_ENDIAN_BIG; + /* Get the addresses and IRQ */ res = platform_get_resource(pdev, IORESOURCE_MEM, 0); regs = devm_ioremap_resource(&pdev->dev, res); diff --git a/sound/soc/fsl/fsl_utils.c b/sound/soc/fsl/fsl_utils.c index b9e42b503a3..2ac7755da87 100644 --- a/sound/soc/fsl/fsl_utils.c +++ b/sound/soc/fsl/fsl_utils.c @@ -86,6 +86,33 @@ int fsl_asoc_get_dma_channel(struct device_node *ssi_np, } EXPORT_SYMBOL(fsl_asoc_get_dma_channel); +/** + * fsl_asoc_xlate_tdm_slot_mask - generate TDM slot TX/RX mask. + * + * @slots: Number of slots in use. + * @tx_mask: bitmask representing active TX slots. + * @rx_mask: bitmask representing active RX slots. + * + * This function used to generate the TDM slot TX/RX mask. And the TX/RX + * mask will use a 0 bit for an active slot as default, and the default + * active bits are at the LSB of the mask value. + */ +int fsl_asoc_xlate_tdm_slot_mask(unsigned int slots, + unsigned int *tx_mask, + unsigned int *rx_mask) +{ + if (!slots) + return -EINVAL; + + if (tx_mask) + *tx_mask = ~((1 << slots) - 1); + if (rx_mask) + *rx_mask = ~((1 << slots) - 1); + + return 0; +} +EXPORT_SYMBOL_GPL(fsl_asoc_xlate_tdm_slot_mask); + MODULE_AUTHOR("Timur Tabi <timur@freescale.com>"); MODULE_DESCRIPTION("Freescale ASoC utility code"); MODULE_LICENSE("GPL v2"); diff --git a/sound/soc/fsl/fsl_utils.h b/sound/soc/fsl/fsl_utils.h index b2951126527..df535db4031 100644 --- a/sound/soc/fsl/fsl_utils.h +++ b/sound/soc/fsl/fsl_utils.h @@ -22,5 +22,7 @@ int fsl_asoc_get_dma_channel(struct device_node *ssi_np, const char *name, struct snd_soc_dai_link *dai, unsigned int *dma_channel_id, unsigned int *dma_id); - +int fsl_asoc_xlate_tdm_slot_mask(unsigned int slots, + unsigned int *tx_mask, + unsigned int *rx_mask); #endif /* _FSL_UTILS_H */ diff --git a/sound/soc/fsl/imx-pcm-fiq.c b/sound/soc/fsl/imx-pcm-fiq.c index 6553202dd48..7abf6a07957 100644 --- a/sound/soc/fsl/imx-pcm-fiq.c +++ b/sound/soc/fsl/imx-pcm-fiq.c @@ -270,18 +270,17 @@ static int imx_pcm_new(struct snd_soc_pcm_runtime *rtd) ret = imx_pcm_preallocate_dma_buffer(pcm, SNDRV_PCM_STREAM_PLAYBACK); if (ret) - goto out; + return ret; } if (pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream) { ret = imx_pcm_preallocate_dma_buffer(pcm, SNDRV_PCM_STREAM_CAPTURE); if (ret) - goto out; + return ret; } -out: - return ret; + return 0; } static int ssi_irq = 0; diff --git a/sound/soc/fsl/imx-ssi.c b/sound/soc/fsl/imx-ssi.c index df552fa1aa6..ab2fdd76b69 100644 --- a/sound/soc/fsl/imx-ssi.c +++ b/sound/soc/fsl/imx-ssi.c @@ -50,6 +50,7 @@ #include <linux/platform_data/asoc-imx-ssi.h> #include "imx-ssi.h" +#include "fsl_utils.h" #define SSI_SACNT_DEFAULT (SSI_SACNT_AC97EN | SSI_SACNT_FV) @@ -339,6 +340,7 @@ static const struct snd_soc_dai_ops imx_ssi_pcm_dai_ops = { .set_fmt = imx_ssi_set_dai_fmt, .set_clkdiv = imx_ssi_set_dai_clkdiv, .set_sysclk = imx_ssi_set_dai_sysclk, + .xlate_tdm_slot_mask = fsl_asoc_xlate_tdm_slot_mask, .set_tdm_slot = imx_ssi_set_dai_tdm_slot, .trigger = imx_ssi_trigger, }; diff --git a/sound/soc/fsl/wm1133-ev1.c b/sound/soc/fsl/wm1133-ev1.c index fce63252bdb..804749a6c61 100644 --- a/sound/soc/fsl/wm1133-ev1.c +++ b/sound/soc/fsl/wm1133-ev1.c @@ -214,12 +214,6 @@ static int wm1133_ev1_init(struct snd_soc_pcm_runtime *rtd) struct snd_soc_codec *codec = rtd->codec; struct snd_soc_dapm_context *dapm = &codec->dapm; - snd_soc_dapm_new_controls(dapm, wm1133_ev1_widgets, - ARRAY_SIZE(wm1133_ev1_widgets)); - - snd_soc_dapm_add_routes(dapm, wm1133_ev1_map, - ARRAY_SIZE(wm1133_ev1_map)); - /* Headphone jack detection */ snd_soc_jack_new(codec, "Headphone", SND_JACK_HEADPHONE, &hp_jack); snd_soc_jack_add_pins(&hp_jack, ARRAY_SIZE(hp_jack_pins), @@ -257,6 +251,11 @@ static struct snd_soc_card wm1133_ev1 = { .owner = THIS_MODULE, .dai_link = &wm1133_ev1_dai, .num_links = 1, + + .dapm_widgets = wm1133_ev1_widgets, + .num_dapm_widgets = ARRAY_SIZE(wm1133_ev1_widgets), + .dapm_routes = wm1133_ev1_map, + .num_dapm_routes = ARRAY_SIZE(wm1133_ev1_map), }; static struct platform_device *wm1133_ev1_snd_device; diff --git a/sound/soc/generic/simple-card.c b/sound/soc/generic/simple-card.c index 2a1b1b5b522..21f1ccbdf58 100644 --- a/sound/soc/generic/simple-card.c +++ b/sound/soc/generic/simple-card.c @@ -9,48 +9,77 @@ * published by the Free Software Foundation. */ #include <linux/clk.h> +#include <linux/device.h> #include <linux/module.h> #include <linux/of.h> #include <linux/platform_device.h> #include <linux/string.h> #include <sound/simple_card.h> +#include <sound/soc-dai.h> +#include <sound/soc.h> + +struct simple_card_data { + struct snd_soc_card snd_card; + struct simple_dai_props { + struct asoc_simple_dai cpu_dai; + struct asoc_simple_dai codec_dai; + } *dai_props; + struct snd_soc_dai_link dai_link[]; /* dynamically allocated */ +}; static int __asoc_simple_card_dai_init(struct snd_soc_dai *dai, - struct asoc_simple_dai *set, - unsigned int daifmt) + struct asoc_simple_dai *set) { - int ret = 0; + int ret; - daifmt |= set->fmt; + if (set->fmt) { + ret = snd_soc_dai_set_fmt(dai, set->fmt); + if (ret && ret != -ENOTSUPP) { + dev_err(dai->dev, "simple-card: set_fmt error\n"); + goto err; + } + } - if (daifmt) - ret = snd_soc_dai_set_fmt(dai, daifmt); + if (set->sysclk) { + ret = snd_soc_dai_set_sysclk(dai, 0, set->sysclk, 0); + if (ret && ret != -ENOTSUPP) { + dev_err(dai->dev, "simple-card: set_sysclk error\n"); + goto err; + } + } - if (ret == -ENOTSUPP) { - dev_dbg(dai->dev, "ASoC: set_fmt is not supported\n"); - ret = 0; + if (set->slots) { + ret = snd_soc_dai_set_tdm_slot(dai, 0, 0, + set->slots, + set->slot_width); + if (ret && ret != -ENOTSUPP) { + dev_err(dai->dev, "simple-card: set_tdm_slot error\n"); + goto err; + } } - if (!ret && set->sysclk) - ret = snd_soc_dai_set_sysclk(dai, 0, set->sysclk, 0); + ret = 0; +err: return ret; } static int asoc_simple_card_dai_init(struct snd_soc_pcm_runtime *rtd) { - struct asoc_simple_card_info *info = + struct simple_card_data *priv = snd_soc_card_get_drvdata(rtd->card); struct snd_soc_dai *codec = rtd->codec_dai; struct snd_soc_dai *cpu = rtd->cpu_dai; - unsigned int daifmt = info->daifmt; - int ret; + struct simple_dai_props *dai_props; + int num, ret; - ret = __asoc_simple_card_dai_init(codec, &info->codec_dai, daifmt); + num = rtd - rtd->card->rtd; + dai_props = &priv->dai_props[num]; + ret = __asoc_simple_card_dai_init(codec, &dai_props->codec_dai); if (ret < 0) return ret; - ret = __asoc_simple_card_dai_init(cpu, &info->cpu_dai, daifmt); + ret = __asoc_simple_card_dai_init(cpu, &dai_props->cpu_dai); if (ret < 0) return ret; @@ -59,9 +88,12 @@ static int asoc_simple_card_dai_init(struct snd_soc_pcm_runtime *rtd) static int asoc_simple_card_sub_parse_of(struct device_node *np, + unsigned int daifmt, struct asoc_simple_dai *dai, - struct device_node **node) + const struct device_node **p_node, + const char **name) { + struct device_node *node; struct clk *clk; int ret; @@ -69,14 +101,20 @@ asoc_simple_card_sub_parse_of(struct device_node *np, * get node via "sound-dai = <&phandle port>" * it will be used as xxx_of_node on soc_bind_dai_link() */ - *node = of_parse_phandle(np, "sound-dai", 0); - if (!*node) + node = of_parse_phandle(np, "sound-dai", 0); + if (!node) return -ENODEV; + *p_node = node; /* get dai->name */ - ret = snd_soc_of_get_dai_name(np, &dai->name); + ret = snd_soc_of_get_dai_name(np, name); if (ret < 0) - goto parse_error; + return ret; + + /* parse TDM slot */ + ret = snd_soc_of_parse_tdm_slot(np, &dai->slots, &dai->slot_width); + if (ret) + return ret; /* * bitclock-inversion, frame-inversion @@ -84,6 +122,7 @@ asoc_simple_card_sub_parse_of(struct device_node *np, * and specific "format" if it has */ dai->fmt = snd_soc_of_parse_daifmt(np, NULL); + dai->fmt |= daifmt; /* * dai->sysclk come from @@ -95,7 +134,7 @@ asoc_simple_card_sub_parse_of(struct device_node *np, clk = of_clk_get(np, 0); if (IS_ERR(clk)) { ret = PTR_ERR(clk); - goto parse_error; + return ret; } dai->sysclk = clk_get_rate(clk); @@ -104,164 +143,278 @@ asoc_simple_card_sub_parse_of(struct device_node *np, "system-clock-frequency", &dai->sysclk); } else { - clk = of_clk_get(*node, 0); + clk = of_clk_get(node, 0); if (!IS_ERR(clk)) dai->sysclk = clk_get_rate(clk); } - ret = 0; + return 0; +} + +static int simple_card_cpu_codec_of(struct device_node *node, + int daifmt, + struct snd_soc_dai_link *dai_link, + struct simple_dai_props *dai_props) +{ + struct device_node *np; + int ret; -parse_error: - of_node_put(*node); + /* CPU sub-node */ + ret = -EINVAL; + np = of_get_child_by_name(node, "simple-audio-card,cpu"); + if (np) { + ret = asoc_simple_card_sub_parse_of(np, daifmt, + &dai_props->cpu_dai, + &dai_link->cpu_of_node, + &dai_link->cpu_dai_name); + of_node_put(np); + } + if (ret < 0) + return ret; + /* CODEC sub-node */ + ret = -EINVAL; + np = of_get_child_by_name(node, "simple-audio-card,codec"); + if (np) { + ret = asoc_simple_card_sub_parse_of(np, daifmt, + &dai_props->codec_dai, + &dai_link->codec_of_node, + &dai_link->codec_dai_name); + of_node_put(np); + } return ret; } static int asoc_simple_card_parse_of(struct device_node *node, - struct asoc_simple_card_info *info, + struct simple_card_data *priv, struct device *dev, - struct device_node **of_cpu, - struct device_node **of_codec, - struct device_node **of_platform) + int multi) { + struct snd_soc_dai_link *dai_link = priv->snd_card.dai_link; + struct simple_dai_props *dai_props = priv->dai_props; struct device_node *np; char *name; + unsigned int daifmt; int ret; + /* parsing the card name from DT */ + snd_soc_of_parse_card_name(&priv->snd_card, "simple-audio-card,name"); + /* get CPU/CODEC common format via simple-audio-card,format */ - info->daifmt = snd_soc_of_parse_daifmt(node, "simple-audio-card,") & + daifmt = snd_soc_of_parse_daifmt(node, "simple-audio-card,") & (SND_SOC_DAIFMT_FORMAT_MASK | SND_SOC_DAIFMT_INV_MASK); + /* off-codec widgets */ + if (of_property_read_bool(node, "simple-audio-card,widgets")) { + ret = snd_soc_of_parse_audio_simple_widgets(&priv->snd_card, + "simple-audio-card,widgets"); + if (ret) + return ret; + } + /* DAPM routes */ if (of_property_read_bool(node, "simple-audio-card,routing")) { - ret = snd_soc_of_parse_audio_routing(&info->snd_card, + ret = snd_soc_of_parse_audio_routing(&priv->snd_card, "simple-audio-card,routing"); if (ret) return ret; } - /* CPU sub-node */ - ret = -EINVAL; - np = of_get_child_by_name(node, "simple-audio-card,cpu"); - if (np) - ret = asoc_simple_card_sub_parse_of(np, - &info->cpu_dai, - of_cpu); - if (ret < 0) - return ret; + /* loop on the DAI links */ + np = NULL; + for (;;) { + if (multi) { + np = of_get_next_child(node, np); + if (!np) + break; + } - /* CODEC sub-node */ - ret = -EINVAL; - np = of_get_child_by_name(node, "simple-audio-card,codec"); - if (np) - ret = asoc_simple_card_sub_parse_of(np, - &info->codec_dai, - of_codec); - if (ret < 0) - return ret; + ret = simple_card_cpu_codec_of(multi ? np : node, + daifmt, dai_link, dai_props); + if (ret < 0) + goto err; + + /* + * overwrite cpu_dai->fmt as its DAIFMT_MASTER bit is based on CODEC + * while the other bits should be identical unless buggy SW/HW design. + */ + dai_props->cpu_dai.fmt = dai_props->codec_dai.fmt; + + if (!dai_link->cpu_dai_name || !dai_link->codec_dai_name) { + ret = -EINVAL; + goto err; + } + + /* simple-card assumes platform == cpu */ + dai_link->platform_of_node = dai_link->cpu_of_node; + + name = devm_kzalloc(dev, + strlen(dai_link->cpu_dai_name) + + strlen(dai_link->codec_dai_name) + 2, + GFP_KERNEL); + sprintf(name, "%s-%s", dai_link->cpu_dai_name, + dai_link->codec_dai_name); + dai_link->name = dai_link->stream_name = name; - if (!info->cpu_dai.name || !info->codec_dai.name) - return -EINVAL; + if (!multi) + break; + + dai_link++; + dai_props++; + } /* card name is created from CPU/CODEC dai name */ - name = devm_kzalloc(dev, - strlen(info->cpu_dai.name) + - strlen(info->codec_dai.name) + 2, - GFP_KERNEL); - sprintf(name, "%s-%s", info->cpu_dai.name, info->codec_dai.name); - info->name = info->card = name; - - /* simple-card assumes platform == cpu */ - *of_platform = *of_cpu; - - dev_dbg(dev, "card-name : %s\n", info->card); - dev_dbg(dev, "platform : %04x\n", info->daifmt); + dai_link = priv->snd_card.dai_link; + if (!priv->snd_card.name) + priv->snd_card.name = dai_link->name; + + dev_dbg(dev, "card-name : %s\n", priv->snd_card.name); + dev_dbg(dev, "platform : %04x\n", daifmt); + dai_props = priv->dai_props; dev_dbg(dev, "cpu : %s / %04x / %d\n", - info->cpu_dai.name, - info->cpu_dai.fmt, - info->cpu_dai.sysclk); + dai_link->cpu_dai_name, + dai_props->cpu_dai.fmt, + dai_props->cpu_dai.sysclk); dev_dbg(dev, "codec : %s / %04x / %d\n", - info->codec_dai.name, - info->codec_dai.fmt, - info->codec_dai.sysclk); + dai_link->codec_dai_name, + dai_props->codec_dai.fmt, + dai_props->codec_dai.sysclk); return 0; + +err: + of_node_put(np); + return ret; +} + +/* update the reference count of the devices nodes at end of probe */ +static int asoc_simple_card_unref(struct platform_device *pdev) +{ + struct snd_soc_card *card = platform_get_drvdata(pdev); + struct snd_soc_dai_link *dai_link; + struct device_node *np; + int num_links; + + for (num_links = 0, dai_link = card->dai_link; + num_links < card->num_links; + num_links++, dai_link++) { + np = (struct device_node *) dai_link->cpu_of_node; + if (np) + of_node_put(np); + np = (struct device_node *) dai_link->codec_of_node; + if (np) + of_node_put(np); + } + return 0; } static int asoc_simple_card_probe(struct platform_device *pdev) { - struct asoc_simple_card_info *cinfo; + struct simple_card_data *priv; + struct snd_soc_dai_link *dai_link; struct device_node *np = pdev->dev.of_node; - struct device_node *of_cpu, *of_codec, *of_platform; struct device *dev = &pdev->dev; - int ret; + int num_links, multi, ret; + + /* get the number of DAI links */ + if (np && of_get_child_by_name(np, "simple-audio-card,dai-link")) { + num_links = of_get_child_count(np); + multi = 1; + } else { + num_links = 1; + multi = 0; + } - cinfo = NULL; - of_cpu = NULL; - of_codec = NULL; - of_platform = NULL; + /* allocate the private data and the DAI link array */ + priv = devm_kzalloc(dev, + sizeof(*priv) + sizeof(*dai_link) * num_links, + GFP_KERNEL); + if (!priv) + return -ENOMEM; - cinfo = devm_kzalloc(dev, sizeof(*cinfo), GFP_KERNEL); - if (!cinfo) + /* + * init snd_soc_card + */ + priv->snd_card.owner = THIS_MODULE; + priv->snd_card.dev = dev; + dai_link = priv->dai_link; + priv->snd_card.dai_link = dai_link; + priv->snd_card.num_links = num_links; + + /* get room for the other properties */ + priv->dai_props = devm_kzalloc(dev, + sizeof(*priv->dai_props) * num_links, + GFP_KERNEL); + if (!priv->dai_props) return -ENOMEM; if (np && of_device_is_available(np)) { - cinfo->snd_card.dev = dev; - ret = asoc_simple_card_parse_of(np, cinfo, dev, - &of_cpu, - &of_codec, - &of_platform); + ret = asoc_simple_card_parse_of(np, priv, dev, multi); if (ret < 0) { if (ret != -EPROBE_DEFER) dev_err(dev, "parse error %d\n", ret); - return ret; + goto err; } + + /* + * soc_bind_dai_link() will check cpu name + * after of_node matching if dai_link has cpu_dai_name. + * but, it will never match if name was created by fmt_single_name() + * remove cpu_dai_name to escape name matching. + * see + * fmt_single_name() + * fmt_multiple_name() + */ + if (num_links == 1) + dai_link->cpu_dai_name = NULL; + } else { - if (!dev->platform_data) { + struct asoc_simple_card_info *cinfo; + + cinfo = dev->platform_data; + if (!cinfo) { dev_err(dev, "no info for asoc-simple-card\n"); return -EINVAL; } - memcpy(cinfo, dev->platform_data, sizeof(*cinfo)); - cinfo->snd_card.dev = dev; - } + if (!cinfo->name || + !cinfo->codec_dai.name || + !cinfo->codec || + !cinfo->platform || + !cinfo->cpu_dai.name) { + dev_err(dev, "insufficient asoc_simple_card_info settings\n"); + return -EINVAL; + } - if (!cinfo->name || - !cinfo->card || - !cinfo->codec_dai.name || - !(cinfo->codec || of_codec) || - !(cinfo->platform || of_platform) || - !(cinfo->cpu_dai.name || of_cpu)) { - dev_err(dev, "insufficient asoc_simple_card_info settings\n"); - return -EINVAL; + priv->snd_card.name = (cinfo->card) ? cinfo->card : cinfo->name; + dai_link->name = cinfo->name; + dai_link->stream_name = cinfo->name; + dai_link->platform_name = cinfo->platform; + dai_link->codec_name = cinfo->codec; + dai_link->cpu_dai_name = cinfo->cpu_dai.name; + dai_link->codec_dai_name = cinfo->codec_dai.name; + memcpy(&priv->dai_props->cpu_dai, &cinfo->cpu_dai, + sizeof(priv->dai_props->cpu_dai)); + memcpy(&priv->dai_props->codec_dai, &cinfo->codec_dai, + sizeof(priv->dai_props->codec_dai)); + + priv->dai_props->cpu_dai.fmt |= cinfo->daifmt; + priv->dai_props->codec_dai.fmt |= cinfo->daifmt; } /* * init snd_soc_dai_link */ - cinfo->snd_link.name = cinfo->name; - cinfo->snd_link.stream_name = cinfo->name; - cinfo->snd_link.cpu_dai_name = cinfo->cpu_dai.name; - cinfo->snd_link.platform_name = cinfo->platform; - cinfo->snd_link.codec_name = cinfo->codec; - cinfo->snd_link.codec_dai_name = cinfo->codec_dai.name; - cinfo->snd_link.cpu_of_node = of_cpu; - cinfo->snd_link.codec_of_node = of_codec; - cinfo->snd_link.platform_of_node = of_platform; - cinfo->snd_link.init = asoc_simple_card_dai_init; + dai_link->init = asoc_simple_card_dai_init; - /* - * init snd_soc_card - */ - cinfo->snd_card.name = cinfo->card; - cinfo->snd_card.owner = THIS_MODULE; - cinfo->snd_card.dai_link = &cinfo->snd_link; - cinfo->snd_card.num_links = 1; + snd_soc_card_set_drvdata(&priv->snd_card, priv); - snd_soc_card_set_drvdata(&cinfo->snd_card, cinfo); + ret = devm_snd_soc_register_card(&pdev->dev, &priv->snd_card); - return devm_snd_soc_register_card(&pdev->dev, &cinfo->snd_card); +err: + asoc_simple_card_unref(pdev); + return ret; } static const struct of_device_id asoc_simple_of_match[] = { diff --git a/sound/soc/intel/Kconfig b/sound/soc/intel/Kconfig index 61c10bf503d..3c81b389120 100644 --- a/sound/soc/intel/Kconfig +++ b/sound/soc/intel/Kconfig @@ -2,12 +2,50 @@ config SND_MFLD_MACHINE tristate "SOC Machine Audio driver for Intel Medfield MID platform" depends on INTEL_SCU_IPC select SND_SOC_SN95031 - select SND_SST_PLATFORM + select SND_SST_MFLD_PLATFORM help This adds support for ASoC machine driver for Intel(R) MID Medfield platform used as alsa device in audio substem in Intel(R) MID devices Say Y if you have such a device If unsure select "N". -config SND_SST_PLATFORM +config SND_SST_MFLD_PLATFORM tristate + +config SND_SOC_INTEL_SST + tristate "ASoC support for Intel(R) Smart Sound Technology" + select SND_SOC_INTEL_SST_ACPI if ACPI + depends on (X86 || COMPILE_TEST) + help + This adds support for Intel(R) Smart Sound Technology (SST). + Say Y if you have such a device + If unsure select "N". + +config SND_SOC_INTEL_SST_ACPI + tristate + +config SND_SOC_INTEL_HASWELL + tristate + +config SND_SOC_INTEL_BAYTRAIL + tristate + +config SND_SOC_INTEL_HASWELL_MACH + tristate "ASoC Audio DSP support for Intel Haswell Lynxpoint" + depends on SND_SOC_INTEL_SST && X86_INTEL_LPSS && I2C + select SND_SOC_INTEL_HASWELL + select SND_SOC_RT5640 + help + This adds support for the Lynxpoint Audio DSP on Intel(R) Haswell + Ultrabook platforms. + Say Y if you have such a device + If unsure select "N". + +config SND_SOC_INTEL_BYT_RT5640_MACH + tristate "ASoC Audio driver for Intel Baytrail with RT5640 codec" + depends on SND_SOC_INTEL_SST && X86_INTEL_LPSS && I2C + select SND_SOC_INTEL_BAYTRAIL + select SND_SOC_RT5640 + help + This adds audio driver for Intel Baytrail platform based boards + with the RT5640 audio codec. diff --git a/sound/soc/intel/Makefile b/sound/soc/intel/Makefile index 63988333946..edeb79ae3df 100644 --- a/sound/soc/intel/Makefile +++ b/sound/soc/intel/Makefile @@ -1,5 +1,28 @@ -snd-soc-sst-platform-objs := sst_platform.o +# Core support +snd-soc-sst-dsp-objs := sst-dsp.o sst-firmware.o +snd-soc-sst-acpi-objs := sst-acpi.o + +snd-soc-sst-mfld-platform-objs := sst-mfld-platform.o snd-soc-mfld-machine-objs := mfld_machine.o -obj-$(CONFIG_SND_SST_PLATFORM) += snd-soc-sst-platform.o +obj-$(CONFIG_SND_SST_MFLD_PLATFORM) += snd-soc-sst-mfld-platform.o obj-$(CONFIG_SND_MFLD_MACHINE) += snd-soc-mfld-machine.o + +obj-$(CONFIG_SND_SOC_INTEL_SST) += snd-soc-sst-dsp.o +obj-$(CONFIG_SND_SOC_INTEL_SST_ACPI) += snd-soc-sst-acpi.o + +# Platform Support +snd-soc-sst-haswell-pcm-objs := \ + sst-haswell-ipc.o sst-haswell-pcm.o sst-haswell-dsp.o +snd-soc-sst-baytrail-pcm-objs := \ + sst-baytrail-ipc.o sst-baytrail-pcm.o sst-baytrail-dsp.o + +obj-$(CONFIG_SND_SOC_INTEL_HASWELL) += snd-soc-sst-haswell-pcm.o +obj-$(CONFIG_SND_SOC_INTEL_BAYTRAIL) += snd-soc-sst-baytrail-pcm.o + +# Machine support +snd-soc-sst-haswell-objs := haswell.o +snd-soc-sst-byt-rt5640-mach-objs := byt-rt5640.o + +obj-$(CONFIG_SND_SOC_INTEL_HASWELL_MACH) += snd-soc-sst-haswell.o +obj-$(CONFIG_SND_SOC_INTEL_BYT_RT5640_MACH) += snd-soc-sst-byt-rt5640-mach.o diff --git a/sound/soc/intel/byt-rt5640.c b/sound/soc/intel/byt-rt5640.c new file mode 100644 index 00000000000..eff97c8e521 --- /dev/null +++ b/sound/soc/intel/byt-rt5640.c @@ -0,0 +1,187 @@ +/* + * Intel Baytrail SST RT5640 machine driver + * Copyright (c) 2014, Intel Corporation. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + */ + +#include <linux/init.h> +#include <linux/module.h> +#include <linux/platform_device.h> +#include <linux/acpi.h> +#include <linux/device.h> +#include <linux/slab.h> +#include <sound/pcm.h> +#include <sound/pcm_params.h> +#include <sound/soc.h> +#include <sound/jack.h> +#include "../codecs/rt5640.h" + +#include "sst-dsp.h" + +static const struct snd_soc_dapm_widget byt_rt5640_widgets[] = { + SND_SOC_DAPM_HP("Headphone", NULL), + SND_SOC_DAPM_MIC("Headset Mic", NULL), + SND_SOC_DAPM_MIC("Internal Mic", NULL), + SND_SOC_DAPM_SPK("Speaker", NULL), +}; + +static const struct snd_soc_dapm_route byt_rt5640_audio_map[] = { + {"IN2P", NULL, "Headset Mic"}, + {"IN2N", NULL, "Headset Mic"}, + {"DMIC1", NULL, "Internal Mic"}, + {"Headphone", NULL, "HPOL"}, + {"Headphone", NULL, "HPOR"}, + {"Speaker", NULL, "SPOLP"}, + {"Speaker", NULL, "SPOLN"}, + {"Speaker", NULL, "SPORP"}, + {"Speaker", NULL, "SPORN"}, +}; + +static const struct snd_kcontrol_new byt_rt5640_controls[] = { + SOC_DAPM_PIN_SWITCH("Headphone"), + SOC_DAPM_PIN_SWITCH("Headset Mic"), + SOC_DAPM_PIN_SWITCH("Internal Mic"), + SOC_DAPM_PIN_SWITCH("Speaker"), +}; + +static int byt_rt5640_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params) +{ + struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_dai *codec_dai = rtd->codec_dai; + int ret; + + ret = snd_soc_dai_set_sysclk(codec_dai, RT5640_SCLK_S_PLL1, + params_rate(params) * 256, + SND_SOC_CLOCK_IN); + if (ret < 0) { + dev_err(codec_dai->dev, "can't set codec clock %d\n", ret); + return ret; + } + ret = snd_soc_dai_set_pll(codec_dai, 0, RT5640_PLL1_S_BCLK1, + params_rate(params) * 64, + params_rate(params) * 256); + if (ret < 0) { + dev_err(codec_dai->dev, "can't set codec pll: %d\n", ret); + return ret; + } + return 0; +} + +static int byt_rt5640_init(struct snd_soc_pcm_runtime *runtime) +{ + int ret; + struct snd_soc_codec *codec = runtime->codec; + struct snd_soc_dapm_context *dapm = &codec->dapm; + struct snd_soc_card *card = runtime->card; + + card->dapm.idle_bias_off = true; + + ret = snd_soc_add_card_controls(card, byt_rt5640_controls, + ARRAY_SIZE(byt_rt5640_controls)); + if (ret) { + dev_err(card->dev, "unable to add card controls\n"); + return ret; + } + + snd_soc_dapm_ignore_suspend(dapm, "HPOL"); + snd_soc_dapm_ignore_suspend(dapm, "HPOR"); + + snd_soc_dapm_ignore_suspend(dapm, "SPOLP"); + snd_soc_dapm_ignore_suspend(dapm, "SPOLN"); + snd_soc_dapm_ignore_suspend(dapm, "SPORP"); + snd_soc_dapm_ignore_suspend(dapm, "SPORN"); + + snd_soc_dapm_enable_pin(dapm, "Headset Mic"); + snd_soc_dapm_enable_pin(dapm, "Headphone"); + snd_soc_dapm_enable_pin(dapm, "Speaker"); + snd_soc_dapm_enable_pin(dapm, "Internal Mic"); + + snd_soc_dapm_sync(dapm); + return ret; +} + +static struct snd_soc_ops byt_rt5640_ops = { + .hw_params = byt_rt5640_hw_params, +}; + +static struct snd_soc_dai_link byt_rt5640_dais[] = { + { + .name = "Baytrail Audio", + .stream_name = "Audio", + .cpu_dai_name = "Front-cpu-dai", + .codec_dai_name = "rt5640-aif1", + .codec_name = "i2c-10EC5640:00", + .platform_name = "baytrail-pcm-audio", + .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | + SND_SOC_DAIFMT_CBS_CFS, + .init = byt_rt5640_init, + .ignore_suspend = 1, + .ops = &byt_rt5640_ops, + }, + { + .name = "Baytrail Voice", + .stream_name = "Voice", + .cpu_dai_name = "Mic1-cpu-dai", + .codec_dai_name = "rt5640-aif1", + .codec_name = "i2c-10EC5640:00", + .platform_name = "baytrail-pcm-audio", + .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | + SND_SOC_DAIFMT_CBS_CFS, + .init = NULL, + .ignore_suspend = 1, + .ops = &byt_rt5640_ops, + }, +}; + +static struct snd_soc_card byt_rt5640_card = { + .name = "byt-rt5640", + .dai_link = byt_rt5640_dais, + .num_links = ARRAY_SIZE(byt_rt5640_dais), + .dapm_widgets = byt_rt5640_widgets, + .num_dapm_widgets = ARRAY_SIZE(byt_rt5640_widgets), + .dapm_routes = byt_rt5640_audio_map, + .num_dapm_routes = ARRAY_SIZE(byt_rt5640_audio_map), +}; + +static int byt_rt5640_probe(struct platform_device *pdev) +{ + struct snd_soc_card *card = &byt_rt5640_card; + struct device *dev = &pdev->dev; + + card->dev = &pdev->dev; + dev_set_drvdata(dev, card); + return snd_soc_register_card(card); +} + +static int byt_rt5640_remove(struct platform_device *pdev) +{ + struct snd_soc_card *card = platform_get_drvdata(pdev); + + snd_soc_unregister_card(card); + + return 0; +} + +static struct platform_driver byt_rt5640_audio = { + .probe = byt_rt5640_probe, + .remove = byt_rt5640_remove, + .driver = { + .name = "byt-rt5640", + .owner = THIS_MODULE, + }, +}; +module_platform_driver(byt_rt5640_audio) + +MODULE_DESCRIPTION("ASoC Intel(R) Baytrail Machine driver"); +MODULE_AUTHOR("Omair Md Abdullah, Jarkko Nikula"); +MODULE_LICENSE("GPL v2"); +MODULE_ALIAS("platform:byt-rt5640"); diff --git a/sound/soc/intel/haswell.c b/sound/soc/intel/haswell.c new file mode 100644 index 00000000000..54345a2a738 --- /dev/null +++ b/sound/soc/intel/haswell.c @@ -0,0 +1,235 @@ +/* + * Intel Haswell Lynxpoint SST Audio + * + * Copyright (C) 2013, Intel Corporation. All rights reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License version + * 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +#include <linux/module.h> +#include <linux/platform_device.h> +#include <sound/core.h> +#include <sound/pcm.h> +#include <sound/soc.h> +#include <sound/pcm_params.h> + +#include "sst-dsp.h" +#include "sst-haswell-ipc.h" + +#include "../codecs/rt5640.h" + +/* Haswell ULT platforms have a Headphone and Mic jack */ +static const struct snd_soc_dapm_widget haswell_widgets[] = { + SND_SOC_DAPM_HP("Headphones", NULL), + SND_SOC_DAPM_MIC("Mic", NULL), +}; + +static const struct snd_soc_dapm_route haswell_rt5640_map[] = { + + {"Headphones", NULL, "HPOR"}, + {"Headphones", NULL, "HPOL"}, + {"IN2P", NULL, "Mic"}, + + /* CODEC BE connections */ + {"SSP0 CODEC IN", NULL, "AIF1 Capture"}, + {"AIF1 Playback", NULL, "SSP0 CODEC OUT"}, +}; + +static int haswell_ssp0_fixup(struct snd_soc_pcm_runtime *rtd, + struct snd_pcm_hw_params *params) +{ + struct snd_interval *rate = hw_param_interval(params, + SNDRV_PCM_HW_PARAM_RATE); + struct snd_interval *channels = hw_param_interval(params, + SNDRV_PCM_HW_PARAM_CHANNELS); + + /* The ADSP will covert the FE rate to 48k, stereo */ + rate->min = rate->max = 48000; + channels->min = channels->max = 2; + + /* set SSP0 to 16 bit */ + snd_mask_set(¶ms->masks[SNDRV_PCM_HW_PARAM_FORMAT - + SNDRV_PCM_HW_PARAM_FIRST_MASK], + SNDRV_PCM_FORMAT_S16_LE); + return 0; +} + +static int haswell_rt5640_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params) +{ + struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_dai *codec_dai = rtd->codec_dai; + int ret; + + ret = snd_soc_dai_set_sysclk(codec_dai, RT5640_SCLK_S_MCLK, 12288000, + SND_SOC_CLOCK_IN); + + if (ret < 0) { + dev_err(rtd->dev, "can't set codec sysclk configuration\n"); + return ret; + } + + /* set correct codec filter for DAI format and clock config */ + snd_soc_update_bits(rtd->codec, 0x83, 0xffff, 0x8000); + + return ret; +} + +static struct snd_soc_ops haswell_rt5640_ops = { + .hw_params = haswell_rt5640_hw_params, +}; + +static int haswell_rtd_init(struct snd_soc_pcm_runtime *rtd) +{ + struct snd_soc_codec *codec = rtd->codec; + struct snd_soc_dapm_context *dapm = &codec->dapm; + struct sst_pdata *pdata = dev_get_platdata(rtd->platform->dev); + struct sst_hsw *haswell = pdata->dsp; + int ret; + + /* Set ADSP SSP port settings */ + ret = sst_hsw_device_set_config(haswell, SST_HSW_DEVICE_SSP_0, + SST_HSW_DEVICE_MCLK_FREQ_24_MHZ, + SST_HSW_DEVICE_CLOCK_MASTER, 9); + if (ret < 0) { + dev_err(rtd->dev, "failed to set device config\n"); + return ret; + } + + /* always connected */ + snd_soc_dapm_enable_pin(dapm, "Headphones"); + snd_soc_dapm_enable_pin(dapm, "Mic"); + + return 0; +} + +static struct snd_soc_dai_link haswell_rt5640_dais[] = { + /* Front End DAI links */ + { + .name = "System", + .stream_name = "System Playback", + .cpu_dai_name = "System Pin", + .platform_name = "haswell-pcm-audio", + .dynamic = 1, + .codec_name = "snd-soc-dummy", + .codec_dai_name = "snd-soc-dummy-dai", + .init = haswell_rtd_init, + .trigger = {SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST}, + .dpcm_playback = 1, + }, + { + .name = "Offload0", + .stream_name = "Offload0 Playback", + .cpu_dai_name = "Offload0 Pin", + .platform_name = "haswell-pcm-audio", + .dynamic = 1, + .codec_name = "snd-soc-dummy", + .codec_dai_name = "snd-soc-dummy-dai", + .trigger = {SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST}, + .dpcm_playback = 1, + }, + { + .name = "Offload1", + .stream_name = "Offload1 Playback", + .cpu_dai_name = "Offload1 Pin", + .platform_name = "haswell-pcm-audio", + .dynamic = 1, + .codec_name = "snd-soc-dummy", + .codec_dai_name = "snd-soc-dummy-dai", + .trigger = {SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST}, + .dpcm_playback = 1, + }, + { + .name = "Loopback", + .stream_name = "Loopback", + .cpu_dai_name = "Loopback Pin", + .platform_name = "haswell-pcm-audio", + .dynamic = 0, + .codec_name = "snd-soc-dummy", + .codec_dai_name = "snd-soc-dummy-dai", + .trigger = {SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST}, + .dpcm_capture = 1, + }, + { + .name = "Capture", + .stream_name = "Capture", + .cpu_dai_name = "Capture Pin", + .platform_name = "haswell-pcm-audio", + .dynamic = 1, + .codec_name = "snd-soc-dummy", + .codec_dai_name = "snd-soc-dummy-dai", + .trigger = {SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST}, + .dpcm_capture = 1, + }, + + /* Back End DAI links */ + { + /* SSP0 - Codec */ + .name = "Codec", + .be_id = 0, + .cpu_dai_name = "snd-soc-dummy-dai", + .platform_name = "snd-soc-dummy", + .no_pcm = 1, + .codec_name = "i2c-INT33CA:00", + .codec_dai_name = "rt5640-aif1", + .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | + SND_SOC_DAIFMT_CBS_CFS, + .ignore_suspend = 1, + .ignore_pmdown_time = 1, + .be_hw_params_fixup = haswell_ssp0_fixup, + .ops = &haswell_rt5640_ops, + .dpcm_playback = 1, + .dpcm_capture = 1, + }, +}; + +/* audio machine driver for Haswell Lynxpoint DSP + RT5640 */ +static struct snd_soc_card haswell_rt5640 = { + .name = "haswell-rt5640", + .owner = THIS_MODULE, + .dai_link = haswell_rt5640_dais, + .num_links = ARRAY_SIZE(haswell_rt5640_dais), + .dapm_widgets = haswell_widgets, + .num_dapm_widgets = ARRAY_SIZE(haswell_widgets), + .dapm_routes = haswell_rt5640_map, + .num_dapm_routes = ARRAY_SIZE(haswell_rt5640_map), + .fully_routed = true, +}; + +static int haswell_audio_probe(struct platform_device *pdev) +{ + haswell_rt5640.dev = &pdev->dev; + + return snd_soc_register_card(&haswell_rt5640); +} + +static int haswell_audio_remove(struct platform_device *pdev) +{ + snd_soc_unregister_card(&haswell_rt5640); + return 0; +} + +static struct platform_driver haswell_audio = { + .probe = haswell_audio_probe, + .remove = haswell_audio_remove, + .driver = { + .name = "haswell-audio", + .owner = THIS_MODULE, + }, +}; + +module_platform_driver(haswell_audio) + +/* Module information */ +MODULE_AUTHOR("Liam Girdwood, Xingchao Wang"); +MODULE_DESCRIPTION("Intel SST Audio for Haswell Lynxpoint"); +MODULE_LICENSE("GPL v2"); +MODULE_ALIAS("platform:haswell-audio"); diff --git a/sound/soc/intel/mfld_machine.c b/sound/soc/intel/mfld_machine.c index d3d4c32434f..031d78783fc 100644 --- a/sound/soc/intel/mfld_machine.c +++ b/sound/soc/intel/mfld_machine.c @@ -53,6 +53,7 @@ enum soc_mic_bias_zones { static unsigned int hs_switch; static unsigned int lo_dac; +static struct snd_soc_codec *mfld_codec; struct mfld_mc_private { void __iomem *int_base; @@ -100,40 +101,47 @@ static int headset_get_switch(struct snd_kcontrol *kcontrol, static int headset_set_switch(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { - struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); + struct snd_soc_card *card = snd_kcontrol_chip(kcontrol); + struct snd_soc_dapm_context *dapm = &card->dapm; if (ucontrol->value.integer.value[0] == hs_switch) return 0; + snd_soc_dapm_mutex_lock(dapm); + if (ucontrol->value.integer.value[0]) { pr_debug("hs_set HS path\n"); - snd_soc_dapm_enable_pin(&codec->dapm, "Headphones"); - snd_soc_dapm_disable_pin(&codec->dapm, "EPOUT"); + snd_soc_dapm_enable_pin_unlocked(dapm, "Headphones"); + snd_soc_dapm_disable_pin_unlocked(dapm, "EPOUT"); } else { pr_debug("hs_set EP path\n"); - snd_soc_dapm_disable_pin(&codec->dapm, "Headphones"); - snd_soc_dapm_enable_pin(&codec->dapm, "EPOUT"); + snd_soc_dapm_disable_pin_unlocked(dapm, "Headphones"); + snd_soc_dapm_enable_pin_unlocked(dapm, "EPOUT"); } - snd_soc_dapm_sync(&codec->dapm); + + snd_soc_dapm_sync_unlocked(dapm); + + snd_soc_dapm_mutex_unlock(dapm); + hs_switch = ucontrol->value.integer.value[0]; return 0; } -static void lo_enable_out_pins(struct snd_soc_codec *codec) +static void lo_enable_out_pins(struct snd_soc_dapm_context *dapm) { - snd_soc_dapm_enable_pin(&codec->dapm, "IHFOUTL"); - snd_soc_dapm_enable_pin(&codec->dapm, "IHFOUTR"); - snd_soc_dapm_enable_pin(&codec->dapm, "LINEOUTL"); - snd_soc_dapm_enable_pin(&codec->dapm, "LINEOUTR"); - snd_soc_dapm_enable_pin(&codec->dapm, "VIB1OUT"); - snd_soc_dapm_enable_pin(&codec->dapm, "VIB2OUT"); + snd_soc_dapm_enable_pin_unlocked(dapm, "IHFOUTL"); + snd_soc_dapm_enable_pin_unlocked(dapm, "IHFOUTR"); + snd_soc_dapm_enable_pin_unlocked(dapm, "LINEOUTL"); + snd_soc_dapm_enable_pin_unlocked(dapm, "LINEOUTR"); + snd_soc_dapm_enable_pin_unlocked(dapm, "VIB1OUT"); + snd_soc_dapm_enable_pin_unlocked(dapm, "VIB2OUT"); if (hs_switch) { - snd_soc_dapm_enable_pin(&codec->dapm, "Headphones"); - snd_soc_dapm_disable_pin(&codec->dapm, "EPOUT"); + snd_soc_dapm_enable_pin_unlocked(dapm, "Headphones"); + snd_soc_dapm_disable_pin_unlocked(dapm, "EPOUT"); } else { - snd_soc_dapm_disable_pin(&codec->dapm, "Headphones"); - snd_soc_dapm_enable_pin(&codec->dapm, "EPOUT"); + snd_soc_dapm_disable_pin_unlocked(dapm, "Headphones"); + snd_soc_dapm_enable_pin_unlocked(dapm, "EPOUT"); } } @@ -147,45 +155,53 @@ static int lo_get_switch(struct snd_kcontrol *kcontrol, static int lo_set_switch(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { - struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); + struct snd_soc_card *card = snd_kcontrol_chip(kcontrol); + struct snd_soc_dapm_context *dapm = &card->dapm; if (ucontrol->value.integer.value[0] == lo_dac) return 0; + snd_soc_dapm_mutex_lock(dapm); + /* we dont want to work with last state of lineout so just enable all * pins and then disable pins not required */ - lo_enable_out_pins(codec); + lo_enable_out_pins(dapm); + switch (ucontrol->value.integer.value[0]) { case 0: pr_debug("set vibra path\n"); - snd_soc_dapm_disable_pin(&codec->dapm, "VIB1OUT"); - snd_soc_dapm_disable_pin(&codec->dapm, "VIB2OUT"); - snd_soc_update_bits(codec, SN95031_LOCTL, 0x66, 0); + snd_soc_dapm_disable_pin_unlocked(dapm, "VIB1OUT"); + snd_soc_dapm_disable_pin_unlocked(dapm, "VIB2OUT"); + snd_soc_update_bits(mfld_codec, SN95031_LOCTL, 0x66, 0); break; case 1: pr_debug("set hs path\n"); - snd_soc_dapm_disable_pin(&codec->dapm, "Headphones"); - snd_soc_dapm_disable_pin(&codec->dapm, "EPOUT"); - snd_soc_update_bits(codec, SN95031_LOCTL, 0x66, 0x22); + snd_soc_dapm_disable_pin_unlocked(dapm, "Headphones"); + snd_soc_dapm_disable_pin_unlocked(dapm, "EPOUT"); + snd_soc_update_bits(mfld_codec, SN95031_LOCTL, 0x66, 0x22); break; case 2: pr_debug("set spkr path\n"); - snd_soc_dapm_disable_pin(&codec->dapm, "IHFOUTL"); - snd_soc_dapm_disable_pin(&codec->dapm, "IHFOUTR"); - snd_soc_update_bits(codec, SN95031_LOCTL, 0x66, 0x44); + snd_soc_dapm_disable_pin_unlocked(dapm, "IHFOUTL"); + snd_soc_dapm_disable_pin_unlocked(dapm, "IHFOUTR"); + snd_soc_update_bits(mfld_codec, SN95031_LOCTL, 0x66, 0x44); break; case 3: pr_debug("set null path\n"); - snd_soc_dapm_disable_pin(&codec->dapm, "LINEOUTL"); - snd_soc_dapm_disable_pin(&codec->dapm, "LINEOUTR"); - snd_soc_update_bits(codec, SN95031_LOCTL, 0x66, 0x66); + snd_soc_dapm_disable_pin_unlocked(dapm, "LINEOUTL"); + snd_soc_dapm_disable_pin_unlocked(dapm, "LINEOUTR"); + snd_soc_update_bits(mfld_codec, SN95031_LOCTL, 0x66, 0x66); break; } - snd_soc_dapm_sync(&codec->dapm); + + snd_soc_dapm_sync_unlocked(dapm); + + snd_soc_dapm_mutex_unlock(dapm); + lo_dac = ucontrol->value.integer.value[0]; return 0; } @@ -221,26 +237,11 @@ static void mfld_jack_check(unsigned int intr_status) static int mfld_init(struct snd_soc_pcm_runtime *runtime) { - struct snd_soc_codec *codec = runtime->codec; - struct snd_soc_dapm_context *dapm = &codec->dapm; + struct snd_soc_dapm_context *dapm = &runtime->card->dapm; int ret_val; - /* Add jack sense widgets */ - snd_soc_dapm_new_controls(dapm, mfld_widgets, ARRAY_SIZE(mfld_widgets)); - - /* Set up the map */ - snd_soc_dapm_add_routes(dapm, mfld_map, ARRAY_SIZE(mfld_map)); + mfld_codec = runtime->codec; - /* always connected */ - snd_soc_dapm_enable_pin(dapm, "Headphones"); - snd_soc_dapm_enable_pin(dapm, "Mic"); - - ret_val = snd_soc_add_codec_controls(codec, mfld_snd_controls, - ARRAY_SIZE(mfld_snd_controls)); - if (ret_val) { - pr_err("soc_add_controls failed %d", ret_val); - return ret_val; - } /* default is earpiece pin, userspace sets it explcitly */ snd_soc_dapm_disable_pin(dapm, "Headphones"); /* default is lineout NC, userspace sets it explcitly */ @@ -253,7 +254,7 @@ static int mfld_init(struct snd_soc_pcm_runtime *runtime) snd_soc_dapm_disable_pin(dapm, "LINEINR"); /* Headset and button jack detection */ - ret_val = snd_soc_jack_new(codec, "Intel(R) MID Audio Jack", + ret_val = snd_soc_jack_new(mfld_codec, "Intel(R) MID Audio Jack", SND_JACK_HEADSET | SND_JACK_BTN_0 | SND_JACK_BTN_1, &mfld_jack); if (ret_val) { @@ -335,6 +336,13 @@ static struct snd_soc_card snd_soc_card_mfld = { .owner = THIS_MODULE, .dai_link = mfld_msic_dailink, .num_links = ARRAY_SIZE(mfld_msic_dailink), + + .controls = mfld_snd_controls, + .num_controls = ARRAY_SIZE(mfld_snd_controls), + .dapm_widgets = mfld_widgets, + .num_dapm_widgets = ARRAY_SIZE(mfld_widgets), + .dapm_routes = mfld_map, + .num_dapm_routes = ARRAY_SIZE(mfld_map), }; static irqreturn_t snd_mfld_jack_intr_handler(int irq, void *dev) diff --git a/sound/soc/intel/sst-acpi.c b/sound/soc/intel/sst-acpi.c new file mode 100644 index 00000000000..5d06eecb619 --- /dev/null +++ b/sound/soc/intel/sst-acpi.c @@ -0,0 +1,284 @@ +/* + * Intel SST loader on ACPI systems + * + * Copyright (C) 2013, Intel Corporation. All rights reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License version + * 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +#include <linux/acpi.h> +#include <linux/device.h> +#include <linux/firmware.h> +#include <linux/module.h> +#include <linux/platform_device.h> + +#include "sst-dsp.h" + +#define SST_LPT_DSP_DMA_ADDR_OFFSET 0x0F0000 +#define SST_WPT_DSP_DMA_ADDR_OFFSET 0x0FE000 +#define SST_LPT_DSP_DMA_SIZE (1024 - 1) + +/* Descriptor for SST ASoC machine driver */ +struct sst_acpi_mach { + /* ACPI ID for the matching machine driver. Audio codec for instance */ + const u8 id[ACPI_ID_LEN]; + /* machine driver name */ + const char *drv_name; + /* firmware file name */ + const char *fw_filename; +}; + +/* Descriptor for setting up SST platform data */ +struct sst_acpi_desc { + const char *drv_name; + struct sst_acpi_mach *machines; + /* Platform resource indexes. Must set to -1 if not used */ + int resindex_lpe_base; + int resindex_pcicfg_base; + int resindex_fw_base; + int irqindex_host_ipc; + int resindex_dma_base; + /* Unique number identifying the SST core on platform */ + int sst_id; + /* DMA only valid when resindex_dma_base != -1*/ + int dma_engine; + int dma_size; +}; + +struct sst_acpi_priv { + struct platform_device *pdev_mach; + struct platform_device *pdev_pcm; + struct sst_pdata sst_pdata; + struct sst_acpi_desc *desc; + struct sst_acpi_mach *mach; +}; + +static void sst_acpi_fw_cb(const struct firmware *fw, void *context) +{ + struct platform_device *pdev = context; + struct device *dev = &pdev->dev; + struct sst_acpi_priv *sst_acpi = platform_get_drvdata(pdev); + struct sst_pdata *sst_pdata = &sst_acpi->sst_pdata; + struct sst_acpi_desc *desc = sst_acpi->desc; + struct sst_acpi_mach *mach = sst_acpi->mach; + + sst_pdata->fw = fw; + if (!fw) { + dev_err(dev, "Cannot load firmware %s\n", mach->fw_filename); + return; + } + + /* register PCM and DAI driver */ + sst_acpi->pdev_pcm = + platform_device_register_data(dev, desc->drv_name, -1, + sst_pdata, sizeof(*sst_pdata)); + if (IS_ERR(sst_acpi->pdev_pcm)) { + dev_err(dev, "Cannot register device %s. Error %d\n", + desc->drv_name, (int)PTR_ERR(sst_acpi->pdev_pcm)); + } + + return; +} + +static acpi_status sst_acpi_mach_match(acpi_handle handle, u32 level, + void *context, void **ret) +{ + *(bool *)context = true; + return AE_OK; +} + +static struct sst_acpi_mach *sst_acpi_find_machine( + struct sst_acpi_mach *machines) +{ + struct sst_acpi_mach *mach; + bool found = false; + + for (mach = machines; mach->id[0]; mach++) + if (ACPI_SUCCESS(acpi_get_devices(mach->id, + sst_acpi_mach_match, + &found, NULL)) && found) + return mach; + + return NULL; +} + +static int sst_acpi_probe(struct platform_device *pdev) +{ + const struct acpi_device_id *id; + struct device *dev = &pdev->dev; + struct sst_acpi_priv *sst_acpi; + struct sst_pdata *sst_pdata; + struct sst_acpi_mach *mach; + struct sst_acpi_desc *desc; + struct resource *mmio; + int ret = 0; + + sst_acpi = devm_kzalloc(dev, sizeof(*sst_acpi), GFP_KERNEL); + if (sst_acpi == NULL) + return -ENOMEM; + + id = acpi_match_device(dev->driver->acpi_match_table, dev); + if (!id) + return -ENODEV; + + desc = (struct sst_acpi_desc *)id->driver_data; + mach = sst_acpi_find_machine(desc->machines); + if (mach == NULL) { + dev_err(dev, "No matching ASoC machine driver found\n"); + return -ENODEV; + } + + sst_pdata = &sst_acpi->sst_pdata; + sst_pdata->id = desc->sst_id; + sst_acpi->desc = desc; + sst_acpi->mach = mach; + + if (desc->resindex_dma_base >= 0) { + sst_pdata->dma_engine = desc->dma_engine; + sst_pdata->dma_base = desc->resindex_dma_base; + sst_pdata->dma_size = desc->dma_size; + } + + if (desc->irqindex_host_ipc >= 0) + sst_pdata->irq = platform_get_irq(pdev, desc->irqindex_host_ipc); + + if (desc->resindex_lpe_base >= 0) { + mmio = platform_get_resource(pdev, IORESOURCE_MEM, + desc->resindex_lpe_base); + if (mmio) { + sst_pdata->lpe_base = mmio->start; + sst_pdata->lpe_size = resource_size(mmio); + } + } + + if (desc->resindex_pcicfg_base >= 0) { + mmio = platform_get_resource(pdev, IORESOURCE_MEM, + desc->resindex_pcicfg_base); + if (mmio) { + sst_pdata->pcicfg_base = mmio->start; + sst_pdata->pcicfg_size = resource_size(mmio); + } + } + + if (desc->resindex_fw_base >= 0) { + mmio = platform_get_resource(pdev, IORESOURCE_MEM, + desc->resindex_fw_base); + if (mmio) { + sst_pdata->fw_base = mmio->start; + sst_pdata->fw_size = resource_size(mmio); + } + } + + platform_set_drvdata(pdev, sst_acpi); + + /* register machine driver */ + sst_acpi->pdev_mach = + platform_device_register_data(dev, mach->drv_name, -1, + sst_pdata, sizeof(*sst_pdata)); + if (IS_ERR(sst_acpi->pdev_mach)) + return PTR_ERR(sst_acpi->pdev_mach); + + /* continue SST probing after firmware is loaded */ + ret = request_firmware_nowait(THIS_MODULE, true, mach->fw_filename, + dev, GFP_KERNEL, pdev, sst_acpi_fw_cb); + if (ret) + platform_device_unregister(sst_acpi->pdev_mach); + + return ret; +} + +static int sst_acpi_remove(struct platform_device *pdev) +{ + struct sst_acpi_priv *sst_acpi = platform_get_drvdata(pdev); + struct sst_pdata *sst_pdata = &sst_acpi->sst_pdata; + + platform_device_unregister(sst_acpi->pdev_mach); + if (!IS_ERR_OR_NULL(sst_acpi->pdev_pcm)) + platform_device_unregister(sst_acpi->pdev_pcm); + release_firmware(sst_pdata->fw); + + return 0; +} + +static struct sst_acpi_mach haswell_machines[] = { + { "INT33CA", "haswell-audio", "intel/IntcSST1.bin" }, + {} +}; + +static struct sst_acpi_desc sst_acpi_haswell_desc = { + .drv_name = "haswell-pcm-audio", + .machines = haswell_machines, + .resindex_lpe_base = 0, + .resindex_pcicfg_base = 1, + .resindex_fw_base = -1, + .irqindex_host_ipc = 0, + .sst_id = SST_DEV_ID_LYNX_POINT, + .dma_engine = SST_DMA_TYPE_DW, + .resindex_dma_base = SST_LPT_DSP_DMA_ADDR_OFFSET, + .dma_size = SST_LPT_DSP_DMA_SIZE, +}; + +static struct sst_acpi_mach broadwell_machines[] = { + { "INT343A", "broadwell-audio", "intel/IntcSST2.bin" }, + {} +}; + +static struct sst_acpi_desc sst_acpi_broadwell_desc = { + .drv_name = "haswell-pcm-audio", + .machines = broadwell_machines, + .resindex_lpe_base = 0, + .resindex_pcicfg_base = 1, + .resindex_fw_base = -1, + .irqindex_host_ipc = 0, + .sst_id = SST_DEV_ID_WILDCAT_POINT, + .dma_engine = SST_DMA_TYPE_DW, + .resindex_dma_base = SST_WPT_DSP_DMA_ADDR_OFFSET, + .dma_size = SST_LPT_DSP_DMA_SIZE, +}; + +static struct sst_acpi_mach baytrail_machines[] = { + { "10EC5640", "byt-rt5640", "intel/fw_sst_0f28.bin-i2s_master" }, + {} +}; + +static struct sst_acpi_desc sst_acpi_baytrail_desc = { + .drv_name = "baytrail-pcm-audio", + .machines = baytrail_machines, + .resindex_lpe_base = 0, + .resindex_pcicfg_base = 1, + .resindex_fw_base = 2, + .irqindex_host_ipc = 5, + .sst_id = SST_DEV_ID_BYT, + .resindex_dma_base = -1, +}; + +static struct acpi_device_id sst_acpi_match[] = { + { "INT33C8", (unsigned long)&sst_acpi_haswell_desc }, + { "INT3438", (unsigned long)&sst_acpi_broadwell_desc }, + { "80860F28", (unsigned long)&sst_acpi_baytrail_desc }, + { } +}; +MODULE_DEVICE_TABLE(acpi, sst_acpi_match); + +static struct platform_driver sst_acpi_driver = { + .probe = sst_acpi_probe, + .remove = sst_acpi_remove, + .driver = { + .name = "sst-acpi", + .owner = THIS_MODULE, + .acpi_match_table = ACPI_PTR(sst_acpi_match), + }, +}; +module_platform_driver(sst_acpi_driver); + +MODULE_AUTHOR("Jarkko Nikula <jarkko.nikula@linux.intel.com>"); +MODULE_DESCRIPTION("Intel SST loader on ACPI systems"); +MODULE_LICENSE("GPL v2"); diff --git a/sound/soc/intel/sst-baytrail-dsp.c b/sound/soc/intel/sst-baytrail-dsp.c new file mode 100644 index 00000000000..a50bf7fc0e3 --- /dev/null +++ b/sound/soc/intel/sst-baytrail-dsp.c @@ -0,0 +1,372 @@ +/* + * Intel Baytrail SST DSP driver + * Copyright (c) 2014, Intel Corporation. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + */ + +#include <linux/delay.h> +#include <linux/fs.h> +#include <linux/slab.h> +#include <linux/device.h> +#include <linux/interrupt.h> +#include <linux/module.h> +#include <linux/dma-mapping.h> +#include <linux/platform_device.h> +#include <linux/firmware.h> + +#include "sst-dsp.h" +#include "sst-dsp-priv.h" +#include "sst-baytrail-ipc.h" + +#define SST_BYT_FW_SIGNATURE_SIZE 4 +#define SST_BYT_FW_SIGN "$SST" + +#define SST_BYT_IRAM_OFFSET 0xC0000 +#define SST_BYT_DRAM_OFFSET 0x100000 +#define SST_BYT_SHIM_OFFSET 0x140000 + +enum sst_ram_type { + SST_BYT_IRAM = 1, + SST_BYT_DRAM = 2, + SST_BYT_CACHE = 3, +}; + +struct dma_block_info { + enum sst_ram_type type; /* IRAM/DRAM */ + u32 size; /* Bytes */ + u32 ram_offset; /* Offset in I/DRAM */ + u32 rsvd; /* Reserved field */ +}; + +struct fw_header { + unsigned char signature[SST_BYT_FW_SIGNATURE_SIZE]; + u32 file_size; /* size of fw minus this header */ + u32 modules; /* # of modules */ + u32 file_format; /* version of header format */ + u32 reserved[4]; +}; + +struct sst_byt_fw_module_header { + unsigned char signature[SST_BYT_FW_SIGNATURE_SIZE]; + u32 mod_size; /* size of module */ + u32 blocks; /* # of blocks */ + u32 type; /* codec type, pp lib */ + u32 entry_point; +}; + +static int sst_byt_parse_module(struct sst_dsp *dsp, struct sst_fw *fw, + struct sst_byt_fw_module_header *module) +{ + struct dma_block_info *block; + struct sst_module *mod; + struct sst_module_data block_data; + struct sst_module_template template; + int count; + + memset(&template, 0, sizeof(template)); + template.id = module->type; + template.entry = module->entry_point; + template.p.type = SST_MEM_DRAM; + template.p.data_type = SST_DATA_P; + template.s.type = SST_MEM_DRAM; + template.s.data_type = SST_DATA_S; + + mod = sst_module_new(fw, &template, NULL); + if (mod == NULL) + return -ENOMEM; + + block = (void *)module + sizeof(*module); + + for (count = 0; count < module->blocks; count++) { + + if (block->size <= 0) { + dev_err(dsp->dev, "block %d size invalid\n", count); + return -EINVAL; + } + + switch (block->type) { + case SST_BYT_IRAM: + block_data.offset = block->ram_offset + + dsp->addr.iram_offset; + block_data.type = SST_MEM_IRAM; + break; + case SST_BYT_DRAM: + block_data.offset = block->ram_offset + + dsp->addr.dram_offset; + block_data.type = SST_MEM_DRAM; + break; + case SST_BYT_CACHE: + block_data.offset = block->ram_offset + + (dsp->addr.fw_ext - dsp->addr.lpe); + block_data.type = SST_MEM_CACHE; + break; + default: + dev_err(dsp->dev, "wrong ram type 0x%x in block0x%x\n", + block->type, count); + return -EINVAL; + } + + block_data.size = block->size; + block_data.data_type = SST_DATA_M; + block_data.data = (void *)block + sizeof(*block); + + sst_module_insert_fixed_block(mod, &block_data); + + block = (void *)block + sizeof(*block) + block->size; + } + return 0; +} + +static int sst_byt_parse_fw_image(struct sst_fw *sst_fw) +{ + struct fw_header *header; + struct sst_byt_fw_module_header *module; + struct sst_dsp *dsp = sst_fw->dsp; + int ret, count; + + /* Read the header information from the data pointer */ + header = (struct fw_header *)sst_fw->dma_buf; + + /* verify FW */ + if ((strncmp(header->signature, SST_BYT_FW_SIGN, 4) != 0) || + (sst_fw->size != header->file_size + sizeof(*header))) { + /* Invalid FW signature */ + dev_err(dsp->dev, "Invalid FW sign/filesize mismatch\n"); + return -EINVAL; + } + + dev_dbg(dsp->dev, + "header sign=%4s size=0x%x modules=0x%x fmt=0x%x size=%zu\n", + header->signature, header->file_size, header->modules, + header->file_format, sizeof(*header)); + + module = (void *)sst_fw->dma_buf + sizeof(*header); + for (count = 0; count < header->modules; count++) { + /* module */ + ret = sst_byt_parse_module(dsp, sst_fw, module); + if (ret < 0) { + dev_err(dsp->dev, "invalid module %d\n", count); + return ret; + } + module = (void *)module + sizeof(*module) + module->mod_size; + } + + return 0; +} + +static void sst_byt_dump_shim(struct sst_dsp *sst) +{ + int i; + u64 reg; + + for (i = 0; i <= 0xF0; i += 8) { + reg = sst_dsp_shim_read64_unlocked(sst, i); + if (reg) + dev_dbg(sst->dev, "shim 0x%2.2x value 0x%16.16llx\n", + i, reg); + } + + for (i = 0x00; i <= 0xff; i += 4) { + reg = readl(sst->addr.pci_cfg + i); + if (reg) + dev_dbg(sst->dev, "pci 0x%2.2x value 0x%8.8x\n", + i, (u32)reg); + } +} + +static irqreturn_t sst_byt_irq(int irq, void *context) +{ + struct sst_dsp *sst = (struct sst_dsp *) context; + u64 isrx; + irqreturn_t ret = IRQ_NONE; + + spin_lock(&sst->spinlock); + + isrx = sst_dsp_shim_read64_unlocked(sst, SST_ISRX); + if (isrx & SST_ISRX_DONE) { + /* ADSP has processed the message request from IA */ + sst_dsp_shim_update_bits64_unlocked(sst, SST_IPCX, + SST_BYT_IPCX_DONE, 0); + ret = IRQ_WAKE_THREAD; + } + if (isrx & SST_BYT_ISRX_REQUEST) { + /* mask message request from ADSP and do processing later */ + sst_dsp_shim_update_bits64_unlocked(sst, SST_IMRX, + SST_BYT_IMRX_REQUEST, + SST_BYT_IMRX_REQUEST); + ret = IRQ_WAKE_THREAD; + } + + spin_unlock(&sst->spinlock); + + return ret; +} + +static void sst_byt_boot(struct sst_dsp *sst) +{ + int tries = 10; + + /* release stall and wait to unstall */ + sst_dsp_shim_update_bits64(sst, SST_CSR, SST_BYT_CSR_STALL, 0x0); + while (tries--) { + if (!(sst_dsp_shim_read64(sst, SST_CSR) & + SST_BYT_CSR_PWAITMODE)) + break; + msleep(100); + } + if (tries < 0) { + dev_err(sst->dev, "unable to start DSP\n"); + sst_byt_dump_shim(sst); + } +} + +static void sst_byt_reset(struct sst_dsp *sst) +{ + /* put DSP into reset, set reset vector and stall */ + sst_dsp_shim_update_bits64(sst, SST_CSR, + SST_BYT_CSR_RST | SST_BYT_CSR_VECTOR_SEL | SST_BYT_CSR_STALL, + SST_BYT_CSR_RST | SST_BYT_CSR_VECTOR_SEL | SST_BYT_CSR_STALL); + + udelay(10); + + /* take DSP out of reset and keep stalled for FW loading */ + sst_dsp_shim_update_bits64(sst, SST_CSR, SST_BYT_CSR_RST, 0); +} + +struct sst_adsp_memregion { + u32 start; + u32 end; + int blocks; + enum sst_mem_type type; +}; + +/* BYT test stuff */ +static const struct sst_adsp_memregion byt_region[] = { + {0xC0000, 0x100000, 8, SST_MEM_IRAM}, /* I-SRAM - 8 * 32kB */ + {0x100000, 0x140000, 8, SST_MEM_DRAM}, /* D-SRAM0 - 8 * 32kB */ +}; + +static int sst_byt_resource_map(struct sst_dsp *sst, struct sst_pdata *pdata) +{ + sst->addr.lpe_base = pdata->lpe_base; + sst->addr.lpe = ioremap(pdata->lpe_base, pdata->lpe_size); + if (!sst->addr.lpe) + return -ENODEV; + + /* ADSP PCI MMIO config space */ + sst->addr.pci_cfg = ioremap(pdata->pcicfg_base, pdata->pcicfg_size); + if (!sst->addr.pci_cfg) { + iounmap(sst->addr.lpe); + return -ENODEV; + } + + /* SST Extended FW allocation */ + sst->addr.fw_ext = ioremap(pdata->fw_base, pdata->fw_size); + if (!sst->addr.fw_ext) { + iounmap(sst->addr.pci_cfg); + iounmap(sst->addr.lpe); + return -ENODEV; + } + + /* SST Shim */ + sst->addr.shim = sst->addr.lpe + sst->addr.shim_offset; + + sst_dsp_mailbox_init(sst, SST_BYT_MAILBOX_OFFSET + 0x204, + SST_BYT_IPC_MAX_PAYLOAD_SIZE, + SST_BYT_MAILBOX_OFFSET, + SST_BYT_IPC_MAX_PAYLOAD_SIZE); + + sst->irq = pdata->irq; + + return 0; +} + +static int sst_byt_init(struct sst_dsp *sst, struct sst_pdata *pdata) +{ + const struct sst_adsp_memregion *region; + struct device *dev; + int ret = -ENODEV, i, j, region_count; + u32 offset, size; + + dev = sst->dev; + + switch (sst->id) { + case SST_DEV_ID_BYT: + region = byt_region; + region_count = ARRAY_SIZE(byt_region); + sst->addr.iram_offset = SST_BYT_IRAM_OFFSET; + sst->addr.dram_offset = SST_BYT_DRAM_OFFSET; + sst->addr.shim_offset = SST_BYT_SHIM_OFFSET; + break; + default: + dev_err(dev, "failed to get mem resources\n"); + return ret; + } + + ret = sst_byt_resource_map(sst, pdata); + if (ret < 0) { + dev_err(dev, "failed to map resources\n"); + return ret; + } + + /* + * save the physical address of extended firmware block in the first + * 4 bytes of the mailbox + */ + memcpy_toio(sst->addr.lpe + SST_BYT_MAILBOX_OFFSET, + &pdata->fw_base, sizeof(u32)); + + ret = dma_coerce_mask_and_coherent(dev, DMA_BIT_MASK(32)); + if (ret) + return ret; + + /* enable Interrupt from both sides */ + sst_dsp_shim_update_bits64(sst, SST_IMRX, 0x3, 0x0); + sst_dsp_shim_update_bits64(sst, SST_IMRD, 0x3, 0x0); + + /* register DSP memory blocks - ideally we should get this from ACPI */ + for (i = 0; i < region_count; i++) { + offset = region[i].start; + size = (region[i].end - region[i].start) / region[i].blocks; + + /* register individual memory blocks */ + for (j = 0; j < region[i].blocks; j++) { + sst_mem_block_register(sst, offset, size, + region[i].type, NULL, j, sst); + offset += size; + } + } + + return 0; +} + +static void sst_byt_free(struct sst_dsp *sst) +{ + sst_mem_block_unregister_all(sst); + iounmap(sst->addr.lpe); + iounmap(sst->addr.pci_cfg); + iounmap(sst->addr.fw_ext); +} + +struct sst_ops sst_byt_ops = { + .reset = sst_byt_reset, + .boot = sst_byt_boot, + .write = sst_shim32_write, + .read = sst_shim32_read, + .write64 = sst_shim32_write64, + .read64 = sst_shim32_read64, + .ram_read = sst_memcpy_fromio_32, + .ram_write = sst_memcpy_toio_32, + .irq_handler = sst_byt_irq, + .init = sst_byt_init, + .free = sst_byt_free, + .parse_fw = sst_byt_parse_fw_image, +}; diff --git a/sound/soc/intel/sst-baytrail-ipc.c b/sound/soc/intel/sst-baytrail-ipc.c new file mode 100644 index 00000000000..d0eaeee21be --- /dev/null +++ b/sound/soc/intel/sst-baytrail-ipc.c @@ -0,0 +1,867 @@ +/* + * Intel Baytrail SST IPC Support + * Copyright (c) 2014, Intel Corporation. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + */ + +#include <linux/types.h> +#include <linux/kernel.h> +#include <linux/list.h> +#include <linux/device.h> +#include <linux/wait.h> +#include <linux/spinlock.h> +#include <linux/workqueue.h> +#include <linux/export.h> +#include <linux/slab.h> +#include <linux/delay.h> +#include <linux/list.h> +#include <linux/platform_device.h> +#include <linux/kthread.h> +#include <linux/firmware.h> +#include <linux/io.h> +#include <asm/div64.h> + +#include "sst-baytrail-ipc.h" +#include "sst-dsp.h" +#include "sst-dsp-priv.h" + +/* IPC message timeout */ +#define IPC_TIMEOUT_MSECS 300 +#define IPC_BOOT_MSECS 200 + +#define IPC_EMPTY_LIST_SIZE 8 + +/* IPC header bits */ +#define IPC_HEADER_MSG_ID_MASK 0xff +#define IPC_HEADER_MSG_ID(x) ((x) & IPC_HEADER_MSG_ID_MASK) +#define IPC_HEADER_STR_ID_SHIFT 8 +#define IPC_HEADER_STR_ID_MASK 0x1f +#define IPC_HEADER_STR_ID(x) (((x) & 0x1f) << IPC_HEADER_STR_ID_SHIFT) +#define IPC_HEADER_LARGE_SHIFT 13 +#define IPC_HEADER_LARGE(x) (((x) & 0x1) << IPC_HEADER_LARGE_SHIFT) +#define IPC_HEADER_DATA_SHIFT 16 +#define IPC_HEADER_DATA_MASK 0x3fff +#define IPC_HEADER_DATA(x) (((x) & 0x3fff) << IPC_HEADER_DATA_SHIFT) + +/* mask for differentiating between notification and reply message */ +#define IPC_NOTIFICATION (0x1 << 7) + +/* I2L Stream config/control msgs */ +#define IPC_IA_ALLOC_STREAM 0x20 +#define IPC_IA_FREE_STREAM 0x21 +#define IPC_IA_PAUSE_STREAM 0x24 +#define IPC_IA_RESUME_STREAM 0x25 +#define IPC_IA_DROP_STREAM 0x26 +#define IPC_IA_START_STREAM 0x30 + +/* notification messages */ +#define IPC_IA_FW_INIT_CMPLT 0x81 +#define IPC_SST_PERIOD_ELAPSED 0x97 + +/* IPC messages between host and ADSP */ +struct sst_byt_address_info { + u32 addr; + u32 size; +} __packed; + +struct sst_byt_str_type { + u8 codec_type; + u8 str_type; + u8 operation; + u8 protected_str; + u8 time_slots; + u8 reserved; + u16 result; +} __packed; + +struct sst_byt_pcm_params { + u8 num_chan; + u8 pcm_wd_sz; + u8 use_offload_path; + u8 reserved; + u32 sfreq; + u8 channel_map[8]; +} __packed; + +struct sst_byt_frames_info { + u16 num_entries; + u16 rsrvd; + u32 frag_size; + struct sst_byt_address_info ring_buf_info[8]; +} __packed; + +struct sst_byt_alloc_params { + struct sst_byt_str_type str_type; + struct sst_byt_pcm_params pcm_params; + struct sst_byt_frames_info frame_info; +} __packed; + +struct sst_byt_alloc_response { + struct sst_byt_str_type str_type; + u8 reserved[88]; +} __packed; + +struct sst_byt_start_stream_params { + u32 byte_offset; +} __packed; + +struct sst_byt_tstamp { + u64 ring_buffer_counter; + u64 hardware_counter; + u64 frames_decoded; + u64 bytes_decoded; + u64 bytes_copied; + u32 sampling_frequency; + u32 channel_peak[8]; +} __packed; + +/* driver internal IPC message structure */ +struct ipc_message { + struct list_head list; + u64 header; + + /* direction wrt host CPU */ + char tx_data[SST_BYT_IPC_MAX_PAYLOAD_SIZE]; + size_t tx_size; + char rx_data[SST_BYT_IPC_MAX_PAYLOAD_SIZE]; + size_t rx_size; + + wait_queue_head_t waitq; + bool complete; + bool wait; + int errno; +}; + +struct sst_byt_stream; +struct sst_byt; + +/* stream infomation */ +struct sst_byt_stream { + struct list_head node; + + /* configuration */ + struct sst_byt_alloc_params request; + struct sst_byt_alloc_response reply; + + /* runtime info */ + struct sst_byt *byt; + int str_id; + bool commited; + bool running; + + /* driver callback */ + u32 (*notify_position)(struct sst_byt_stream *stream, void *data); + void *pdata; +}; + +/* SST Baytrail IPC data */ +struct sst_byt { + struct device *dev; + struct sst_dsp *dsp; + + /* stream */ + struct list_head stream_list; + + /* boot */ + wait_queue_head_t boot_wait; + bool boot_complete; + + /* IPC messaging */ + struct list_head tx_list; + struct list_head rx_list; + struct list_head empty_list; + wait_queue_head_t wait_txq; + struct task_struct *tx_thread; + struct kthread_worker kworker; + struct kthread_work kwork; + struct ipc_message *msg; +}; + +static inline u64 sst_byt_header(int msg_id, int data, bool large, int str_id) +{ + u64 header; + + header = IPC_HEADER_MSG_ID(msg_id) | + IPC_HEADER_STR_ID(str_id) | + IPC_HEADER_LARGE(large) | + IPC_HEADER_DATA(data) | + SST_BYT_IPCX_BUSY; + + return header; +} + +static inline u16 sst_byt_header_msg_id(u64 header) +{ + return header & IPC_HEADER_MSG_ID_MASK; +} + +static inline u8 sst_byt_header_str_id(u64 header) +{ + return (header >> IPC_HEADER_STR_ID_SHIFT) & IPC_HEADER_STR_ID_MASK; +} + +static inline u16 sst_byt_header_data(u64 header) +{ + return (header >> IPC_HEADER_DATA_SHIFT) & IPC_HEADER_DATA_MASK; +} + +static struct sst_byt_stream *sst_byt_get_stream(struct sst_byt *byt, + int stream_id) +{ + struct sst_byt_stream *stream; + + list_for_each_entry(stream, &byt->stream_list, node) { + if (stream->str_id == stream_id) + return stream; + } + + return NULL; +} + +static void sst_byt_ipc_shim_dbg(struct sst_byt *byt, const char *text) +{ + struct sst_dsp *sst = byt->dsp; + u64 isr, ipcd, imrx, ipcx; + + ipcx = sst_dsp_shim_read64_unlocked(sst, SST_IPCX); + isr = sst_dsp_shim_read64_unlocked(sst, SST_ISRX); + ipcd = sst_dsp_shim_read64_unlocked(sst, SST_IPCD); + imrx = sst_dsp_shim_read64_unlocked(sst, SST_IMRX); + + dev_err(byt->dev, + "ipc: --%s-- ipcx 0x%llx isr 0x%llx ipcd 0x%llx imrx 0x%llx\n", + text, ipcx, isr, ipcd, imrx); +} + +/* locks held by caller */ +static struct ipc_message *sst_byt_msg_get_empty(struct sst_byt *byt) +{ + struct ipc_message *msg = NULL; + + if (!list_empty(&byt->empty_list)) { + msg = list_first_entry(&byt->empty_list, + struct ipc_message, list); + list_del(&msg->list); + } + + return msg; +} + +static void sst_byt_ipc_tx_msgs(struct kthread_work *work) +{ + struct sst_byt *byt = + container_of(work, struct sst_byt, kwork); + struct ipc_message *msg; + u64 ipcx; + unsigned long flags; + + spin_lock_irqsave(&byt->dsp->spinlock, flags); + if (list_empty(&byt->tx_list)) { + spin_unlock_irqrestore(&byt->dsp->spinlock, flags); + return; + } + + /* if the DSP is busy we will TX messages after IRQ */ + ipcx = sst_dsp_shim_read64_unlocked(byt->dsp, SST_IPCX); + if (ipcx & SST_BYT_IPCX_BUSY) { + spin_unlock_irqrestore(&byt->dsp->spinlock, flags); + return; + } + + msg = list_first_entry(&byt->tx_list, struct ipc_message, list); + + list_move(&msg->list, &byt->rx_list); + + /* send the message */ + if (msg->header & IPC_HEADER_LARGE(true)) + sst_dsp_outbox_write(byt->dsp, msg->tx_data, msg->tx_size); + sst_dsp_shim_write64_unlocked(byt->dsp, SST_IPCX, msg->header); + + spin_unlock_irqrestore(&byt->dsp->spinlock, flags); +} + +static inline void sst_byt_tx_msg_reply_complete(struct sst_byt *byt, + struct ipc_message *msg) +{ + msg->complete = true; + + if (!msg->wait) + list_add_tail(&msg->list, &byt->empty_list); + else + wake_up(&msg->waitq); +} + +static int sst_byt_tx_wait_done(struct sst_byt *byt, struct ipc_message *msg, + void *rx_data) +{ + unsigned long flags; + int ret; + + /* wait for DSP completion */ + ret = wait_event_timeout(msg->waitq, msg->complete, + msecs_to_jiffies(IPC_TIMEOUT_MSECS)); + + spin_lock_irqsave(&byt->dsp->spinlock, flags); + if (ret == 0) { + list_del(&msg->list); + sst_byt_ipc_shim_dbg(byt, "message timeout"); + + ret = -ETIMEDOUT; + } else { + + /* copy the data returned from DSP */ + if (msg->rx_size) + memcpy(rx_data, msg->rx_data, msg->rx_size); + ret = msg->errno; + } + + list_add_tail(&msg->list, &byt->empty_list); + spin_unlock_irqrestore(&byt->dsp->spinlock, flags); + return ret; +} + +static int sst_byt_ipc_tx_message(struct sst_byt *byt, u64 header, + void *tx_data, size_t tx_bytes, + void *rx_data, size_t rx_bytes, int wait) +{ + unsigned long flags; + struct ipc_message *msg; + + spin_lock_irqsave(&byt->dsp->spinlock, flags); + + msg = sst_byt_msg_get_empty(byt); + if (msg == NULL) { + spin_unlock_irqrestore(&byt->dsp->spinlock, flags); + return -EBUSY; + } + + msg->header = header; + msg->tx_size = tx_bytes; + msg->rx_size = rx_bytes; + msg->wait = wait; + msg->errno = 0; + msg->complete = false; + + if (tx_bytes) { + /* msg content = lower 32-bit of the header + data */ + *(u32 *)msg->tx_data = (u32)(header & (u32)-1); + memcpy(msg->tx_data + sizeof(u32), tx_data, tx_bytes); + msg->tx_size += sizeof(u32); + } + + list_add_tail(&msg->list, &byt->tx_list); + spin_unlock_irqrestore(&byt->dsp->spinlock, flags); + + queue_kthread_work(&byt->kworker, &byt->kwork); + + if (wait) + return sst_byt_tx_wait_done(byt, msg, rx_data); + else + return 0; +} + +static inline int sst_byt_ipc_tx_msg_wait(struct sst_byt *byt, u64 header, + void *tx_data, size_t tx_bytes, + void *rx_data, size_t rx_bytes) +{ + return sst_byt_ipc_tx_message(byt, header, tx_data, tx_bytes, + rx_data, rx_bytes, 1); +} + +static inline int sst_byt_ipc_tx_msg_nowait(struct sst_byt *byt, u64 header, + void *tx_data, size_t tx_bytes) +{ + return sst_byt_ipc_tx_message(byt, header, tx_data, tx_bytes, + NULL, 0, 0); +} + +static struct ipc_message *sst_byt_reply_find_msg(struct sst_byt *byt, + u64 header) +{ + struct ipc_message *msg = NULL, *_msg; + u64 mask; + + /* match reply to message sent based on msg and stream IDs */ + mask = IPC_HEADER_MSG_ID_MASK | + IPC_HEADER_STR_ID_MASK << IPC_HEADER_STR_ID_SHIFT; + header &= mask; + + if (list_empty(&byt->rx_list)) { + dev_err(byt->dev, + "ipc: rx list is empty but received 0x%llx\n", header); + goto out; + } + + list_for_each_entry(_msg, &byt->rx_list, list) { + if ((_msg->header & mask) == header) { + msg = _msg; + break; + } + } + +out: + return msg; +} + +static void sst_byt_stream_update(struct sst_byt *byt, struct ipc_message *msg) +{ + struct sst_byt_stream *stream; + u64 header = msg->header; + u8 stream_id = sst_byt_header_str_id(header); + u8 stream_msg = sst_byt_header_msg_id(header); + + stream = sst_byt_get_stream(byt, stream_id); + if (stream == NULL) + return; + + switch (stream_msg) { + case IPC_IA_DROP_STREAM: + case IPC_IA_PAUSE_STREAM: + case IPC_IA_FREE_STREAM: + stream->running = false; + break; + case IPC_IA_START_STREAM: + case IPC_IA_RESUME_STREAM: + stream->running = true; + break; + } +} + +static int sst_byt_process_reply(struct sst_byt *byt, u64 header) +{ + struct ipc_message *msg; + + msg = sst_byt_reply_find_msg(byt, header); + if (msg == NULL) + return 1; + + if (header & IPC_HEADER_LARGE(true)) { + msg->rx_size = sst_byt_header_data(header); + sst_dsp_inbox_read(byt->dsp, msg->rx_data, msg->rx_size); + } + + /* update any stream states */ + sst_byt_stream_update(byt, msg); + + list_del(&msg->list); + /* wake up */ + sst_byt_tx_msg_reply_complete(byt, msg); + + return 1; +} + +static void sst_byt_fw_ready(struct sst_byt *byt, u64 header) +{ + dev_dbg(byt->dev, "ipc: DSP is ready 0x%llX\n", header); + + byt->boot_complete = true; + wake_up(&byt->boot_wait); +} + +static int sst_byt_process_notification(struct sst_byt *byt, + unsigned long *flags) +{ + struct sst_dsp *sst = byt->dsp; + struct sst_byt_stream *stream; + u64 header; + u8 msg_id, stream_id; + int handled = 1; + + header = sst_dsp_shim_read64_unlocked(sst, SST_IPCD); + msg_id = sst_byt_header_msg_id(header); + + switch (msg_id) { + case IPC_SST_PERIOD_ELAPSED: + stream_id = sst_byt_header_str_id(header); + stream = sst_byt_get_stream(byt, stream_id); + if (stream && stream->running && stream->notify_position) { + spin_unlock_irqrestore(&sst->spinlock, *flags); + stream->notify_position(stream, stream->pdata); + spin_lock_irqsave(&sst->spinlock, *flags); + } + break; + case IPC_IA_FW_INIT_CMPLT: + sst_byt_fw_ready(byt, header); + break; + } + + return handled; +} + +static irqreturn_t sst_byt_irq_thread(int irq, void *context) +{ + struct sst_dsp *sst = (struct sst_dsp *) context; + struct sst_byt *byt = sst_dsp_get_thread_context(sst); + u64 header; + unsigned long flags; + + spin_lock_irqsave(&sst->spinlock, flags); + + header = sst_dsp_shim_read64_unlocked(sst, SST_IPCD); + if (header & SST_BYT_IPCD_BUSY) { + if (header & IPC_NOTIFICATION) { + /* message from ADSP */ + sst_byt_process_notification(byt, &flags); + } else { + /* reply from ADSP */ + sst_byt_process_reply(byt, header); + } + /* + * clear IPCD BUSY bit and set DONE bit. Tell DSP we have + * processed the message and can accept new. Clear data part + * of the header + */ + sst_dsp_shim_update_bits64_unlocked(sst, SST_IPCD, + SST_BYT_IPCD_DONE | SST_BYT_IPCD_BUSY | + IPC_HEADER_DATA(IPC_HEADER_DATA_MASK), + SST_BYT_IPCD_DONE); + /* unmask message request interrupts */ + sst_dsp_shim_update_bits64_unlocked(sst, SST_IMRX, + SST_BYT_IMRX_REQUEST, 0); + } + + spin_unlock_irqrestore(&sst->spinlock, flags); + + /* continue to send any remaining messages... */ + queue_kthread_work(&byt->kworker, &byt->kwork); + + return IRQ_HANDLED; +} + +/* stream API */ +struct sst_byt_stream *sst_byt_stream_new(struct sst_byt *byt, int id, + u32 (*notify_position)(struct sst_byt_stream *stream, void *data), + void *data) +{ + struct sst_byt_stream *stream; + + stream = kzalloc(sizeof(*stream), GFP_KERNEL); + if (stream == NULL) + return NULL; + + list_add(&stream->node, &byt->stream_list); + stream->notify_position = notify_position; + stream->pdata = data; + stream->byt = byt; + stream->str_id = id; + + return stream; +} + +int sst_byt_stream_set_bits(struct sst_byt *byt, struct sst_byt_stream *stream, + int bits) +{ + stream->request.pcm_params.pcm_wd_sz = bits; + return 0; +} + +int sst_byt_stream_set_channels(struct sst_byt *byt, + struct sst_byt_stream *stream, u8 channels) +{ + stream->request.pcm_params.num_chan = channels; + return 0; +} + +int sst_byt_stream_set_rate(struct sst_byt *byt, struct sst_byt_stream *stream, + unsigned int rate) +{ + stream->request.pcm_params.sfreq = rate; + return 0; +} + +/* stream sonfiguration */ +int sst_byt_stream_type(struct sst_byt *byt, struct sst_byt_stream *stream, + int codec_type, int stream_type, int operation) +{ + stream->request.str_type.codec_type = codec_type; + stream->request.str_type.str_type = stream_type; + stream->request.str_type.operation = operation; + stream->request.str_type.time_slots = 0xc; + + return 0; +} + +int sst_byt_stream_buffer(struct sst_byt *byt, struct sst_byt_stream *stream, + uint32_t buffer_addr, uint32_t buffer_size) +{ + stream->request.frame_info.num_entries = 1; + stream->request.frame_info.ring_buf_info[0].addr = buffer_addr; + stream->request.frame_info.ring_buf_info[0].size = buffer_size; + /* calculate bytes per 4 ms fragment */ + stream->request.frame_info.frag_size = + stream->request.pcm_params.sfreq * + stream->request.pcm_params.num_chan * + stream->request.pcm_params.pcm_wd_sz / 8 * + 4 / 1000; + return 0; +} + +int sst_byt_stream_commit(struct sst_byt *byt, struct sst_byt_stream *stream) +{ + struct sst_byt_alloc_params *str_req = &stream->request; + struct sst_byt_alloc_response *reply = &stream->reply; + u64 header; + int ret; + + header = sst_byt_header(IPC_IA_ALLOC_STREAM, + sizeof(*str_req) + sizeof(u32), + true, stream->str_id); + ret = sst_byt_ipc_tx_msg_wait(byt, header, str_req, sizeof(*str_req), + reply, sizeof(*reply)); + if (ret < 0) { + dev_err(byt->dev, "ipc: error stream commit failed\n"); + return ret; + } + + stream->commited = true; + + return 0; +} + +int sst_byt_stream_free(struct sst_byt *byt, struct sst_byt_stream *stream) +{ + u64 header; + int ret = 0; + + if (!stream->commited) + goto out; + + header = sst_byt_header(IPC_IA_FREE_STREAM, 0, false, stream->str_id); + ret = sst_byt_ipc_tx_msg_wait(byt, header, NULL, 0, NULL, 0); + if (ret < 0) { + dev_err(byt->dev, "ipc: free stream %d failed\n", + stream->str_id); + return -EAGAIN; + } + + stream->commited = false; +out: + list_del(&stream->node); + kfree(stream); + + return ret; +} + +static int sst_byt_stream_operations(struct sst_byt *byt, int type, + int stream_id, int wait) +{ + struct sst_byt_start_stream_params start_stream; + u64 header; + void *tx_msg = NULL; + size_t size = 0; + + if (type != IPC_IA_START_STREAM) { + header = sst_byt_header(type, 0, false, stream_id); + } else { + start_stream.byte_offset = 0; + header = sst_byt_header(IPC_IA_START_STREAM, + sizeof(start_stream) + sizeof(u32), + true, stream_id); + tx_msg = &start_stream; + size = sizeof(start_stream); + } + + if (wait) + return sst_byt_ipc_tx_msg_wait(byt, header, + tx_msg, size, NULL, 0); + else + return sst_byt_ipc_tx_msg_nowait(byt, header, tx_msg, size); +} + +/* stream ALSA trigger operations */ +int sst_byt_stream_start(struct sst_byt *byt, struct sst_byt_stream *stream) +{ + int ret; + + ret = sst_byt_stream_operations(byt, IPC_IA_START_STREAM, + stream->str_id, 0); + if (ret < 0) + dev_err(byt->dev, "ipc: error failed to start stream %d\n", + stream->str_id); + + return ret; +} + +int sst_byt_stream_stop(struct sst_byt *byt, struct sst_byt_stream *stream) +{ + int ret; + + /* don't stop streams that are not commited */ + if (!stream->commited) + return 0; + + ret = sst_byt_stream_operations(byt, IPC_IA_DROP_STREAM, + stream->str_id, 0); + if (ret < 0) + dev_err(byt->dev, "ipc: error failed to stop stream %d\n", + stream->str_id); + return ret; +} + +int sst_byt_stream_pause(struct sst_byt *byt, struct sst_byt_stream *stream) +{ + int ret; + + ret = sst_byt_stream_operations(byt, IPC_IA_PAUSE_STREAM, + stream->str_id, 0); + if (ret < 0) + dev_err(byt->dev, "ipc: error failed to pause stream %d\n", + stream->str_id); + + return ret; +} + +int sst_byt_stream_resume(struct sst_byt *byt, struct sst_byt_stream *stream) +{ + int ret; + + ret = sst_byt_stream_operations(byt, IPC_IA_RESUME_STREAM, + stream->str_id, 0); + if (ret < 0) + dev_err(byt->dev, "ipc: error failed to resume stream %d\n", + stream->str_id); + + return ret; +} + +int sst_byt_get_dsp_position(struct sst_byt *byt, + struct sst_byt_stream *stream, int buffer_size) +{ + struct sst_dsp *sst = byt->dsp; + struct sst_byt_tstamp fw_tstamp; + u8 str_id = stream->str_id; + u32 tstamp_offset; + + tstamp_offset = SST_BYT_TIMESTAMP_OFFSET + str_id * sizeof(fw_tstamp); + memcpy_fromio(&fw_tstamp, + sst->addr.lpe + tstamp_offset, sizeof(fw_tstamp)); + + return do_div(fw_tstamp.ring_buffer_counter, buffer_size); +} + +static int msg_empty_list_init(struct sst_byt *byt) +{ + struct ipc_message *msg; + int i; + + byt->msg = kzalloc(sizeof(*msg) * IPC_EMPTY_LIST_SIZE, GFP_KERNEL); + if (byt->msg == NULL) + return -ENOMEM; + + for (i = 0; i < IPC_EMPTY_LIST_SIZE; i++) { + init_waitqueue_head(&byt->msg[i].waitq); + list_add(&byt->msg[i].list, &byt->empty_list); + } + + return 0; +} + +struct sst_dsp *sst_byt_get_dsp(struct sst_byt *byt) +{ + return byt->dsp; +} + +static struct sst_dsp_device byt_dev = { + .thread = sst_byt_irq_thread, + .ops = &sst_byt_ops, +}; + +int sst_byt_dsp_init(struct device *dev, struct sst_pdata *pdata) +{ + struct sst_byt *byt; + struct sst_fw *byt_sst_fw; + int err; + + dev_dbg(dev, "initialising Byt DSP IPC\n"); + + byt = devm_kzalloc(dev, sizeof(*byt), GFP_KERNEL); + if (byt == NULL) + return -ENOMEM; + + byt->dev = dev; + INIT_LIST_HEAD(&byt->stream_list); + INIT_LIST_HEAD(&byt->tx_list); + INIT_LIST_HEAD(&byt->rx_list); + INIT_LIST_HEAD(&byt->empty_list); + init_waitqueue_head(&byt->boot_wait); + init_waitqueue_head(&byt->wait_txq); + + err = msg_empty_list_init(byt); + if (err < 0) + return -ENOMEM; + + /* start the IPC message thread */ + init_kthread_worker(&byt->kworker); + byt->tx_thread = kthread_run(kthread_worker_fn, + &byt->kworker, + dev_name(byt->dev)); + if (IS_ERR(byt->tx_thread)) { + err = PTR_ERR(byt->tx_thread); + dev_err(byt->dev, "error failed to create message TX task\n"); + goto err_free_msg; + } + init_kthread_work(&byt->kwork, sst_byt_ipc_tx_msgs); + + byt_dev.thread_context = byt; + + /* init SST shim */ + byt->dsp = sst_dsp_new(dev, &byt_dev, pdata); + if (byt->dsp == NULL) { + err = -ENODEV; + goto err_free_msg; + } + + /* keep the DSP in reset state for base FW loading */ + sst_dsp_reset(byt->dsp); + + byt_sst_fw = sst_fw_new(byt->dsp, pdata->fw, byt); + if (byt_sst_fw == NULL) { + err = -ENODEV; + dev_err(dev, "error: failed to load firmware\n"); + goto fw_err; + } + + /* wait for DSP boot completion */ + sst_dsp_boot(byt->dsp); + err = wait_event_timeout(byt->boot_wait, byt->boot_complete, + msecs_to_jiffies(IPC_BOOT_MSECS)); + if (err == 0) { + err = -EIO; + dev_err(byt->dev, "ipc: error DSP boot timeout\n"); + goto boot_err; + } + + pdata->dsp = byt; + + return 0; + +boot_err: + sst_dsp_reset(byt->dsp); + sst_fw_free(byt_sst_fw); +fw_err: + sst_dsp_free(byt->dsp); +err_free_msg: + kfree(byt->msg); + + return err; +} +EXPORT_SYMBOL_GPL(sst_byt_dsp_init); + +void sst_byt_dsp_free(struct device *dev, struct sst_pdata *pdata) +{ + struct sst_byt *byt = pdata->dsp; + + sst_dsp_reset(byt->dsp); + sst_fw_free_all(byt->dsp); + sst_dsp_free(byt->dsp); + kfree(byt->msg); +} +EXPORT_SYMBOL_GPL(sst_byt_dsp_free); diff --git a/sound/soc/intel/sst-baytrail-ipc.h b/sound/soc/intel/sst-baytrail-ipc.h new file mode 100644 index 00000000000..f172b6440fa --- /dev/null +++ b/sound/soc/intel/sst-baytrail-ipc.h @@ -0,0 +1,69 @@ +/* + * Intel Baytrail SST IPC Support + * Copyright (c) 2014, Intel Corporation. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + */ + +#ifndef __SST_BYT_IPC_H +#define __SST_BYT_IPC_H + +#include <linux/types.h> + +struct sst_byt; +struct sst_byt_stream; +struct sst_pdata; +extern struct sst_ops sst_byt_ops; + + +#define SST_BYT_MAILBOX_OFFSET 0x144000 +#define SST_BYT_TIMESTAMP_OFFSET (SST_BYT_MAILBOX_OFFSET + 0x800) + +/** + * Upfront defined maximum message size that is + * expected by the in/out communication pipes in FW. + */ +#define SST_BYT_IPC_MAX_PAYLOAD_SIZE 200 + +/* stream API */ +struct sst_byt_stream *sst_byt_stream_new(struct sst_byt *byt, int id, + uint32_t (*get_write_position)(struct sst_byt_stream *stream, + void *data), + void *data); + +/* stream configuration */ +int sst_byt_stream_set_bits(struct sst_byt *byt, struct sst_byt_stream *stream, + int bits); +int sst_byt_stream_set_channels(struct sst_byt *byt, + struct sst_byt_stream *stream, u8 channels); +int sst_byt_stream_set_rate(struct sst_byt *byt, struct sst_byt_stream *stream, + unsigned int rate); +int sst_byt_stream_type(struct sst_byt *byt, struct sst_byt_stream *stream, + int codec_type, int stream_type, int operation); +int sst_byt_stream_buffer(struct sst_byt *byt, struct sst_byt_stream *stream, + uint32_t buffer_addr, uint32_t buffer_size); +int sst_byt_stream_commit(struct sst_byt *byt, struct sst_byt_stream *stream); +int sst_byt_stream_free(struct sst_byt *byt, struct sst_byt_stream *stream); + +/* stream ALSA trigger operations */ +int sst_byt_stream_start(struct sst_byt *byt, struct sst_byt_stream *stream); +int sst_byt_stream_stop(struct sst_byt *byt, struct sst_byt_stream *stream); +int sst_byt_stream_pause(struct sst_byt *byt, struct sst_byt_stream *stream); +int sst_byt_stream_resume(struct sst_byt *byt, struct sst_byt_stream *stream); + +int sst_byt_get_dsp_position(struct sst_byt *byt, + struct sst_byt_stream *stream, int buffer_size); + +/* init */ +int sst_byt_dsp_init(struct device *dev, struct sst_pdata *pdata); +void sst_byt_dsp_free(struct device *dev, struct sst_pdata *pdata); +struct sst_dsp *sst_byt_get_dsp(struct sst_byt *byt); + +#endif diff --git a/sound/soc/intel/sst-baytrail-pcm.c b/sound/soc/intel/sst-baytrail-pcm.c new file mode 100644 index 00000000000..6d101f3813b --- /dev/null +++ b/sound/soc/intel/sst-baytrail-pcm.c @@ -0,0 +1,422 @@ +/* + * Intel Baytrail SST PCM Support + * Copyright (c) 2014, Intel Corporation. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + */ + +#include <linux/module.h> +#include <linux/dma-mapping.h> +#include <linux/slab.h> +#include <sound/core.h> +#include <sound/pcm.h> +#include <sound/pcm_params.h> +#include <sound/soc.h> +#include "sst-baytrail-ipc.h" +#include "sst-dsp-priv.h" +#include "sst-dsp.h" + +#define BYT_PCM_COUNT 2 + +static const struct snd_pcm_hardware sst_byt_pcm_hardware = { + .info = SNDRV_PCM_INFO_MMAP | + SNDRV_PCM_INFO_MMAP_VALID | + SNDRV_PCM_INFO_INTERLEAVED | + SNDRV_PCM_INFO_PAUSE | + SNDRV_PCM_INFO_RESUME, + .formats = SNDRV_PCM_FMTBIT_S16_LE | + SNDRV_PCM_FORMAT_S24_LE, + .period_bytes_min = 384, + .period_bytes_max = 48000, + .periods_min = 2, + .periods_max = 250, + .buffer_bytes_max = 96000, +}; + +/* private data for each PCM DSP stream */ +struct sst_byt_pcm_data { + struct sst_byt_stream *stream; + struct snd_pcm_substream *substream; + struct mutex mutex; +}; + +/* private data for the driver */ +struct sst_byt_priv_data { + /* runtime DSP */ + struct sst_byt *byt; + + /* DAI data */ + struct sst_byt_pcm_data pcm[BYT_PCM_COUNT]; +}; + +/* this may get called several times by oss emulation */ +static int sst_byt_pcm_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params) +{ + struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct sst_byt_priv_data *pdata = + snd_soc_platform_get_drvdata(rtd->platform); + struct sst_byt_pcm_data *pcm_data = snd_soc_pcm_get_drvdata(rtd); + struct sst_byt *byt = pdata->byt; + u32 rate, bits; + u8 channels; + int ret, playback = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK); + + dev_dbg(rtd->dev, "PCM: hw_params, pcm_data %p\n", pcm_data); + + ret = sst_byt_stream_type(byt, pcm_data->stream, + 1, 1, !playback); + if (ret < 0) { + dev_err(rtd->dev, "failed to set stream format %d\n", ret); + return ret; + } + + rate = params_rate(params); + ret = sst_byt_stream_set_rate(byt, pcm_data->stream, rate); + if (ret < 0) { + dev_err(rtd->dev, "could not set rate %d\n", rate); + return ret; + } + + bits = snd_pcm_format_width(params_format(params)); + ret = sst_byt_stream_set_bits(byt, pcm_data->stream, bits); + if (ret < 0) { + dev_err(rtd->dev, "could not set formats %d\n", + params_rate(params)); + return ret; + } + + channels = (u8)(params_channels(params) & 0xF); + ret = sst_byt_stream_set_channels(byt, pcm_data->stream, channels); + if (ret < 0) { + dev_err(rtd->dev, "could not set channels %d\n", + params_rate(params)); + return ret; + } + + snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(params)); + + ret = sst_byt_stream_buffer(byt, pcm_data->stream, + substream->dma_buffer.addr, + params_buffer_bytes(params)); + if (ret < 0) { + dev_err(rtd->dev, "PCM: failed to set DMA buffer %d\n", ret); + return ret; + } + + ret = sst_byt_stream_commit(byt, pcm_data->stream); + if (ret < 0) { + dev_err(rtd->dev, "PCM: failed stream commit %d\n", ret); + return ret; + } + + return 0; +} + +static int sst_byt_pcm_hw_free(struct snd_pcm_substream *substream) +{ + struct snd_soc_pcm_runtime *rtd = substream->private_data; + + dev_dbg(rtd->dev, "PCM: hw_free\n"); + snd_pcm_lib_free_pages(substream); + + return 0; +} + +static int sst_byt_pcm_trigger(struct snd_pcm_substream *substream, int cmd) +{ + struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct sst_byt_priv_data *pdata = + snd_soc_platform_get_drvdata(rtd->platform); + struct sst_byt_pcm_data *pcm_data = snd_soc_pcm_get_drvdata(rtd); + struct sst_byt *byt = pdata->byt; + + dev_dbg(rtd->dev, "PCM: trigger %d\n", cmd); + + switch (cmd) { + case SNDRV_PCM_TRIGGER_START: + sst_byt_stream_start(byt, pcm_data->stream); + break; + case SNDRV_PCM_TRIGGER_RESUME: + case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: + sst_byt_stream_resume(byt, pcm_data->stream); + break; + case SNDRV_PCM_TRIGGER_STOP: + sst_byt_stream_stop(byt, pcm_data->stream); + break; + case SNDRV_PCM_TRIGGER_SUSPEND: + case SNDRV_PCM_TRIGGER_PAUSE_PUSH: + sst_byt_stream_pause(byt, pcm_data->stream); + break; + default: + break; + } + + return 0; +} + +static u32 byt_notify_pointer(struct sst_byt_stream *stream, void *data) +{ + struct sst_byt_pcm_data *pcm_data = data; + struct snd_pcm_substream *substream = pcm_data->substream; + struct snd_pcm_runtime *runtime = substream->runtime; + struct snd_soc_pcm_runtime *rtd = substream->private_data; + u32 pos; + + pos = frames_to_bytes(runtime, + (runtime->control->appl_ptr % + runtime->buffer_size)); + + dev_dbg(rtd->dev, "PCM: App pointer %d bytes\n", pos); + + snd_pcm_period_elapsed(substream); + return pos; +} + +static snd_pcm_uframes_t sst_byt_pcm_pointer(struct snd_pcm_substream *substream) +{ + struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_pcm_runtime *runtime = substream->runtime; + struct sst_byt_priv_data *pdata = + snd_soc_platform_get_drvdata(rtd->platform); + struct sst_byt_pcm_data *pcm_data = snd_soc_pcm_get_drvdata(rtd); + struct sst_byt *byt = pdata->byt; + snd_pcm_uframes_t offset; + int pos; + + pos = sst_byt_get_dsp_position(byt, pcm_data->stream, + snd_pcm_lib_buffer_bytes(substream)); + offset = bytes_to_frames(runtime, pos); + + dev_dbg(rtd->dev, "PCM: DMA pointer %zu bytes\n", + frames_to_bytes(runtime, (u32)offset)); + return offset; +} + +static int sst_byt_pcm_open(struct snd_pcm_substream *substream) +{ + struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct sst_byt_priv_data *pdata = + snd_soc_platform_get_drvdata(rtd->platform); + struct sst_byt_pcm_data *pcm_data = snd_soc_pcm_get_drvdata(rtd); + struct sst_byt *byt = pdata->byt; + + dev_dbg(rtd->dev, "PCM: open\n"); + + pcm_data = &pdata->pcm[rtd->cpu_dai->id]; + mutex_lock(&pcm_data->mutex); + + snd_soc_pcm_set_drvdata(rtd, pcm_data); + pcm_data->substream = substream; + + snd_soc_set_runtime_hwparams(substream, &sst_byt_pcm_hardware); + + pcm_data->stream = sst_byt_stream_new(byt, rtd->cpu_dai->id + 1, + byt_notify_pointer, pcm_data); + if (pcm_data->stream == NULL) { + dev_err(rtd->dev, "failed to create stream\n"); + mutex_unlock(&pcm_data->mutex); + return -EINVAL; + } + + mutex_unlock(&pcm_data->mutex); + return 0; +} + +static int sst_byt_pcm_close(struct snd_pcm_substream *substream) +{ + struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct sst_byt_priv_data *pdata = + snd_soc_platform_get_drvdata(rtd->platform); + struct sst_byt_pcm_data *pcm_data = snd_soc_pcm_get_drvdata(rtd); + struct sst_byt *byt = pdata->byt; + int ret; + + dev_dbg(rtd->dev, "PCM: close\n"); + + mutex_lock(&pcm_data->mutex); + ret = sst_byt_stream_free(byt, pcm_data->stream); + if (ret < 0) { + dev_dbg(rtd->dev, "Free stream fail\n"); + goto out; + } + pcm_data->stream = NULL; + +out: + mutex_unlock(&pcm_data->mutex); + return ret; +} + +static int sst_byt_pcm_mmap(struct snd_pcm_substream *substream, + struct vm_area_struct *vma) +{ + struct snd_soc_pcm_runtime *rtd = substream->private_data; + + dev_dbg(rtd->dev, "PCM: mmap\n"); + return snd_pcm_lib_default_mmap(substream, vma); +} + +static struct snd_pcm_ops sst_byt_pcm_ops = { + .open = sst_byt_pcm_open, + .close = sst_byt_pcm_close, + .ioctl = snd_pcm_lib_ioctl, + .hw_params = sst_byt_pcm_hw_params, + .hw_free = sst_byt_pcm_hw_free, + .trigger = sst_byt_pcm_trigger, + .pointer = sst_byt_pcm_pointer, + .mmap = sst_byt_pcm_mmap, +}; + +static void sst_byt_pcm_free(struct snd_pcm *pcm) +{ + snd_pcm_lib_preallocate_free_for_all(pcm); +} + +static int sst_byt_pcm_new(struct snd_soc_pcm_runtime *rtd) +{ + struct snd_pcm *pcm = rtd->pcm; + size_t size; + int ret = 0; + + ret = dma_coerce_mask_and_coherent(rtd->card->dev, DMA_BIT_MASK(32)); + if (ret) + return ret; + + if (pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream || + pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream) { + size = sst_byt_pcm_hardware.buffer_bytes_max; + ret = snd_pcm_lib_preallocate_pages_for_all(pcm, + SNDRV_DMA_TYPE_DEV, + rtd->card->dev, + size, size); + if (ret) { + dev_err(rtd->dev, "dma buffer allocation failed %d\n", + ret); + return ret; + } + } + + return ret; +} + +static struct snd_soc_dai_driver byt_dais[] = { + { + .name = "Front-cpu-dai", + .playback = { + .stream_name = "System Playback", + .channels_min = 2, + .channels_max = 2, + .rates = SNDRV_PCM_RATE_48000, + .formats = SNDRV_PCM_FMTBIT_S24_3LE | + SNDRV_PCM_FMTBIT_S16_LE, + }, + }, + { + .name = "Mic1-cpu-dai", + .capture = { + .stream_name = "Analog Capture", + .channels_min = 2, + .channels_max = 2, + .rates = SNDRV_PCM_RATE_48000, + .formats = SNDRV_PCM_FMTBIT_S16_LE, + }, + }, +}; + +static int sst_byt_pcm_probe(struct snd_soc_platform *platform) +{ + struct sst_pdata *plat_data = dev_get_platdata(platform->dev); + struct sst_byt_priv_data *priv_data; + int i; + + if (!plat_data) + return -ENODEV; + + priv_data = devm_kzalloc(platform->dev, sizeof(*priv_data), + GFP_KERNEL); + priv_data->byt = plat_data->dsp; + snd_soc_platform_set_drvdata(platform, priv_data); + + for (i = 0; i < ARRAY_SIZE(byt_dais); i++) + mutex_init(&priv_data->pcm[i].mutex); + + return 0; +} + +static int sst_byt_pcm_remove(struct snd_soc_platform *platform) +{ + return 0; +} + +static struct snd_soc_platform_driver byt_soc_platform = { + .probe = sst_byt_pcm_probe, + .remove = sst_byt_pcm_remove, + .ops = &sst_byt_pcm_ops, + .pcm_new = sst_byt_pcm_new, + .pcm_free = sst_byt_pcm_free, +}; + +static const struct snd_soc_component_driver byt_dai_component = { + .name = "byt-dai", +}; + +static int sst_byt_pcm_dev_probe(struct platform_device *pdev) +{ + struct sst_pdata *sst_pdata = dev_get_platdata(&pdev->dev); + int ret; + + ret = sst_byt_dsp_init(&pdev->dev, sst_pdata); + if (ret < 0) + return -ENODEV; + + ret = snd_soc_register_platform(&pdev->dev, &byt_soc_platform); + if (ret < 0) + goto err_plat; + + ret = snd_soc_register_component(&pdev->dev, &byt_dai_component, + byt_dais, ARRAY_SIZE(byt_dais)); + if (ret < 0) + goto err_comp; + + return 0; + +err_comp: + snd_soc_unregister_platform(&pdev->dev); +err_plat: + sst_byt_dsp_free(&pdev->dev, sst_pdata); + return ret; +} + +static int sst_byt_pcm_dev_remove(struct platform_device *pdev) +{ + struct sst_pdata *sst_pdata = dev_get_platdata(&pdev->dev); + + snd_soc_unregister_platform(&pdev->dev); + snd_soc_unregister_component(&pdev->dev); + sst_byt_dsp_free(&pdev->dev, sst_pdata); + + return 0; +} + +static struct platform_driver sst_byt_pcm_driver = { + .driver = { + .name = "baytrail-pcm-audio", + .owner = THIS_MODULE, + }, + + .probe = sst_byt_pcm_dev_probe, + .remove = sst_byt_pcm_dev_remove, +}; +module_platform_driver(sst_byt_pcm_driver); + +MODULE_AUTHOR("Jarkko Nikula"); +MODULE_DESCRIPTION("Baytrail PCM"); +MODULE_LICENSE("GPL v2"); +MODULE_ALIAS("platform:baytrail-pcm-audio"); diff --git a/sound/soc/intel/sst-dsp-priv.h b/sound/soc/intel/sst-dsp-priv.h new file mode 100644 index 00000000000..fe8e81aad64 --- /dev/null +++ b/sound/soc/intel/sst-dsp-priv.h @@ -0,0 +1,309 @@ +/* + * Intel Smart Sound Technology + * + * Copyright (C) 2013, Intel Corporation. All rights reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License version + * 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +#ifndef __SOUND_SOC_SST_DSP_PRIV_H +#define __SOUND_SOC_SST_DSP_PRIV_H + +#include <linux/kernel.h> +#include <linux/types.h> +#include <linux/interrupt.h> +#include <linux/firmware.h> + +struct sst_mem_block; +struct sst_module; +struct sst_fw; + +/* + * DSP Operations exported by platform Audio DSP driver. + */ +struct sst_ops { + /* DSP core boot / reset */ + void (*boot)(struct sst_dsp *); + void (*reset)(struct sst_dsp *); + + /* Shim IO */ + void (*write)(void __iomem *addr, u32 offset, u32 value); + u32 (*read)(void __iomem *addr, u32 offset); + void (*write64)(void __iomem *addr, u32 offset, u64 value); + u64 (*read64)(void __iomem *addr, u32 offset); + + /* DSP I/DRAM IO */ + void (*ram_read)(struct sst_dsp *sst, void *dest, void __iomem *src, + size_t bytes); + void (*ram_write)(struct sst_dsp *sst, void __iomem *dest, void *src, + size_t bytes); + + void (*dump)(struct sst_dsp *); + + /* IRQ handlers */ + irqreturn_t (*irq_handler)(int irq, void *context); + + /* SST init and free */ + int (*init)(struct sst_dsp *sst, struct sst_pdata *pdata); + void (*free)(struct sst_dsp *sst); + + /* FW module parser/loader */ + int (*parse_fw)(struct sst_fw *sst_fw); +}; + +/* + * Audio DSP memory offsets and addresses. + */ +struct sst_addr { + u32 lpe_base; + u32 shim_offset; + u32 iram_offset; + u32 dram_offset; + void __iomem *lpe; + void __iomem *shim; + void __iomem *pci_cfg; + void __iomem *fw_ext; +}; + +/* + * Audio DSP Mailbox configuration. + */ +struct sst_mailbox { + void __iomem *in_base; + void __iomem *out_base; + size_t in_size; + size_t out_size; +}; + +/* + * Audio DSP Firmware data types. + */ +enum sst_data_type { + SST_DATA_M = 0, /* module block data */ + SST_DATA_P = 1, /* peristant data (text, data) */ + SST_DATA_S = 2, /* scratch data (usually buffers) */ +}; + +/* + * Audio DSP memory block types. + */ +enum sst_mem_type { + SST_MEM_IRAM = 0, + SST_MEM_DRAM = 1, + SST_MEM_ANY = 2, + SST_MEM_CACHE= 3, +}; + +/* + * Audio DSP Generic Firmware File. + * + * SST Firmware files can consist of 1..N modules. This generic structure is + * used to manage each firmware file and it's modules regardless of SST firmware + * type. A SST driver may load multiple FW files. + */ +struct sst_fw { + struct sst_dsp *dsp; + + /* base addresses of FW file data */ + dma_addr_t dmable_fw_paddr; /* physical address of fw data */ + void *dma_buf; /* virtual address of fw data */ + u32 size; /* size of fw data */ + + /* lists */ + struct list_head list; /* DSP list of FW */ + struct list_head module_list; /* FW list of modules */ + + void *private; /* core doesn't touch this */ +}; + +/* + * Audio DSP Generic Module data. + * + * This is used to dsecribe any sections of persistent (text and data) and + * scratch (buffers) of module data in ADSP memory space. + */ +struct sst_module_data { + + enum sst_mem_type type; /* destination memory type */ + enum sst_data_type data_type; /* type of module data */ + + u32 size; /* size in bytes */ + u32 offset; /* offset in FW file */ + u32 data_offset; /* offset in ADSP memory space */ + void *data; /* module data */ +}; + +/* + * Audio DSP Generic Module Template. + * + * Used to define and register a new FW module. This data is extracted from + * FW module header information. + */ +struct sst_module_template { + u32 id; + u32 entry; /* entry point */ + struct sst_module_data s; /* scratch data */ + struct sst_module_data p; /* peristant data */ +}; + +/* + * Audio DSP Generic Module. + * + * Each Firmware file can consist of 1..N modules. A module can span multiple + * ADSP memory blocks. The simplest FW will be a file with 1 module. + */ +struct sst_module { + struct sst_dsp *dsp; + struct sst_fw *sst_fw; /* parent FW we belong too */ + + /* module configuration */ + u32 id; + u32 entry; /* module entry point */ + u32 offset; /* module offset in firmware file */ + u32 size; /* module size */ + struct sst_module_data s; /* scratch data */ + struct sst_module_data p; /* peristant data */ + + /* runtime */ + u32 usage_count; /* can be unloaded if count == 0 */ + void *private; /* core doesn't touch this */ + + /* lists */ + struct list_head block_list; /* Module list of blocks in use */ + struct list_head list; /* DSP list of modules */ + struct list_head list_fw; /* FW list of modules */ +}; + +/* + * SST Memory Block operations. + */ +struct sst_block_ops { + int (*enable)(struct sst_mem_block *block); + int (*disable)(struct sst_mem_block *block); +}; + +/* + * SST Generic Memory Block. + * + * SST ADP memory has multiple IRAM and DRAM blocks. Some ADSP blocks can be + * power gated. + */ +struct sst_mem_block { + struct sst_dsp *dsp; + struct sst_module *module; /* module that uses this block */ + + /* block config */ + u32 offset; /* offset from base */ + u32 size; /* block size */ + u32 index; /* block index 0..N */ + enum sst_mem_type type; /* block memory type IRAM/DRAM */ + struct sst_block_ops *ops; /* block operations, if any */ + + /* block status */ + enum sst_data_type data_type; /* data type held in this block */ + u32 bytes_used; /* bytes in use by modules */ + void *private; /* generic core does not touch this */ + int users; /* number of modules using this block */ + + /* block lists */ + struct list_head module_list; /* Module list of blocks */ + struct list_head list; /* Map list of free/used blocks */ +}; + +/* + * Generic SST Shim Interface. + */ +struct sst_dsp { + + /* runtime */ + struct sst_dsp_device *sst_dev; + spinlock_t spinlock; /* IPC locking */ + struct mutex mutex; /* DSP FW lock */ + struct device *dev; + void *thread_context; + int irq; + u32 id; + + /* list of free and used ADSP memory blocks */ + struct list_head used_block_list; + struct list_head free_block_list; + + /* operations */ + struct sst_ops *ops; + + /* debug FS */ + struct dentry *debugfs_root; + + /* base addresses */ + struct sst_addr addr; + + /* mailbox */ + struct sst_mailbox mailbox; + + /* SST FW files loaded and their modules */ + struct list_head module_list; + struct list_head fw_list; + + /* platform data */ + struct sst_pdata *pdata; + + /* DMA FW loading */ + struct sst_dma *dma; + bool fw_use_dma; +}; + +/* Size optimised DRAM/IRAM memcpy */ +static inline void sst_dsp_write(struct sst_dsp *sst, void *src, + u32 dest_offset, size_t bytes) +{ + sst->ops->ram_write(sst, sst->addr.lpe + dest_offset, src, bytes); +} + +static inline void sst_dsp_read(struct sst_dsp *sst, void *dest, + u32 src_offset, size_t bytes) +{ + sst->ops->ram_read(sst, dest, sst->addr.lpe + src_offset, bytes); +} + +static inline void *sst_dsp_get_thread_context(struct sst_dsp *sst) +{ + return sst->thread_context; +} + +/* Create/Free FW files - can contain multiple modules */ +struct sst_fw *sst_fw_new(struct sst_dsp *dsp, + const struct firmware *fw, void *private); +void sst_fw_free(struct sst_fw *sst_fw); +void sst_fw_free_all(struct sst_dsp *dsp); + +/* Create/Free firmware modules */ +struct sst_module *sst_module_new(struct sst_fw *sst_fw, + struct sst_module_template *template, void *private); +void sst_module_free(struct sst_module *sst_module); +int sst_module_insert(struct sst_module *sst_module); +int sst_module_remove(struct sst_module *sst_module); +int sst_module_insert_fixed_block(struct sst_module *module, + struct sst_module_data *data); +struct sst_module *sst_module_get_from_id(struct sst_dsp *dsp, u32 id); + +/* allocate/free pesistent/scratch memory regions managed by drv */ +struct sst_module *sst_mem_block_alloc_scratch(struct sst_dsp *dsp); +void sst_mem_block_free_scratch(struct sst_dsp *dsp, + struct sst_module *scratch); +int sst_block_module_remove(struct sst_module *module); + +/* Register the DSPs memory blocks - would be nice to read from ACPI */ +struct sst_mem_block *sst_mem_block_register(struct sst_dsp *dsp, u32 offset, + u32 size, enum sst_mem_type type, struct sst_block_ops *ops, u32 index, + void *private); +void sst_mem_block_unregister_all(struct sst_dsp *dsp); + +#endif diff --git a/sound/soc/intel/sst-dsp.c b/sound/soc/intel/sst-dsp.c new file mode 100644 index 00000000000..0c129fd85ec --- /dev/null +++ b/sound/soc/intel/sst-dsp.c @@ -0,0 +1,385 @@ +/* + * Intel Smart Sound Technology (SST) DSP Core Driver + * + * Copyright (C) 2013, Intel Corporation. All rights reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License version + * 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +#include <linux/slab.h> +#include <linux/export.h> +#include <linux/interrupt.h> +#include <linux/module.h> +#include <linux/platform_device.h> +#include <linux/io.h> + +#include "sst-dsp.h" +#include "sst-dsp-priv.h" + +#define CREATE_TRACE_POINTS +#include <trace/events/intel-sst.h> + +/* Internal generic low-level SST IO functions - can be overidden */ +void sst_shim32_write(void __iomem *addr, u32 offset, u32 value) +{ + writel(value, addr + offset); +} +EXPORT_SYMBOL_GPL(sst_shim32_write); + +u32 sst_shim32_read(void __iomem *addr, u32 offset) +{ + return readl(addr + offset); +} +EXPORT_SYMBOL_GPL(sst_shim32_read); + +void sst_shim32_write64(void __iomem *addr, u32 offset, u64 value) +{ + memcpy_toio(addr + offset, &value, sizeof(value)); +} +EXPORT_SYMBOL_GPL(sst_shim32_write64); + +u64 sst_shim32_read64(void __iomem *addr, u32 offset) +{ + u64 val; + + memcpy_fromio(&val, addr + offset, sizeof(val)); + return val; +} +EXPORT_SYMBOL_GPL(sst_shim32_read64); + +static inline void _sst_memcpy_toio_32(volatile u32 __iomem *dest, + u32 *src, size_t bytes) +{ + int i, words = bytes >> 2; + + for (i = 0; i < words; i++) + writel(src[i], dest + i); +} + +static inline void _sst_memcpy_fromio_32(u32 *dest, + const volatile __iomem u32 *src, size_t bytes) +{ + int i, words = bytes >> 2; + + for (i = 0; i < words; i++) + dest[i] = readl(src + i); +} + +void sst_memcpy_toio_32(struct sst_dsp *sst, + void __iomem *dest, void *src, size_t bytes) +{ + _sst_memcpy_toio_32(dest, src, bytes); +} +EXPORT_SYMBOL_GPL(sst_memcpy_toio_32); + +void sst_memcpy_fromio_32(struct sst_dsp *sst, void *dest, + void __iomem *src, size_t bytes) +{ + _sst_memcpy_fromio_32(dest, src, bytes); +} +EXPORT_SYMBOL_GPL(sst_memcpy_fromio_32); + +/* Public API */ +void sst_dsp_shim_write(struct sst_dsp *sst, u32 offset, u32 value) +{ + unsigned long flags; + + spin_lock_irqsave(&sst->spinlock, flags); + sst->ops->write(sst->addr.shim, offset, value); + spin_unlock_irqrestore(&sst->spinlock, flags); +} +EXPORT_SYMBOL_GPL(sst_dsp_shim_write); + +u32 sst_dsp_shim_read(struct sst_dsp *sst, u32 offset) +{ + unsigned long flags; + u32 val; + + spin_lock_irqsave(&sst->spinlock, flags); + val = sst->ops->read(sst->addr.shim, offset); + spin_unlock_irqrestore(&sst->spinlock, flags); + + return val; +} +EXPORT_SYMBOL_GPL(sst_dsp_shim_read); + +void sst_dsp_shim_write64(struct sst_dsp *sst, u32 offset, u64 value) +{ + unsigned long flags; + + spin_lock_irqsave(&sst->spinlock, flags); + sst->ops->write64(sst->addr.shim, offset, value); + spin_unlock_irqrestore(&sst->spinlock, flags); +} +EXPORT_SYMBOL_GPL(sst_dsp_shim_write64); + +u64 sst_dsp_shim_read64(struct sst_dsp *sst, u32 offset) +{ + unsigned long flags; + u64 val; + + spin_lock_irqsave(&sst->spinlock, flags); + val = sst->ops->read64(sst->addr.shim, offset); + spin_unlock_irqrestore(&sst->spinlock, flags); + + return val; +} +EXPORT_SYMBOL_GPL(sst_dsp_shim_read64); + +void sst_dsp_shim_write_unlocked(struct sst_dsp *sst, u32 offset, u32 value) +{ + sst->ops->write(sst->addr.shim, offset, value); +} +EXPORT_SYMBOL_GPL(sst_dsp_shim_write_unlocked); + +u32 sst_dsp_shim_read_unlocked(struct sst_dsp *sst, u32 offset) +{ + return sst->ops->read(sst->addr.shim, offset); +} +EXPORT_SYMBOL_GPL(sst_dsp_shim_read_unlocked); + +void sst_dsp_shim_write64_unlocked(struct sst_dsp *sst, u32 offset, u64 value) +{ + sst->ops->write64(sst->addr.shim, offset, value); +} +EXPORT_SYMBOL_GPL(sst_dsp_shim_write64_unlocked); + +u64 sst_dsp_shim_read64_unlocked(struct sst_dsp *sst, u32 offset) +{ + return sst->ops->read64(sst->addr.shim, offset); +} +EXPORT_SYMBOL_GPL(sst_dsp_shim_read64_unlocked); + +int sst_dsp_shim_update_bits_unlocked(struct sst_dsp *sst, u32 offset, + u32 mask, u32 value) +{ + bool change; + unsigned int old, new; + u32 ret; + + ret = sst_dsp_shim_read_unlocked(sst, offset); + + old = ret; + new = (old & (~mask)) | (value & mask); + + change = (old != new); + if (change) + sst_dsp_shim_write_unlocked(sst, offset, new); + + return change; +} +EXPORT_SYMBOL_GPL(sst_dsp_shim_update_bits_unlocked); + +int sst_dsp_shim_update_bits64_unlocked(struct sst_dsp *sst, u32 offset, + u64 mask, u64 value) +{ + bool change; + u64 old, new; + + old = sst_dsp_shim_read64_unlocked(sst, offset); + + new = (old & (~mask)) | (value & mask); + + change = (old != new); + if (change) + sst_dsp_shim_write64_unlocked(sst, offset, new); + + return change; +} +EXPORT_SYMBOL_GPL(sst_dsp_shim_update_bits64_unlocked); + +int sst_dsp_shim_update_bits(struct sst_dsp *sst, u32 offset, + u32 mask, u32 value) +{ + unsigned long flags; + bool change; + + spin_lock_irqsave(&sst->spinlock, flags); + change = sst_dsp_shim_update_bits_unlocked(sst, offset, mask, value); + spin_unlock_irqrestore(&sst->spinlock, flags); + return change; +} +EXPORT_SYMBOL_GPL(sst_dsp_shim_update_bits); + +int sst_dsp_shim_update_bits64(struct sst_dsp *sst, u32 offset, + u64 mask, u64 value) +{ + unsigned long flags; + bool change; + + spin_lock_irqsave(&sst->spinlock, flags); + change = sst_dsp_shim_update_bits64_unlocked(sst, offset, mask, value); + spin_unlock_irqrestore(&sst->spinlock, flags); + return change; +} +EXPORT_SYMBOL_GPL(sst_dsp_shim_update_bits64); + +void sst_dsp_dump(struct sst_dsp *sst) +{ + sst->ops->dump(sst); +} +EXPORT_SYMBOL_GPL(sst_dsp_dump); + +void sst_dsp_reset(struct sst_dsp *sst) +{ + sst->ops->reset(sst); +} +EXPORT_SYMBOL_GPL(sst_dsp_reset); + +int sst_dsp_boot(struct sst_dsp *sst) +{ + sst->ops->boot(sst); + return 0; +} +EXPORT_SYMBOL_GPL(sst_dsp_boot); + +void sst_dsp_ipc_msg_tx(struct sst_dsp *dsp, u32 msg) +{ + sst_dsp_shim_write_unlocked(dsp, SST_IPCX, msg | SST_IPCX_BUSY); + trace_sst_ipc_msg_tx(msg); +} +EXPORT_SYMBOL_GPL(sst_dsp_ipc_msg_tx); + +u32 sst_dsp_ipc_msg_rx(struct sst_dsp *dsp) +{ + u32 msg; + + msg = sst_dsp_shim_read_unlocked(dsp, SST_IPCX); + trace_sst_ipc_msg_rx(msg); + + return msg; +} +EXPORT_SYMBOL_GPL(sst_dsp_ipc_msg_rx); + +int sst_dsp_mailbox_init(struct sst_dsp *sst, u32 inbox_offset, size_t inbox_size, + u32 outbox_offset, size_t outbox_size) +{ + sst->mailbox.in_base = sst->addr.lpe + inbox_offset; + sst->mailbox.out_base = sst->addr.lpe + outbox_offset; + sst->mailbox.in_size = inbox_size; + sst->mailbox.out_size = outbox_size; + return 0; +} +EXPORT_SYMBOL_GPL(sst_dsp_mailbox_init); + +void sst_dsp_outbox_write(struct sst_dsp *sst, void *message, size_t bytes) +{ + u32 i; + + trace_sst_ipc_outbox_write(bytes); + + memcpy_toio(sst->mailbox.out_base, message, bytes); + + for (i = 0; i < bytes; i += 4) + trace_sst_ipc_outbox_wdata(i, *(u32 *)(message + i)); +} +EXPORT_SYMBOL_GPL(sst_dsp_outbox_write); + +void sst_dsp_outbox_read(struct sst_dsp *sst, void *message, size_t bytes) +{ + u32 i; + + trace_sst_ipc_outbox_read(bytes); + + memcpy_fromio(message, sst->mailbox.out_base, bytes); + + for (i = 0; i < bytes; i += 4) + trace_sst_ipc_outbox_rdata(i, *(u32 *)(message + i)); +} +EXPORT_SYMBOL_GPL(sst_dsp_outbox_read); + +void sst_dsp_inbox_write(struct sst_dsp *sst, void *message, size_t bytes) +{ + u32 i; + + trace_sst_ipc_inbox_write(bytes); + + memcpy_toio(sst->mailbox.in_base, message, bytes); + + for (i = 0; i < bytes; i += 4) + trace_sst_ipc_inbox_wdata(i, *(u32 *)(message + i)); +} +EXPORT_SYMBOL_GPL(sst_dsp_inbox_write); + +void sst_dsp_inbox_read(struct sst_dsp *sst, void *message, size_t bytes) +{ + u32 i; + + trace_sst_ipc_inbox_read(bytes); + + memcpy_fromio(message, sst->mailbox.in_base, bytes); + + for (i = 0; i < bytes; i += 4) + trace_sst_ipc_inbox_rdata(i, *(u32 *)(message + i)); +} +EXPORT_SYMBOL_GPL(sst_dsp_inbox_read); + +struct sst_dsp *sst_dsp_new(struct device *dev, + struct sst_dsp_device *sst_dev, struct sst_pdata *pdata) +{ + struct sst_dsp *sst; + int err; + + dev_dbg(dev, "initialising audio DSP id 0x%x\n", pdata->id); + + sst = devm_kzalloc(dev, sizeof(*sst), GFP_KERNEL); + if (sst == NULL) + return NULL; + + spin_lock_init(&sst->spinlock); + mutex_init(&sst->mutex); + sst->dev = dev; + sst->thread_context = sst_dev->thread_context; + sst->sst_dev = sst_dev; + sst->id = pdata->id; + sst->irq = pdata->irq; + sst->ops = sst_dev->ops; + sst->pdata = pdata; + INIT_LIST_HEAD(&sst->used_block_list); + INIT_LIST_HEAD(&sst->free_block_list); + INIT_LIST_HEAD(&sst->module_list); + INIT_LIST_HEAD(&sst->fw_list); + + /* Initialise SST Audio DSP */ + if (sst->ops->init) { + err = sst->ops->init(sst, pdata); + if (err < 0) + return NULL; + } + + /* Register the ISR */ + err = request_threaded_irq(sst->irq, sst->ops->irq_handler, + sst_dev->thread, IRQF_SHARED, "AudioDSP", sst); + if (err) + goto irq_err; + + return sst; + +irq_err: + if (sst->ops->free) + sst->ops->free(sst); + + return NULL; +} +EXPORT_SYMBOL_GPL(sst_dsp_new); + +void sst_dsp_free(struct sst_dsp *sst) +{ + free_irq(sst->irq, sst); + if (sst->ops->free) + sst->ops->free(sst); +} +EXPORT_SYMBOL_GPL(sst_dsp_free); + +/* Module information */ +MODULE_AUTHOR("Liam Girdwood"); +MODULE_DESCRIPTION("Intel SST Core"); +MODULE_LICENSE("GPL v2"); diff --git a/sound/soc/intel/sst-dsp.h b/sound/soc/intel/sst-dsp.h new file mode 100644 index 00000000000..74052b59485 --- /dev/null +++ b/sound/soc/intel/sst-dsp.h @@ -0,0 +1,233 @@ +/* + * Intel Smart Sound Technology (SST) Core + * + * Copyright (C) 2013, Intel Corporation. All rights reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License version + * 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +#ifndef __SOUND_SOC_SST_DSP_H +#define __SOUND_SOC_SST_DSP_H + +#include <linux/kernel.h> +#include <linux/types.h> +#include <linux/interrupt.h> + +/* SST Device IDs */ +#define SST_DEV_ID_LYNX_POINT 0x33C8 +#define SST_DEV_ID_WILDCAT_POINT 0x3438 +#define SST_DEV_ID_BYT 0x0F28 + +/* Supported SST DMA Devices */ +#define SST_DMA_TYPE_DW 1 +#define SST_DMA_TYPE_MID 2 + +/* SST Shim register map + * The register naming can differ between products. Some products also + * contain extra functionality. + */ +#define SST_CSR 0x00 +#define SST_PISR 0x08 +#define SST_PIMR 0x10 +#define SST_ISRX 0x18 +#define SST_ISRD 0x20 +#define SST_IMRX 0x28 +#define SST_IMRD 0x30 +#define SST_IPCX 0x38 /* IPC IA -> SST */ +#define SST_IPCD 0x40 /* IPC SST -> IA */ +#define SST_ISRSC 0x48 +#define SST_ISRLPESC 0x50 +#define SST_IMRSC 0x58 +#define SST_IMRLPESC 0x60 +#define SST_IPCSC 0x68 +#define SST_IPCLPESC 0x70 +#define SST_CLKCTL 0x78 +#define SST_CSR2 0x80 +#define SST_LTRC 0xE0 +#define SST_HDMC 0xE8 +#define SST_DBGO 0xF0 + +#define SST_SHIM_SIZE 0x100 +#define SST_PWMCTRL 0x1000 + +/* SST Shim Register bits + * The register bit naming can differ between products. Some products also + * contain extra functionality. + */ + +/* CSR / CS */ +#define SST_CSR_RST (0x1 << 1) +#define SST_CSR_SBCS0 (0x1 << 2) +#define SST_CSR_SBCS1 (0x1 << 3) +#define SST_CSR_DCS(x) (x << 4) +#define SST_CSR_DCS_MASK (0x7 << 4) +#define SST_CSR_STALL (0x1 << 10) +#define SST_CSR_S0IOCS (0x1 << 21) +#define SST_CSR_S1IOCS (0x1 << 23) +#define SST_CSR_LPCS (0x1 << 31) +#define SST_BYT_CSR_RST (0x1 << 0) +#define SST_BYT_CSR_VECTOR_SEL (0x1 << 1) +#define SST_BYT_CSR_STALL (0x1 << 2) +#define SST_BYT_CSR_PWAITMODE (0x1 << 3) + +/* ISRX / ISC */ +#define SST_ISRX_BUSY (0x1 << 1) +#define SST_ISRX_DONE (0x1 << 0) +#define SST_BYT_ISRX_REQUEST (0x1 << 1) + +/* ISRD / ISD */ +#define SST_ISRD_BUSY (0x1 << 1) +#define SST_ISRD_DONE (0x1 << 0) + +/* IMRX / IMC */ +#define SST_IMRX_BUSY (0x1 << 1) +#define SST_IMRX_DONE (0x1 << 0) +#define SST_BYT_IMRX_REQUEST (0x1 << 1) + +/* IPCX / IPCC */ +#define SST_IPCX_DONE (0x1 << 30) +#define SST_IPCX_BUSY (0x1 << 31) +#define SST_BYT_IPCX_DONE ((u64)0x1 << 62) +#define SST_BYT_IPCX_BUSY ((u64)0x1 << 63) + +/* IPCD */ +#define SST_IPCD_DONE (0x1 << 30) +#define SST_IPCD_BUSY (0x1 << 31) +#define SST_BYT_IPCD_DONE ((u64)0x1 << 62) +#define SST_BYT_IPCD_BUSY ((u64)0x1 << 63) + +/* CLKCTL */ +#define SST_CLKCTL_SMOS(x) (x << 24) +#define SST_CLKCTL_MASK (3 << 24) +#define SST_CLKCTL_DCPLCG (1 << 18) +#define SST_CLKCTL_SCOE1 (1 << 17) +#define SST_CLKCTL_SCOE0 (1 << 16) + +/* CSR2 / CS2 */ +#define SST_CSR2_SDFD_SSP0 (1 << 1) +#define SST_CSR2_SDFD_SSP1 (1 << 2) + +/* LTRC */ +#define SST_LTRC_VAL(x) (x << 0) + +/* HDMC */ +#define SST_HDMC_HDDA0(x) (x << 0) +#define SST_HDMC_HDDA1(x) (x << 7) + + +/* SST Vendor Defined Registers and bits */ +#define SST_VDRTCTL0 0xa0 +#define SST_VDRTCTL1 0xa4 +#define SST_VDRTCTL2 0xa8 +#define SST_VDRTCTL3 0xaC + +/* VDRTCTL0 */ +#define SST_VDRTCL0_DSRAMPGE_SHIFT 16 +#define SST_VDRTCL0_DSRAMPGE_MASK (0xffff << SST_VDRTCL0_DSRAMPGE_SHIFT) +#define SST_VDRTCL0_ISRAMPGE_SHIFT 6 +#define SST_VDRTCL0_ISRAMPGE_MASK (0x3ff << SST_VDRTCL0_ISRAMPGE_SHIFT) + +struct sst_dsp; + +/* + * SST Device. + * + * This structure is populated by the SST core driver. + */ +struct sst_dsp_device { + /* Mandatory fields */ + struct sst_ops *ops; + irqreturn_t (*thread)(int irq, void *context); + void *thread_context; +}; + +/* + * SST Platform Data. + */ +struct sst_pdata { + /* ACPI data */ + u32 lpe_base; + u32 lpe_size; + u32 pcicfg_base; + u32 pcicfg_size; + u32 fw_base; + u32 fw_size; + int irq; + + /* Firmware */ + const struct firmware *fw; + + /* DMA */ + u32 dma_base; + u32 dma_size; + int dma_engine; + + /* DSP */ + u32 id; + void *dsp; +}; + +/* Initialization */ +struct sst_dsp *sst_dsp_new(struct device *dev, + struct sst_dsp_device *sst_dev, struct sst_pdata *pdata); +void sst_dsp_free(struct sst_dsp *sst); + +/* SHIM Read / Write */ +void sst_dsp_shim_write(struct sst_dsp *sst, u32 offset, u32 value); +u32 sst_dsp_shim_read(struct sst_dsp *sst, u32 offset); +int sst_dsp_shim_update_bits(struct sst_dsp *sst, u32 offset, + u32 mask, u32 value); +void sst_dsp_shim_write64(struct sst_dsp *sst, u32 offset, u64 value); +u64 sst_dsp_shim_read64(struct sst_dsp *sst, u32 offset); +int sst_dsp_shim_update_bits64(struct sst_dsp *sst, u32 offset, + u64 mask, u64 value); + +/* SHIM Read / Write Unlocked for callers already holding sst lock */ +void sst_dsp_shim_write_unlocked(struct sst_dsp *sst, u32 offset, u32 value); +u32 sst_dsp_shim_read_unlocked(struct sst_dsp *sst, u32 offset); +int sst_dsp_shim_update_bits_unlocked(struct sst_dsp *sst, u32 offset, + u32 mask, u32 value); +void sst_dsp_shim_write64_unlocked(struct sst_dsp *sst, u32 offset, u64 value); +u64 sst_dsp_shim_read64_unlocked(struct sst_dsp *sst, u32 offset); +int sst_dsp_shim_update_bits64_unlocked(struct sst_dsp *sst, u32 offset, + u64 mask, u64 value); + +/* Internal generic low-level SST IO functions - can be overidden */ +void sst_shim32_write(void __iomem *addr, u32 offset, u32 value); +u32 sst_shim32_read(void __iomem *addr, u32 offset); +void sst_shim32_write64(void __iomem *addr, u32 offset, u64 value); +u64 sst_shim32_read64(void __iomem *addr, u32 offset); +void sst_memcpy_toio_32(struct sst_dsp *sst, + void __iomem *dest, void *src, size_t bytes); +void sst_memcpy_fromio_32(struct sst_dsp *sst, + void *dest, void __iomem *src, size_t bytes); + +/* DSP reset & boot */ +void sst_dsp_reset(struct sst_dsp *sst); +int sst_dsp_boot(struct sst_dsp *sst); + +/* Msg IO */ +void sst_dsp_ipc_msg_tx(struct sst_dsp *dsp, u32 msg); +u32 sst_dsp_ipc_msg_rx(struct sst_dsp *dsp); + +/* Mailbox management */ +int sst_dsp_mailbox_init(struct sst_dsp *dsp, u32 inbox_offset, + size_t inbox_size, u32 outbox_offset, size_t outbox_size); +void sst_dsp_inbox_write(struct sst_dsp *dsp, void *message, size_t bytes); +void sst_dsp_inbox_read(struct sst_dsp *dsp, void *message, size_t bytes); +void sst_dsp_outbox_write(struct sst_dsp *dsp, void *message, size_t bytes); +void sst_dsp_outbox_read(struct sst_dsp *dsp, void *message, size_t bytes); +void sst_dsp_mailbox_dump(struct sst_dsp *dsp, size_t bytes); + +/* Debug */ +void sst_dsp_dump(struct sst_dsp *sst); + +#endif diff --git a/sound/soc/intel/sst-firmware.c b/sound/soc/intel/sst-firmware.c new file mode 100644 index 00000000000..f7687107cf7 --- /dev/null +++ b/sound/soc/intel/sst-firmware.c @@ -0,0 +1,587 @@ +/* + * Intel SST Firmware Loader + * + * Copyright (C) 2013, Intel Corporation. All rights reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License version + * 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +#include <linux/kernel.h> +#include <linux/slab.h> +#include <linux/sched.h> +#include <linux/firmware.h> +#include <linux/export.h> +#include <linux/platform_device.h> +#include <linux/dma-mapping.h> +#include <linux/dmaengine.h> +#include <linux/pci.h> + +#include <asm/page.h> +#include <asm/pgtable.h> + +#include "sst-dsp.h" +#include "sst-dsp-priv.h" + +static void sst_memcpy32(volatile void __iomem *dest, void *src, u32 bytes) +{ + u32 i; + + /* copy one 32 bit word at a time as 64 bit access is not supported */ + for (i = 0; i < bytes; i += 4) + memcpy_toio(dest + i, src + i, 4); +} + +/* create new generic firmware object */ +struct sst_fw *sst_fw_new(struct sst_dsp *dsp, + const struct firmware *fw, void *private) +{ + struct sst_fw *sst_fw; + int err; + + if (!dsp->ops->parse_fw) + return NULL; + + sst_fw = kzalloc(sizeof(*sst_fw), GFP_KERNEL); + if (sst_fw == NULL) + return NULL; + + sst_fw->dsp = dsp; + sst_fw->private = private; + sst_fw->size = fw->size; + + err = dma_coerce_mask_and_coherent(dsp->dev, DMA_BIT_MASK(32)); + if (err < 0) { + kfree(sst_fw); + return NULL; + } + + /* allocate DMA buffer to store FW data */ + sst_fw->dma_buf = dma_alloc_coherent(dsp->dev, sst_fw->size, + &sst_fw->dmable_fw_paddr, GFP_DMA | GFP_KERNEL); + if (!sst_fw->dma_buf) { + dev_err(dsp->dev, "error: DMA alloc failed\n"); + kfree(sst_fw); + return NULL; + } + + /* copy FW data to DMA-able memory */ + memcpy((void *)sst_fw->dma_buf, (void *)fw->data, fw->size); + + /* call core specific FW paser to load FW data into DSP */ + err = dsp->ops->parse_fw(sst_fw); + if (err < 0) { + dev_err(dsp->dev, "error: parse fw failed %d\n", err); + goto parse_err; + } + + mutex_lock(&dsp->mutex); + list_add(&sst_fw->list, &dsp->fw_list); + mutex_unlock(&dsp->mutex); + + return sst_fw; + +parse_err: + dma_free_coherent(dsp->dev, sst_fw->size, + sst_fw->dma_buf, + sst_fw->dmable_fw_paddr); + kfree(sst_fw); + return NULL; +} +EXPORT_SYMBOL_GPL(sst_fw_new); + +/* free single firmware object */ +void sst_fw_free(struct sst_fw *sst_fw) +{ + struct sst_dsp *dsp = sst_fw->dsp; + + mutex_lock(&dsp->mutex); + list_del(&sst_fw->list); + mutex_unlock(&dsp->mutex); + + dma_free_coherent(dsp->dev, sst_fw->size, sst_fw->dma_buf, + sst_fw->dmable_fw_paddr); + kfree(sst_fw); +} +EXPORT_SYMBOL_GPL(sst_fw_free); + +/* free all firmware objects */ +void sst_fw_free_all(struct sst_dsp *dsp) +{ + struct sst_fw *sst_fw, *t; + + mutex_lock(&dsp->mutex); + list_for_each_entry_safe(sst_fw, t, &dsp->fw_list, list) { + + list_del(&sst_fw->list); + dma_free_coherent(dsp->dev, sst_fw->size, sst_fw->dma_buf, + sst_fw->dmable_fw_paddr); + kfree(sst_fw); + } + mutex_unlock(&dsp->mutex); +} +EXPORT_SYMBOL_GPL(sst_fw_free_all); + +/* create a new SST generic module from FW template */ +struct sst_module *sst_module_new(struct sst_fw *sst_fw, + struct sst_module_template *template, void *private) +{ + struct sst_dsp *dsp = sst_fw->dsp; + struct sst_module *sst_module; + + sst_module = kzalloc(sizeof(*sst_module), GFP_KERNEL); + if (sst_module == NULL) + return NULL; + + sst_module->id = template->id; + sst_module->dsp = dsp; + sst_module->sst_fw = sst_fw; + + memcpy(&sst_module->s, &template->s, sizeof(struct sst_module_data)); + memcpy(&sst_module->p, &template->p, sizeof(struct sst_module_data)); + + INIT_LIST_HEAD(&sst_module->block_list); + + mutex_lock(&dsp->mutex); + list_add(&sst_module->list, &dsp->module_list); + mutex_unlock(&dsp->mutex); + + return sst_module; +} +EXPORT_SYMBOL_GPL(sst_module_new); + +/* free firmware module and remove from available list */ +void sst_module_free(struct sst_module *sst_module) +{ + struct sst_dsp *dsp = sst_module->dsp; + + mutex_lock(&dsp->mutex); + list_del(&sst_module->list); + mutex_unlock(&dsp->mutex); + + kfree(sst_module); +} +EXPORT_SYMBOL_GPL(sst_module_free); + +static struct sst_mem_block *find_block(struct sst_dsp *dsp, int type, + u32 offset) +{ + struct sst_mem_block *block; + + list_for_each_entry(block, &dsp->free_block_list, list) { + if (block->type == type && block->offset == offset) + return block; + } + + return NULL; +} + +static int block_alloc_contiguous(struct sst_module *module, + struct sst_module_data *data, u32 offset, int size) +{ + struct list_head tmp = LIST_HEAD_INIT(tmp); + struct sst_dsp *dsp = module->dsp; + struct sst_mem_block *block; + + while (size > 0) { + block = find_block(dsp, data->type, offset); + if (!block) { + list_splice(&tmp, &dsp->free_block_list); + return -ENOMEM; + } + + list_move_tail(&block->list, &tmp); + offset += block->size; + size -= block->size; + } + + list_splice(&tmp, &dsp->used_block_list); + return 0; +} + +/* allocate free DSP blocks for module data - callers hold locks */ +static int block_alloc(struct sst_module *module, + struct sst_module_data *data) +{ + struct sst_dsp *dsp = module->dsp; + struct sst_mem_block *block, *tmp; + int ret = 0; + + if (data->size == 0) + return 0; + + /* find first free whole blocks that can hold module */ + list_for_each_entry_safe(block, tmp, &dsp->free_block_list, list) { + + /* ignore blocks with wrong type */ + if (block->type != data->type) + continue; + + if (data->size > block->size) + continue; + + data->offset = block->offset; + block->data_type = data->data_type; + block->bytes_used = data->size % block->size; + list_add(&block->module_list, &module->block_list); + list_move(&block->list, &dsp->used_block_list); + dev_dbg(dsp->dev, " *module %d added block %d:%d\n", + module->id, block->type, block->index); + return 0; + } + + /* then find free multiple blocks that can hold module */ + list_for_each_entry_safe(block, tmp, &dsp->free_block_list, list) { + + /* ignore blocks with wrong type */ + if (block->type != data->type) + continue; + + /* do we span > 1 blocks */ + if (data->size > block->size) { + ret = block_alloc_contiguous(module, data, + block->offset + block->size, + data->size - block->size); + if (ret == 0) + return ret; + } + } + + /* not enough free block space */ + return -ENOMEM; +} + +/* remove module from memory - callers hold locks */ +static void block_module_remove(struct sst_module *module) +{ + struct sst_mem_block *block, *tmp; + struct sst_dsp *dsp = module->dsp; + int err; + + /* disable each block */ + list_for_each_entry(block, &module->block_list, module_list) { + + if (block->ops && block->ops->disable) { + err = block->ops->disable(block); + if (err < 0) + dev_err(dsp->dev, + "error: cant disable block %d:%d\n", + block->type, block->index); + } + } + + /* mark each block as free */ + list_for_each_entry_safe(block, tmp, &module->block_list, module_list) { + list_del(&block->module_list); + list_move(&block->list, &dsp->free_block_list); + } +} + +/* prepare the memory block to receive data from host - callers hold locks */ +static int block_module_prepare(struct sst_module *module) +{ + struct sst_mem_block *block; + int ret = 0; + + /* enable each block so that's it'e ready for module P/S data */ + list_for_each_entry(block, &module->block_list, module_list) { + + if (block->ops && block->ops->enable) { + ret = block->ops->enable(block); + if (ret < 0) { + dev_err(module->dsp->dev, + "error: cant disable block %d:%d\n", + block->type, block->index); + goto err; + } + } + } + return ret; + +err: + list_for_each_entry(block, &module->block_list, module_list) { + if (block->ops && block->ops->disable) + block->ops->disable(block); + } + return ret; +} + +/* allocate memory blocks for static module addresses - callers hold locks */ +static int block_alloc_fixed(struct sst_module *module, + struct sst_module_data *data) +{ + struct sst_dsp *dsp = module->dsp; + struct sst_mem_block *block, *tmp; + u32 end = data->offset + data->size, block_end; + int err; + + /* only IRAM/DRAM blocks are managed */ + if (data->type != SST_MEM_IRAM && data->type != SST_MEM_DRAM) + return 0; + + /* are blocks already attached to this module */ + list_for_each_entry_safe(block, tmp, &module->block_list, module_list) { + + /* force compacting mem blocks of the same data_type */ + if (block->data_type != data->data_type) + continue; + + block_end = block->offset + block->size; + + /* find block that holds section */ + if (data->offset >= block->offset && end < block_end) + return 0; + + /* does block span more than 1 section */ + if (data->offset >= block->offset && data->offset < block_end) { + + err = block_alloc_contiguous(module, data, + block->offset + block->size, + data->size - block->size + data->offset - block->offset); + if (err < 0) + return -ENOMEM; + + /* module already owns blocks */ + return 0; + } + } + + /* find first free blocks that can hold section in free list */ + list_for_each_entry_safe(block, tmp, &dsp->free_block_list, list) { + block_end = block->offset + block->size; + + /* find block that holds section */ + if (data->offset >= block->offset && end < block_end) { + + /* add block */ + block->data_type = data->data_type; + list_move(&block->list, &dsp->used_block_list); + list_add(&block->module_list, &module->block_list); + return 0; + } + + /* does block span more than 1 section */ + if (data->offset >= block->offset && data->offset < block_end) { + + err = block_alloc_contiguous(module, data, + block->offset + block->size, + data->size - block->size); + if (err < 0) + return -ENOMEM; + + /* add block */ + block->data_type = data->data_type; + list_move(&block->list, &dsp->used_block_list); + list_add(&block->module_list, &module->block_list); + return 0; + } + + } + + return -ENOMEM; +} + +/* Load fixed module data into DSP memory blocks */ +int sst_module_insert_fixed_block(struct sst_module *module, + struct sst_module_data *data) +{ + struct sst_dsp *dsp = module->dsp; + int ret; + + mutex_lock(&dsp->mutex); + + /* alloc blocks that includes this section */ + ret = block_alloc_fixed(module, data); + if (ret < 0) { + dev_err(dsp->dev, + "error: no free blocks for section at offset 0x%x size 0x%x\n", + data->offset, data->size); + mutex_unlock(&dsp->mutex); + return -ENOMEM; + } + + /* prepare DSP blocks for module copy */ + ret = block_module_prepare(module); + if (ret < 0) { + dev_err(dsp->dev, "error: fw module prepare failed\n"); + goto err; + } + + /* copy partial module data to blocks */ + sst_memcpy32(dsp->addr.lpe + data->offset, data->data, data->size); + + mutex_unlock(&dsp->mutex); + return ret; + +err: + block_module_remove(module); + mutex_unlock(&dsp->mutex); + return ret; +} +EXPORT_SYMBOL_GPL(sst_module_insert_fixed_block); + +/* Unload entire module from DSP memory */ +int sst_block_module_remove(struct sst_module *module) +{ + struct sst_dsp *dsp = module->dsp; + + mutex_lock(&dsp->mutex); + block_module_remove(module); + mutex_unlock(&dsp->mutex); + return 0; +} +EXPORT_SYMBOL_GPL(sst_block_module_remove); + +/* register a DSP memory block for use with FW based modules */ +struct sst_mem_block *sst_mem_block_register(struct sst_dsp *dsp, u32 offset, + u32 size, enum sst_mem_type type, struct sst_block_ops *ops, u32 index, + void *private) +{ + struct sst_mem_block *block; + + block = kzalloc(sizeof(*block), GFP_KERNEL); + if (block == NULL) + return NULL; + + block->offset = offset; + block->size = size; + block->index = index; + block->type = type; + block->dsp = dsp; + block->private = private; + block->ops = ops; + + mutex_lock(&dsp->mutex); + list_add(&block->list, &dsp->free_block_list); + mutex_unlock(&dsp->mutex); + + return block; +} +EXPORT_SYMBOL_GPL(sst_mem_block_register); + +/* unregister all DSP memory blocks */ +void sst_mem_block_unregister_all(struct sst_dsp *dsp) +{ + struct sst_mem_block *block, *tmp; + + mutex_lock(&dsp->mutex); + + /* unregister used blocks */ + list_for_each_entry_safe(block, tmp, &dsp->used_block_list, list) { + list_del(&block->list); + kfree(block); + } + + /* unregister free blocks */ + list_for_each_entry_safe(block, tmp, &dsp->free_block_list, list) { + list_del(&block->list); + kfree(block); + } + + mutex_unlock(&dsp->mutex); +} +EXPORT_SYMBOL_GPL(sst_mem_block_unregister_all); + +/* allocate scratch buffer blocks */ +struct sst_module *sst_mem_block_alloc_scratch(struct sst_dsp *dsp) +{ + struct sst_module *sst_module, *scratch; + struct sst_mem_block *block, *tmp; + u32 block_size; + int ret = 0; + + scratch = kzalloc(sizeof(struct sst_module), GFP_KERNEL); + if (scratch == NULL) + return NULL; + + mutex_lock(&dsp->mutex); + + /* calculate required scratch size */ + list_for_each_entry(sst_module, &dsp->module_list, list) { + if (scratch->s.size > sst_module->s.size) + scratch->s.size = scratch->s.size; + else + scratch->s.size = sst_module->s.size; + } + + dev_dbg(dsp->dev, "scratch buffer required is %d bytes\n", + scratch->s.size); + + /* init scratch module */ + scratch->dsp = dsp; + scratch->s.type = SST_MEM_DRAM; + scratch->s.data_type = SST_DATA_S; + INIT_LIST_HEAD(&scratch->block_list); + + /* check free blocks before looking at used blocks for space */ + if (!list_empty(&dsp->free_block_list)) + block = list_first_entry(&dsp->free_block_list, + struct sst_mem_block, list); + else + block = list_first_entry(&dsp->used_block_list, + struct sst_mem_block, list); + block_size = block->size; + + /* allocate blocks for module scratch buffers */ + dev_dbg(dsp->dev, "allocating scratch blocks\n"); + ret = block_alloc(scratch, &scratch->s); + if (ret < 0) { + dev_err(dsp->dev, "error: can't alloc scratch blocks\n"); + goto err; + } + + /* assign the same offset of scratch to each module */ + list_for_each_entry(sst_module, &dsp->module_list, list) + sst_module->s.offset = scratch->s.offset; + + mutex_unlock(&dsp->mutex); + return scratch; + +err: + list_for_each_entry_safe(block, tmp, &scratch->block_list, module_list) + list_del(&block->module_list); + mutex_unlock(&dsp->mutex); + return NULL; +} +EXPORT_SYMBOL_GPL(sst_mem_block_alloc_scratch); + +/* free all scratch blocks */ +void sst_mem_block_free_scratch(struct sst_dsp *dsp, + struct sst_module *scratch) +{ + struct sst_mem_block *block, *tmp; + + mutex_lock(&dsp->mutex); + + list_for_each_entry_safe(block, tmp, &scratch->block_list, module_list) + list_del(&block->module_list); + + mutex_unlock(&dsp->mutex); +} +EXPORT_SYMBOL_GPL(sst_mem_block_free_scratch); + +/* get a module from it's unique ID */ +struct sst_module *sst_module_get_from_id(struct sst_dsp *dsp, u32 id) +{ + struct sst_module *module; + + mutex_lock(&dsp->mutex); + + list_for_each_entry(module, &dsp->module_list, list) { + if (module->id == id) { + mutex_unlock(&dsp->mutex); + return module; + } + } + + mutex_unlock(&dsp->mutex); + return NULL; +} +EXPORT_SYMBOL_GPL(sst_module_get_from_id); diff --git a/sound/soc/intel/sst-haswell-dsp.c b/sound/soc/intel/sst-haswell-dsp.c new file mode 100644 index 00000000000..f5ebf36af88 --- /dev/null +++ b/sound/soc/intel/sst-haswell-dsp.c @@ -0,0 +1,517 @@ +/* + * Intel Haswell SST DSP driver + * + * Copyright (C) 2013, Intel Corporation. All rights reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License version + * 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +#include <linux/delay.h> +#include <linux/fs.h> +#include <linux/slab.h> +#include <linux/device.h> +#include <linux/sched.h> +#include <linux/export.h> +#include <linux/interrupt.h> +#include <linux/module.h> +#include <linux/dma-mapping.h> +#include <linux/platform_device.h> +#include <linux/pci.h> +#include <linux/firmware.h> +#include <linux/pm_runtime.h> + +#include <linux/acpi.h> +#include <acpi/acpi_bus.h> + +#include "sst-dsp.h" +#include "sst-dsp-priv.h" +#include "sst-haswell-ipc.h" + +#include <trace/events/hswadsp.h> + +#define SST_HSW_FW_SIGNATURE_SIZE 4 +#define SST_HSW_FW_SIGN "$SST" +#define SST_HSW_FW_LIB_SIGN "$LIB" + +#define SST_WPT_SHIM_OFFSET 0xFB000 +#define SST_LP_SHIM_OFFSET 0xE7000 +#define SST_WPT_IRAM_OFFSET 0xA0000 +#define SST_LP_IRAM_OFFSET 0x80000 + +#define SST_SHIM_PM_REG 0x84 + +#define SST_HSW_IRAM 1 +#define SST_HSW_DRAM 2 +#define SST_HSW_REGS 3 + +struct dma_block_info { + __le32 type; /* IRAM/DRAM */ + __le32 size; /* Bytes */ + __le32 ram_offset; /* Offset in I/DRAM */ + __le32 rsvd; /* Reserved field */ +} __attribute__((packed)); + +struct fw_module_info { + __le32 persistent_size; + __le32 scratch_size; +} __attribute__((packed)); + +struct fw_header { + unsigned char signature[SST_HSW_FW_SIGNATURE_SIZE]; /* FW signature */ + __le32 file_size; /* size of fw minus this header */ + __le32 modules; /* # of modules */ + __le32 file_format; /* version of header format */ + __le32 reserved[4]; +} __attribute__((packed)); + +struct fw_module_header { + unsigned char signature[SST_HSW_FW_SIGNATURE_SIZE]; /* module signature */ + __le32 mod_size; /* size of module */ + __le32 blocks; /* # of blocks */ + __le16 padding; + __le16 type; /* codec type, pp lib */ + __le32 entry_point; + struct fw_module_info info; +} __attribute__((packed)); + +static void hsw_free(struct sst_dsp *sst); + +static int hsw_parse_module(struct sst_dsp *dsp, struct sst_fw *fw, + struct fw_module_header *module) +{ + struct dma_block_info *block; + struct sst_module *mod; + struct sst_module_data block_data; + struct sst_module_template template; + int count; + void __iomem *ram; + + /* TODO: allowed module types need to be configurable */ + if (module->type != SST_HSW_MODULE_BASE_FW + && module->type != SST_HSW_MODULE_PCM_SYSTEM + && module->type != SST_HSW_MODULE_PCM + && module->type != SST_HSW_MODULE_PCM_REFERENCE + && module->type != SST_HSW_MODULE_PCM_CAPTURE + && module->type != SST_HSW_MODULE_LPAL) + return 0; + + dev_dbg(dsp->dev, "new module sign 0x%s size 0x%x blocks 0x%x type 0x%x\n", + module->signature, module->mod_size, + module->blocks, module->type); + dev_dbg(dsp->dev, " entrypoint 0x%x\n", module->entry_point); + dev_dbg(dsp->dev, " persistent 0x%x scratch 0x%x\n", + module->info.persistent_size, module->info.scratch_size); + + memset(&template, 0, sizeof(template)); + template.id = module->type; + template.entry = module->entry_point; + template.p.size = module->info.persistent_size; + template.p.type = SST_MEM_DRAM; + template.p.data_type = SST_DATA_P; + template.s.size = module->info.scratch_size; + template.s.type = SST_MEM_DRAM; + template.s.data_type = SST_DATA_S; + + mod = sst_module_new(fw, &template, NULL); + if (mod == NULL) + return -ENOMEM; + + block = (void *)module + sizeof(*module); + + for (count = 0; count < module->blocks; count++) { + + if (block->size <= 0) { + dev_err(dsp->dev, + "error: block %d size invalid\n", count); + sst_module_free(mod); + return -EINVAL; + } + + switch (block->type) { + case SST_HSW_IRAM: + ram = dsp->addr.lpe; + block_data.offset = + block->ram_offset + dsp->addr.iram_offset; + block_data.type = SST_MEM_IRAM; + break; + case SST_HSW_DRAM: + ram = dsp->addr.lpe; + block_data.offset = block->ram_offset; + block_data.type = SST_MEM_DRAM; + break; + default: + dev_err(dsp->dev, "error: bad type 0x%x for block 0x%x\n", + block->type, count); + sst_module_free(mod); + return -EINVAL; + } + + block_data.size = block->size; + block_data.data_type = SST_DATA_M; + block_data.data = (void *)block + sizeof(*block); + block_data.data_offset = block_data.data - fw->dma_buf; + + dev_dbg(dsp->dev, "copy firmware block %d type 0x%x " + "size 0x%x ==> ram %p offset 0x%x\n", + count, block->type, block->size, ram, + block->ram_offset); + + sst_module_insert_fixed_block(mod, &block_data); + + block = (void *)block + sizeof(*block) + block->size; + } + return 0; +} + +static int hsw_parse_fw_image(struct sst_fw *sst_fw) +{ + struct fw_header *header; + struct sst_module *scratch; + struct fw_module_header *module; + struct sst_dsp *dsp = sst_fw->dsp; + struct sst_hsw *hsw = sst_fw->private; + int ret, count; + + /* Read the header information from the data pointer */ + header = (struct fw_header *)sst_fw->dma_buf; + + /* verify FW */ + if ((strncmp(header->signature, SST_HSW_FW_SIGN, 4) != 0) || + (sst_fw->size != header->file_size + sizeof(*header))) { + dev_err(dsp->dev, "error: invalid fw sign/filesize mismatch\n"); + return -EINVAL; + } + + dev_dbg(dsp->dev, "header size=0x%x modules=0x%x fmt=0x%x size=%zu\n", + header->file_size, header->modules, + header->file_format, sizeof(*header)); + + /* parse each module */ + module = (void *)sst_fw->dma_buf + sizeof(*header); + for (count = 0; count < header->modules; count++) { + + /* module */ + ret = hsw_parse_module(dsp, sst_fw, module); + if (ret < 0) { + dev_err(dsp->dev, "error: invalid module %d\n", count); + return ret; + } + module = (void *)module + sizeof(*module) + module->mod_size; + } + + /* allocate persistent/scratch mem regions */ + scratch = sst_mem_block_alloc_scratch(dsp); + if (scratch == NULL) + return -ENOMEM; + + sst_hsw_set_scratch_module(hsw, scratch); + + return 0; +} + +static irqreturn_t hsw_irq(int irq, void *context) +{ + struct sst_dsp *sst = (struct sst_dsp *) context; + u32 isr; + int ret = IRQ_NONE; + + spin_lock(&sst->spinlock); + + /* Interrupt arrived, check src */ + isr = sst_dsp_shim_read_unlocked(sst, SST_ISRX); + if (isr & SST_ISRX_DONE) { + trace_sst_irq_done(isr, + sst_dsp_shim_read_unlocked(sst, SST_IMRX)); + + /* Mask Done interrupt before return */ + sst_dsp_shim_update_bits_unlocked(sst, SST_IMRX, + SST_IMRX_DONE, SST_IMRX_DONE); + ret = IRQ_WAKE_THREAD; + } + + if (isr & SST_ISRX_BUSY) { + trace_sst_irq_busy(isr, + sst_dsp_shim_read_unlocked(sst, SST_IMRX)); + + /* Mask Busy interrupt before return */ + sst_dsp_shim_update_bits_unlocked(sst, SST_IMRX, + SST_IMRX_BUSY, SST_IMRX_BUSY); + ret = IRQ_WAKE_THREAD; + } + + spin_unlock(&sst->spinlock); + return ret; +} + +static void hsw_boot(struct sst_dsp *sst) +{ + /* select SSP1 19.2MHz base clock, SSP clock 0, turn off Low Power Clock */ + sst_dsp_shim_update_bits_unlocked(sst, SST_CSR, + SST_CSR_S1IOCS | SST_CSR_SBCS1 | SST_CSR_LPCS, 0x0); + + /* stall DSP core, set clk to 192/96Mhz */ + sst_dsp_shim_update_bits_unlocked(sst, + SST_CSR, SST_CSR_STALL | SST_CSR_DCS_MASK, + SST_CSR_STALL | SST_CSR_DCS(4)); + + /* Set 24MHz MCLK, prevent local clock gating, enable SSP0 clock */ + sst_dsp_shim_update_bits_unlocked(sst, SST_CLKCTL, + SST_CLKCTL_MASK | SST_CLKCTL_DCPLCG | SST_CLKCTL_SCOE0, + SST_CLKCTL_MASK | SST_CLKCTL_DCPLCG | SST_CLKCTL_SCOE0); + + /* disable DMA finish function for SSP0 & SSP1 */ + sst_dsp_shim_update_bits_unlocked(sst, SST_CSR2, SST_CSR2_SDFD_SSP1, + SST_CSR2_SDFD_SSP1); + + /* enable DMA engine 0,1 all channels to access host memory */ + sst_dsp_shim_update_bits_unlocked(sst, SST_HDMC, + SST_HDMC_HDDA1(0xff) | SST_HDMC_HDDA0(0xff), + SST_HDMC_HDDA1(0xff) | SST_HDMC_HDDA0(0xff)); + + /* disable all clock gating */ + writel(0x0, sst->addr.pci_cfg + SST_VDRTCTL2); + + /* set DSP to RUN */ + sst_dsp_shim_update_bits_unlocked(sst, SST_CSR, SST_CSR_STALL, 0x0); +} + +static void hsw_reset(struct sst_dsp *sst) +{ + /* put DSP into reset and stall */ + sst_dsp_shim_update_bits_unlocked(sst, SST_CSR, + SST_CSR_RST | SST_CSR_STALL, SST_CSR_RST | SST_CSR_STALL); + + /* keep in reset for 10ms */ + mdelay(10); + + /* take DSP out of reset and keep stalled for FW loading */ + sst_dsp_shim_update_bits_unlocked(sst, SST_CSR, + SST_CSR_RST | SST_CSR_STALL, SST_CSR_STALL); +} + +struct sst_adsp_memregion { + u32 start; + u32 end; + int blocks; + enum sst_mem_type type; +}; + +/* lynx point ADSP mem regions */ +static const struct sst_adsp_memregion lp_region[] = { + {0x00000, 0x40000, 8, SST_MEM_DRAM}, /* D-SRAM0 - 8 * 32kB */ + {0x40000, 0x80000, 8, SST_MEM_DRAM}, /* D-SRAM1 - 8 * 32kB */ + {0x80000, 0xE0000, 12, SST_MEM_IRAM}, /* I-SRAM - 12 * 32kB */ +}; + +/* wild cat point ADSP mem regions */ +static const struct sst_adsp_memregion wpt_region[] = { + {0x00000, 0x40000, 8, SST_MEM_DRAM}, /* D-SRAM0 - 8 * 32kB */ + {0x40000, 0x80000, 8, SST_MEM_DRAM}, /* D-SRAM1 - 8 * 32kB */ + {0x80000, 0xA0000, 4, SST_MEM_DRAM}, /* D-SRAM2 - 4 * 32kB */ + {0xA0000, 0xF0000, 10, SST_MEM_IRAM}, /* I-SRAM - 10 * 32kB */ +}; + +static int hsw_acpi_resource_map(struct sst_dsp *sst, struct sst_pdata *pdata) +{ + /* ADSP DRAM & IRAM */ + sst->addr.lpe_base = pdata->lpe_base; + sst->addr.lpe = ioremap(pdata->lpe_base, pdata->lpe_size); + if (!sst->addr.lpe) + return -ENODEV; + + /* ADSP PCI MMIO config space */ + sst->addr.pci_cfg = ioremap(pdata->pcicfg_base, pdata->pcicfg_size); + if (!sst->addr.pci_cfg) { + iounmap(sst->addr.lpe); + return -ENODEV; + } + + /* SST Shim */ + sst->addr.shim = sst->addr.lpe + sst->addr.shim_offset; + return 0; +} + +static u32 hsw_block_get_bit(struct sst_mem_block *block) +{ + u32 bit = 0, shift = 0; + + switch (block->type) { + case SST_MEM_DRAM: + shift = 16; + break; + case SST_MEM_IRAM: + shift = 6; + break; + default: + return 0; + } + + bit = 1 << (block->index + shift); + + return bit; +} + +/* enable 32kB memory block - locks held by caller */ +static int hsw_block_enable(struct sst_mem_block *block) +{ + struct sst_dsp *sst = block->dsp; + u32 bit, val; + + if (block->users++ > 0) + return 0; + + dev_dbg(block->dsp->dev, " enabled block %d:%d at offset 0x%x\n", + block->type, block->index, block->offset); + + val = readl(sst->addr.pci_cfg + SST_VDRTCTL0); + bit = hsw_block_get_bit(block); + writel(val & ~bit, sst->addr.pci_cfg + SST_VDRTCTL0); + + /* wait 18 DSP clock ticks */ + udelay(10); + + return 0; +} + +/* disable 32kB memory block - locks held by caller */ +static int hsw_block_disable(struct sst_mem_block *block) +{ + struct sst_dsp *sst = block->dsp; + u32 bit, val; + + if (--block->users > 0) + return 0; + + dev_dbg(block->dsp->dev, " disabled block %d:%d at offset 0x%x\n", + block->type, block->index, block->offset); + + val = readl(sst->addr.pci_cfg + SST_VDRTCTL0); + bit = hsw_block_get_bit(block); + writel(val | bit, sst->addr.pci_cfg + SST_VDRTCTL0); + + return 0; +} + +static struct sst_block_ops sst_hsw_ops = { + .enable = hsw_block_enable, + .disable = hsw_block_disable, +}; + +static int hsw_enable_shim(struct sst_dsp *sst) +{ + int tries = 10; + u32 reg; + + /* enable shim */ + reg = readl(sst->addr.pci_cfg + SST_SHIM_PM_REG); + writel(reg & ~0x3, sst->addr.pci_cfg + SST_SHIM_PM_REG); + + /* check that ADSP shim is enabled */ + while (tries--) { + reg = sst_dsp_shim_read_unlocked(sst, SST_CSR); + if (reg != 0xffffffff) + return 0; + + msleep(1); + } + + return -ENODEV; +} + +static int hsw_init(struct sst_dsp *sst, struct sst_pdata *pdata) +{ + const struct sst_adsp_memregion *region; + struct device *dev; + int ret = -ENODEV, i, j, region_count; + u32 offset, size; + + dev = sst->dev; + + switch (sst->id) { + case SST_DEV_ID_LYNX_POINT: + region = lp_region; + region_count = ARRAY_SIZE(lp_region); + sst->addr.iram_offset = SST_LP_IRAM_OFFSET; + sst->addr.shim_offset = SST_LP_SHIM_OFFSET; + break; + case SST_DEV_ID_WILDCAT_POINT: + region = wpt_region; + region_count = ARRAY_SIZE(wpt_region); + sst->addr.iram_offset = SST_WPT_IRAM_OFFSET; + sst->addr.shim_offset = SST_WPT_SHIM_OFFSET; + break; + default: + dev_err(dev, "error: failed to get mem resources\n"); + return ret; + } + + ret = hsw_acpi_resource_map(sst, pdata); + if (ret < 0) { + dev_err(dev, "error: failed to map resources\n"); + return ret; + } + + /* enable the DSP SHIM */ + ret = hsw_enable_shim(sst); + if (ret < 0) { + dev_err(dev, "error: failed to set DSP D0 and reset SHIM\n"); + return ret; + } + + ret = dma_coerce_mask_and_coherent(dev, DMA_BIT_MASK(32)); + if (ret) + return ret; + + /* Enable Interrupt from both sides */ + sst_dsp_shim_update_bits_unlocked(sst, SST_IMRX, 0x3, 0x0); + sst_dsp_shim_update_bits_unlocked(sst, SST_IMRD, + (0x3 | 0x1 << 16 | 0x3 << 21), 0x0); + + /* register DSP memory blocks - ideally we should get this from ACPI */ + for (i = 0; i < region_count; i++) { + offset = region[i].start; + size = (region[i].end - region[i].start) / region[i].blocks; + + /* register individual memory blocks */ + for (j = 0; j < region[i].blocks; j++) { + sst_mem_block_register(sst, offset, size, + region[i].type, &sst_hsw_ops, j, sst); + offset += size; + } + } + + /* set default power gating mask */ + writel(0x0, sst->addr.pci_cfg + SST_VDRTCTL0); + + return 0; +} + +static void hsw_free(struct sst_dsp *sst) +{ + sst_mem_block_unregister_all(sst); + iounmap(sst->addr.lpe); + iounmap(sst->addr.pci_cfg); +} + +struct sst_ops haswell_ops = { + .reset = hsw_reset, + .boot = hsw_boot, + .write = sst_shim32_write, + .read = sst_shim32_read, + .write64 = sst_shim32_write64, + .read64 = sst_shim32_read64, + .ram_read = sst_memcpy_fromio_32, + .ram_write = sst_memcpy_toio_32, + .irq_handler = hsw_irq, + .init = hsw_init, + .free = hsw_free, + .parse_fw = hsw_parse_fw_image, +}; diff --git a/sound/soc/intel/sst-haswell-ipc.c b/sound/soc/intel/sst-haswell-ipc.c new file mode 100644 index 00000000000..f46bb4ddde6 --- /dev/null +++ b/sound/soc/intel/sst-haswell-ipc.c @@ -0,0 +1,1785 @@ +/* + * Intel SST Haswell/Broadwell IPC Support + * + * Copyright (C) 2013, Intel Corporation. All rights reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License version + * 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +#include <linux/types.h> +#include <linux/kernel.h> +#include <linux/list.h> +#include <linux/device.h> +#include <linux/wait.h> +#include <linux/spinlock.h> +#include <linux/workqueue.h> +#include <linux/export.h> +#include <linux/slab.h> +#include <linux/delay.h> +#include <linux/sched.h> +#include <linux/list.h> +#include <linux/platform_device.h> +#include <linux/kthread.h> +#include <linux/firmware.h> +#include <linux/dma-mapping.h> +#include <linux/debugfs.h> + +#include "sst-haswell-ipc.h" +#include "sst-dsp.h" +#include "sst-dsp-priv.h" + +/* Global Message - Generic */ +#define IPC_GLB_TYPE_SHIFT 24 +#define IPC_GLB_TYPE_MASK (0x1f << IPC_GLB_TYPE_SHIFT) +#define IPC_GLB_TYPE(x) (x << IPC_GLB_TYPE_SHIFT) + +/* Global Message - Reply */ +#define IPC_GLB_REPLY_SHIFT 0 +#define IPC_GLB_REPLY_MASK (0x1f << IPC_GLB_REPLY_SHIFT) +#define IPC_GLB_REPLY_TYPE(x) (x << IPC_GLB_REPLY_TYPE_SHIFT) + +/* Stream Message - Generic */ +#define IPC_STR_TYPE_SHIFT 20 +#define IPC_STR_TYPE_MASK (0xf << IPC_STR_TYPE_SHIFT) +#define IPC_STR_TYPE(x) (x << IPC_STR_TYPE_SHIFT) +#define IPC_STR_ID_SHIFT 16 +#define IPC_STR_ID_MASK (0xf << IPC_STR_ID_SHIFT) +#define IPC_STR_ID(x) (x << IPC_STR_ID_SHIFT) + +/* Stream Message - Reply */ +#define IPC_STR_REPLY_SHIFT 0 +#define IPC_STR_REPLY_MASK (0x1f << IPC_STR_REPLY_SHIFT) + +/* Stream Stage Message - Generic */ +#define IPC_STG_TYPE_SHIFT 12 +#define IPC_STG_TYPE_MASK (0xf << IPC_STG_TYPE_SHIFT) +#define IPC_STG_TYPE(x) (x << IPC_STG_TYPE_SHIFT) +#define IPC_STG_ID_SHIFT 10 +#define IPC_STG_ID_MASK (0x3 << IPC_STG_ID_SHIFT) +#define IPC_STG_ID(x) (x << IPC_STG_ID_SHIFT) + +/* Stream Stage Message - Reply */ +#define IPC_STG_REPLY_SHIFT 0 +#define IPC_STG_REPLY_MASK (0x1f << IPC_STG_REPLY_SHIFT) + +/* Debug Log Message - Generic */ +#define IPC_LOG_OP_SHIFT 20 +#define IPC_LOG_OP_MASK (0xf << IPC_LOG_OP_SHIFT) +#define IPC_LOG_OP_TYPE(x) (x << IPC_LOG_OP_SHIFT) +#define IPC_LOG_ID_SHIFT 16 +#define IPC_LOG_ID_MASK (0xf << IPC_LOG_ID_SHIFT) +#define IPC_LOG_ID(x) (x << IPC_LOG_ID_SHIFT) + +/* IPC message timeout (msecs) */ +#define IPC_TIMEOUT_MSECS 300 +#define IPC_BOOT_MSECS 200 +#define IPC_MSG_WAIT 0 +#define IPC_MSG_NOWAIT 1 + +/* Firmware Ready Message */ +#define IPC_FW_READY (0x1 << 29) +#define IPC_STATUS_MASK (0x3 << 30) + +#define IPC_EMPTY_LIST_SIZE 8 +#define IPC_MAX_STREAMS 4 + +/* Mailbox */ +#define IPC_MAX_MAILBOX_BYTES 256 + +/* Global Message - Types and Replies */ +enum ipc_glb_type { + IPC_GLB_GET_FW_VERSION = 0, /* Retrieves firmware version */ + IPC_GLB_PERFORMANCE_MONITOR = 1, /* Performance monitoring actions */ + IPC_GLB_ALLOCATE_STREAM = 3, /* Request to allocate new stream */ + IPC_GLB_FREE_STREAM = 4, /* Request to free stream */ + IPC_GLB_GET_FW_CAPABILITIES = 5, /* Retrieves firmware capabilities */ + IPC_GLB_STREAM_MESSAGE = 6, /* Message directed to stream or its stages */ + /* Request to store firmware context during D0->D3 transition */ + IPC_GLB_REQUEST_DUMP = 7, + /* Request to restore firmware context during D3->D0 transition */ + IPC_GLB_RESTORE_CONTEXT = 8, + IPC_GLB_GET_DEVICE_FORMATS = 9, /* Set device format */ + IPC_GLB_SET_DEVICE_FORMATS = 10, /* Get device format */ + IPC_GLB_SHORT_REPLY = 11, + IPC_GLB_ENTER_DX_STATE = 12, + IPC_GLB_GET_MIXER_STREAM_INFO = 13, /* Request mixer stream params */ + IPC_GLB_DEBUG_LOG_MESSAGE = 14, /* Message to or from the debug logger. */ + IPC_GLB_REQUEST_TRANSFER = 16, /* < Request Transfer for host */ + IPC_GLB_MAX_IPC_MESSAGE_TYPE = 17, /* Maximum message number */ +}; + +enum ipc_glb_reply { + IPC_GLB_REPLY_SUCCESS = 0, /* The operation was successful. */ + IPC_GLB_REPLY_ERROR_INVALID_PARAM = 1, /* Invalid parameter was passed. */ + IPC_GLB_REPLY_UNKNOWN_MESSAGE_TYPE = 2, /* Uknown message type was resceived. */ + IPC_GLB_REPLY_OUT_OF_RESOURCES = 3, /* No resources to satisfy the request. */ + IPC_GLB_REPLY_BUSY = 4, /* The system or resource is busy. */ + IPC_GLB_REPLY_PENDING = 5, /* The action was scheduled for processing. */ + IPC_GLB_REPLY_FAILURE = 6, /* Critical error happened. */ + IPC_GLB_REPLY_INVALID_REQUEST = 7, /* Request can not be completed. */ + IPC_GLB_REPLY_STAGE_UNINITIALIZED = 8, /* Processing stage was uninitialized. */ + IPC_GLB_REPLY_NOT_FOUND = 9, /* Required resource can not be found. */ + IPC_GLB_REPLY_SOURCE_NOT_STARTED = 10, /* Source was not started. */ +}; + +/* Stream Message - Types */ +enum ipc_str_operation { + IPC_STR_RESET = 0, + IPC_STR_PAUSE = 1, + IPC_STR_RESUME = 2, + IPC_STR_STAGE_MESSAGE = 3, + IPC_STR_NOTIFICATION = 4, + IPC_STR_MAX_MESSAGE +}; + +/* Stream Stage Message Types */ +enum ipc_stg_operation { + IPC_STG_GET_VOLUME = 0, + IPC_STG_SET_VOLUME, + IPC_STG_SET_WRITE_POSITION, + IPC_STG_SET_FX_ENABLE, + IPC_STG_SET_FX_DISABLE, + IPC_STG_SET_FX_GET_PARAM, + IPC_STG_SET_FX_SET_PARAM, + IPC_STG_SET_FX_GET_INFO, + IPC_STG_MUTE_LOOPBACK, + IPC_STG_MAX_MESSAGE +}; + +/* Stream Stage Message Types For Notification*/ +enum ipc_stg_operation_notify { + IPC_POSITION_CHANGED = 0, + IPC_STG_GLITCH, + IPC_STG_MAX_NOTIFY +}; + +enum ipc_glitch_type { + IPC_GLITCH_UNDERRUN = 1, + IPC_GLITCH_DECODER_ERROR, + IPC_GLITCH_DOUBLED_WRITE_POS, + IPC_GLITCH_MAX +}; + +/* Debug Control */ +enum ipc_debug_operation { + IPC_DEBUG_ENABLE_LOG = 0, + IPC_DEBUG_DISABLE_LOG = 1, + IPC_DEBUG_REQUEST_LOG_DUMP = 2, + IPC_DEBUG_NOTIFY_LOG_DUMP = 3, + IPC_DEBUG_MAX_DEBUG_LOG +}; + +/* Firmware Ready */ +struct sst_hsw_ipc_fw_ready { + u32 inbox_offset; + u32 outbox_offset; + u32 inbox_size; + u32 outbox_size; + u32 fw_info_size; + u8 fw_info[1]; +} __attribute__((packed)); + +struct ipc_message { + struct list_head list; + u32 header; + + /* direction wrt host CPU */ + char tx_data[IPC_MAX_MAILBOX_BYTES]; + size_t tx_size; + char rx_data[IPC_MAX_MAILBOX_BYTES]; + size_t rx_size; + + wait_queue_head_t waitq; + bool pending; + bool complete; + bool wait; + int errno; +}; + +struct sst_hsw_stream; +struct sst_hsw; + +/* Stream infomation */ +struct sst_hsw_stream { + /* configuration */ + struct sst_hsw_ipc_stream_alloc_req request; + struct sst_hsw_ipc_stream_alloc_reply reply; + struct sst_hsw_ipc_stream_free_req free_req; + + /* Mixer info */ + u32 mute_volume[SST_HSW_NO_CHANNELS]; + u32 mute[SST_HSW_NO_CHANNELS]; + + /* runtime info */ + struct sst_hsw *hsw; + int host_id; + bool commited; + bool running; + + /* Notification work */ + struct work_struct notify_work; + u32 header; + + /* Position info from DSP */ + struct sst_hsw_ipc_stream_set_position wpos; + struct sst_hsw_ipc_stream_get_position rpos; + struct sst_hsw_ipc_stream_glitch_position glitch; + + /* Volume info */ + struct sst_hsw_ipc_volume_req vol_req; + + /* driver callback */ + u32 (*notify_position)(struct sst_hsw_stream *stream, void *data); + void *pdata; + + struct list_head node; +}; + +/* FW log ring information */ +struct sst_hsw_log_stream { + dma_addr_t dma_addr; + unsigned char *dma_area; + unsigned char *ring_descr; + int pages; + int size; + + /* Notification work */ + struct work_struct notify_work; + wait_queue_head_t readers_wait_q; + struct mutex rw_mutex; + + u32 last_pos; + u32 curr_pos; + u32 reader_pos; + + /* fw log config */ + u32 config[SST_HSW_FW_LOG_CONFIG_DWORDS]; + + struct sst_hsw *hsw; +}; + +/* SST Haswell IPC data */ +struct sst_hsw { + struct device *dev; + struct sst_dsp *dsp; + struct platform_device *pdev_pcm; + + /* FW config */ + struct sst_hsw_ipc_fw_ready fw_ready; + struct sst_hsw_ipc_fw_version version; + struct sst_module *scratch; + bool fw_done; + + /* stream */ + struct list_head stream_list; + + /* global mixer */ + struct sst_hsw_ipc_stream_info_reply mixer_info; + enum sst_hsw_volume_curve curve_type; + u32 curve_duration; + u32 mute[SST_HSW_NO_CHANNELS]; + u32 mute_volume[SST_HSW_NO_CHANNELS]; + + /* DX */ + struct sst_hsw_ipc_dx_reply dx; + + /* boot */ + wait_queue_head_t boot_wait; + bool boot_complete; + bool shutdown; + + /* IPC messaging */ + struct list_head tx_list; + struct list_head rx_list; + struct list_head empty_list; + wait_queue_head_t wait_txq; + struct task_struct *tx_thread; + struct kthread_worker kworker; + struct kthread_work kwork; + bool pending; + struct ipc_message *msg; + + /* FW log stream */ + struct sst_hsw_log_stream log_stream; +}; + +#define CREATE_TRACE_POINTS +#include <trace/events/hswadsp.h> + +static inline u32 msg_get_global_type(u32 msg) +{ + return (msg & IPC_GLB_TYPE_MASK) >> IPC_GLB_TYPE_SHIFT; +} + +static inline u32 msg_get_global_reply(u32 msg) +{ + return (msg & IPC_GLB_REPLY_MASK) >> IPC_GLB_REPLY_SHIFT; +} + +static inline u32 msg_get_stream_type(u32 msg) +{ + return (msg & IPC_STR_TYPE_MASK) >> IPC_STR_TYPE_SHIFT; +} + +static inline u32 msg_get_stage_type(u32 msg) +{ + return (msg & IPC_STG_TYPE_MASK) >> IPC_STG_TYPE_SHIFT; +} + +static inline u32 msg_set_stage_type(u32 msg, u32 type) +{ + return (msg & ~IPC_STG_TYPE_MASK) + + (type << IPC_STG_TYPE_SHIFT); +} + +static inline u32 msg_get_stream_id(u32 msg) +{ + return (msg & IPC_STR_ID_MASK) >> IPC_STR_ID_SHIFT; +} + +static inline u32 msg_get_notify_reason(u32 msg) +{ + return (msg & IPC_STG_TYPE_MASK) >> IPC_STG_TYPE_SHIFT; +} + +u32 create_channel_map(enum sst_hsw_channel_config config) +{ + switch (config) { + case SST_HSW_CHANNEL_CONFIG_MONO: + return (0xFFFFFFF0 | SST_HSW_CHANNEL_CENTER); + case SST_HSW_CHANNEL_CONFIG_STEREO: + return (0xFFFFFF00 | SST_HSW_CHANNEL_LEFT + | (SST_HSW_CHANNEL_RIGHT << 4)); + case SST_HSW_CHANNEL_CONFIG_2_POINT_1: + return (0xFFFFF000 | SST_HSW_CHANNEL_LEFT + | (SST_HSW_CHANNEL_RIGHT << 4) + | (SST_HSW_CHANNEL_LFE << 8 )); + case SST_HSW_CHANNEL_CONFIG_3_POINT_0: + return (0xFFFFF000 | SST_HSW_CHANNEL_LEFT + | (SST_HSW_CHANNEL_CENTER << 4) + | (SST_HSW_CHANNEL_RIGHT << 8)); + case SST_HSW_CHANNEL_CONFIG_3_POINT_1: + return (0xFFFF0000 | SST_HSW_CHANNEL_LEFT + | (SST_HSW_CHANNEL_CENTER << 4) + | (SST_HSW_CHANNEL_RIGHT << 8) + | (SST_HSW_CHANNEL_LFE << 12)); + case SST_HSW_CHANNEL_CONFIG_QUATRO: + return (0xFFFF0000 | SST_HSW_CHANNEL_LEFT + | (SST_HSW_CHANNEL_RIGHT << 4) + | (SST_HSW_CHANNEL_LEFT_SURROUND << 8) + | (SST_HSW_CHANNEL_RIGHT_SURROUND << 12)); + case SST_HSW_CHANNEL_CONFIG_4_POINT_0: + return (0xFFFF0000 | SST_HSW_CHANNEL_LEFT + | (SST_HSW_CHANNEL_CENTER << 4) + | (SST_HSW_CHANNEL_RIGHT << 8) + | (SST_HSW_CHANNEL_CENTER_SURROUND << 12)); + case SST_HSW_CHANNEL_CONFIG_5_POINT_0: + return (0xFFF00000 | SST_HSW_CHANNEL_LEFT + | (SST_HSW_CHANNEL_CENTER << 4) + | (SST_HSW_CHANNEL_RIGHT << 8) + | (SST_HSW_CHANNEL_LEFT_SURROUND << 12) + | (SST_HSW_CHANNEL_RIGHT_SURROUND << 16)); + case SST_HSW_CHANNEL_CONFIG_5_POINT_1: + return (0xFF000000 | SST_HSW_CHANNEL_CENTER + | (SST_HSW_CHANNEL_LEFT << 4) + | (SST_HSW_CHANNEL_RIGHT << 8) + | (SST_HSW_CHANNEL_LEFT_SURROUND << 12) + | (SST_HSW_CHANNEL_RIGHT_SURROUND << 16) + | (SST_HSW_CHANNEL_LFE << 20)); + case SST_HSW_CHANNEL_CONFIG_DUAL_MONO: + return (0xFFFFFF00 | SST_HSW_CHANNEL_LEFT + | (SST_HSW_CHANNEL_LEFT << 4)); + default: + return 0xFFFFFFFF; + } +} + +static struct sst_hsw_stream *get_stream_by_id(struct sst_hsw *hsw, + int stream_id) +{ + struct sst_hsw_stream *stream; + + list_for_each_entry(stream, &hsw->stream_list, node) { + if (stream->reply.stream_hw_id == stream_id) + return stream; + } + + return NULL; +} + +static void ipc_shim_dbg(struct sst_hsw *hsw, const char *text) +{ + struct sst_dsp *sst = hsw->dsp; + u32 isr, ipcd, imrx, ipcx; + + ipcx = sst_dsp_shim_read_unlocked(sst, SST_IPCX); + isr = sst_dsp_shim_read_unlocked(sst, SST_ISRX); + ipcd = sst_dsp_shim_read_unlocked(sst, SST_IPCD); + imrx = sst_dsp_shim_read_unlocked(sst, SST_IMRX); + + dev_err(hsw->dev, "ipc: --%s-- ipcx 0x%8.8x isr 0x%8.8x ipcd 0x%8.8x imrx 0x%8.8x\n", + text, ipcx, isr, ipcd, imrx); +} + +/* locks held by caller */ +static struct ipc_message *msg_get_empty(struct sst_hsw *hsw) +{ + struct ipc_message *msg = NULL; + + if (!list_empty(&hsw->empty_list)) { + msg = list_first_entry(&hsw->empty_list, struct ipc_message, + list); + list_del(&msg->list); + } + + return msg; +} + +static void ipc_tx_msgs(struct kthread_work *work) +{ + struct sst_hsw *hsw = + container_of(work, struct sst_hsw, kwork); + struct ipc_message *msg; + unsigned long flags; + u32 ipcx; + + spin_lock_irqsave(&hsw->dsp->spinlock, flags); + + if (list_empty(&hsw->tx_list) || hsw->pending) { + spin_unlock_irqrestore(&hsw->dsp->spinlock, flags); + return; + } + + /* if the DSP is busy we will TX messages after IRQ */ + ipcx = sst_dsp_shim_read_unlocked(hsw->dsp, SST_IPCX); + if (ipcx & SST_IPCX_BUSY) { + spin_unlock_irqrestore(&hsw->dsp->spinlock, flags); + return; + } + + msg = list_first_entry(&hsw->tx_list, struct ipc_message, list); + + list_move(&msg->list, &hsw->rx_list); + + /* send the message */ + sst_dsp_outbox_write(hsw->dsp, msg->tx_data, msg->tx_size); + sst_dsp_ipc_msg_tx(hsw->dsp, msg->header | SST_IPCX_BUSY); + + spin_unlock_irqrestore(&hsw->dsp->spinlock, flags); +} + +/* locks held by caller */ +static void tx_msg_reply_complete(struct sst_hsw *hsw, struct ipc_message *msg) +{ + msg->complete = true; + trace_ipc_reply("completed", msg->header); + + if (!msg->wait) + list_add_tail(&msg->list, &hsw->empty_list); + else + wake_up(&msg->waitq); +} + +static int tx_wait_done(struct sst_hsw *hsw, struct ipc_message *msg, + void *rx_data) +{ + unsigned long flags; + int ret; + + /* wait for DSP completion (in all cases atm inc pending) */ + ret = wait_event_timeout(msg->waitq, msg->complete, + msecs_to_jiffies(IPC_TIMEOUT_MSECS)); + + spin_lock_irqsave(&hsw->dsp->spinlock, flags); + if (ret == 0) { + ipc_shim_dbg(hsw, "message timeout"); + + trace_ipc_error("error message timeout for", msg->header); + ret = -ETIMEDOUT; + } else { + + /* copy the data returned from DSP */ + if (msg->rx_size) + memcpy(rx_data, msg->rx_data, msg->rx_size); + ret = msg->errno; + } + + list_add_tail(&msg->list, &hsw->empty_list); + spin_unlock_irqrestore(&hsw->dsp->spinlock, flags); + return ret; +} + +static int ipc_tx_message(struct sst_hsw *hsw, u32 header, void *tx_data, + size_t tx_bytes, void *rx_data, size_t rx_bytes, int wait) +{ + struct ipc_message *msg; + unsigned long flags; + + spin_lock_irqsave(&hsw->dsp->spinlock, flags); + + msg = msg_get_empty(hsw); + if (msg == NULL) { + spin_unlock_irqrestore(&hsw->dsp->spinlock, flags); + return -EBUSY; + } + + if (tx_bytes) + memcpy(msg->tx_data, tx_data, tx_bytes); + + msg->header = header; + msg->tx_size = tx_bytes; + msg->rx_size = rx_bytes; + msg->wait = wait; + msg->errno = 0; + msg->pending = false; + msg->complete = false; + + list_add_tail(&msg->list, &hsw->tx_list); + spin_unlock_irqrestore(&hsw->dsp->spinlock, flags); + + queue_kthread_work(&hsw->kworker, &hsw->kwork); + + if (wait) + return tx_wait_done(hsw, msg, rx_data); + else + return 0; +} + +static inline int ipc_tx_message_wait(struct sst_hsw *hsw, u32 header, + void *tx_data, size_t tx_bytes, void *rx_data, size_t rx_bytes) +{ + return ipc_tx_message(hsw, header, tx_data, tx_bytes, rx_data, + rx_bytes, 1); +} + +static inline int ipc_tx_message_nowait(struct sst_hsw *hsw, u32 header, + void *tx_data, size_t tx_bytes) +{ + return ipc_tx_message(hsw, header, tx_data, tx_bytes, NULL, 0, 0); +} + +static void hsw_fw_ready(struct sst_hsw *hsw, u32 header) +{ + struct sst_hsw_ipc_fw_ready fw_ready; + u32 offset; + + offset = (header & 0x1FFFFFFF) << 3; + + dev_dbg(hsw->dev, "ipc: DSP is ready 0x%8.8x offset %d\n", + header, offset); + + /* copy data from the DSP FW ready offset */ + sst_dsp_read(hsw->dsp, &fw_ready, offset, sizeof(fw_ready)); + + sst_dsp_mailbox_init(hsw->dsp, fw_ready.inbox_offset, + fw_ready.inbox_size, fw_ready.outbox_offset, + fw_ready.outbox_size); + + hsw->boot_complete = true; + wake_up(&hsw->boot_wait); + + dev_dbg(hsw->dev, " mailbox upstream 0x%x - size 0x%x\n", + fw_ready.inbox_offset, fw_ready.inbox_size); + dev_dbg(hsw->dev, " mailbox downstream 0x%x - size 0x%x\n", + fw_ready.outbox_offset, fw_ready.outbox_size); +} + +static void hsw_notification_work(struct work_struct *work) +{ + struct sst_hsw_stream *stream = container_of(work, + struct sst_hsw_stream, notify_work); + struct sst_hsw_ipc_stream_glitch_position *glitch = &stream->glitch; + struct sst_hsw_ipc_stream_get_position *pos = &stream->rpos; + struct sst_hsw *hsw = stream->hsw; + u32 reason; + + reason = msg_get_notify_reason(stream->header); + + switch (reason) { + case IPC_STG_GLITCH: + trace_ipc_notification("DSP stream under/overrun", + stream->reply.stream_hw_id); + sst_dsp_inbox_read(hsw->dsp, glitch, sizeof(*glitch)); + + dev_err(hsw->dev, "glitch %d pos 0x%x write pos 0x%x\n", + glitch->glitch_type, glitch->present_pos, + glitch->write_pos); + break; + + case IPC_POSITION_CHANGED: + trace_ipc_notification("DSP stream position changed for", + stream->reply.stream_hw_id); + sst_dsp_inbox_read(hsw->dsp, pos, sizeof(pos)); + + if (stream->notify_position) + stream->notify_position(stream, stream->pdata); + + break; + default: + dev_err(hsw->dev, "error: unknown notification 0x%x\n", + stream->header); + break; + } + + /* tell DSP that notification has been handled */ + sst_dsp_shim_update_bits_unlocked(hsw->dsp, SST_IPCD, + SST_IPCD_BUSY | SST_IPCD_DONE, SST_IPCD_DONE); + + /* unmask busy interrupt */ + sst_dsp_shim_update_bits_unlocked(hsw->dsp, SST_IMRX, SST_IMRX_BUSY, 0); +} + +static struct ipc_message *reply_find_msg(struct sst_hsw *hsw, u32 header) +{ + struct ipc_message *msg; + + /* clear reply bits & status bits */ + header &= ~(IPC_STATUS_MASK | IPC_GLB_REPLY_MASK); + + if (list_empty(&hsw->rx_list)) { + dev_err(hsw->dev, "error: rx list empty but received 0x%x\n", + header); + return NULL; + } + + list_for_each_entry(msg, &hsw->rx_list, list) { + if (msg->header == header) + return msg; + } + + return NULL; +} + +static void hsw_stream_update(struct sst_hsw *hsw, struct ipc_message *msg) +{ + struct sst_hsw_stream *stream; + u32 header = msg->header & ~(IPC_STATUS_MASK | IPC_GLB_REPLY_MASK); + u32 stream_id = msg_get_stream_id(header); + u32 stream_msg = msg_get_stream_type(header); + + stream = get_stream_by_id(hsw, stream_id); + if (stream == NULL) + return; + + switch (stream_msg) { + case IPC_STR_STAGE_MESSAGE: + case IPC_STR_NOTIFICATION: + case IPC_STR_RESET: + break; + case IPC_STR_PAUSE: + stream->running = false; + trace_ipc_notification("stream paused", + stream->reply.stream_hw_id); + break; + case IPC_STR_RESUME: + stream->running = true; + trace_ipc_notification("stream running", + stream->reply.stream_hw_id); + break; + } +} + +static int hsw_process_reply(struct sst_hsw *hsw, u32 header) +{ + struct ipc_message *msg; + u32 reply = msg_get_global_reply(header); + + trace_ipc_reply("processing -->", header); + + msg = reply_find_msg(hsw, header); + if (msg == NULL) { + trace_ipc_error("error: can't find message header", header); + return -EIO; + } + + /* first process the header */ + switch (reply) { + case IPC_GLB_REPLY_PENDING: + trace_ipc_pending_reply("received", header); + msg->pending = true; + hsw->pending = true; + return 1; + case IPC_GLB_REPLY_SUCCESS: + if (msg->pending) { + trace_ipc_pending_reply("completed", header); + sst_dsp_inbox_read(hsw->dsp, msg->rx_data, + msg->rx_size); + hsw->pending = false; + } else { + /* copy data from the DSP */ + sst_dsp_outbox_read(hsw->dsp, msg->rx_data, + msg->rx_size); + } + break; + /* these will be rare - but useful for debug */ + case IPC_GLB_REPLY_UNKNOWN_MESSAGE_TYPE: + trace_ipc_error("error: unknown message type", header); + msg->errno = -EBADMSG; + break; + case IPC_GLB_REPLY_OUT_OF_RESOURCES: + trace_ipc_error("error: out of resources", header); + msg->errno = -ENOMEM; + break; + case IPC_GLB_REPLY_BUSY: + trace_ipc_error("error: reply busy", header); + msg->errno = -EBUSY; + break; + case IPC_GLB_REPLY_FAILURE: + trace_ipc_error("error: reply failure", header); + msg->errno = -EINVAL; + break; + case IPC_GLB_REPLY_STAGE_UNINITIALIZED: + trace_ipc_error("error: stage uninitialized", header); + msg->errno = -EINVAL; + break; + case IPC_GLB_REPLY_NOT_FOUND: + trace_ipc_error("error: reply not found", header); + msg->errno = -EINVAL; + break; + case IPC_GLB_REPLY_SOURCE_NOT_STARTED: + trace_ipc_error("error: source not started", header); + msg->errno = -EINVAL; + break; + case IPC_GLB_REPLY_INVALID_REQUEST: + trace_ipc_error("error: invalid request", header); + msg->errno = -EINVAL; + break; + case IPC_GLB_REPLY_ERROR_INVALID_PARAM: + trace_ipc_error("error: invalid parameter", header); + msg->errno = -EINVAL; + break; + default: + trace_ipc_error("error: unknown reply", header); + msg->errno = -EINVAL; + break; + } + + /* update any stream states */ + hsw_stream_update(hsw, msg); + + /* wake up and return the error if we have waiters on this message ? */ + list_del(&msg->list); + tx_msg_reply_complete(hsw, msg); + + return 1; +} + +static int hsw_stream_message(struct sst_hsw *hsw, u32 header) +{ + u32 stream_msg, stream_id, stage_type; + struct sst_hsw_stream *stream; + int handled = 0; + + stream_msg = msg_get_stream_type(header); + stream_id = msg_get_stream_id(header); + stage_type = msg_get_stage_type(header); + + stream = get_stream_by_id(hsw, stream_id); + if (stream == NULL) + return handled; + + stream->header = header; + + switch (stream_msg) { + case IPC_STR_STAGE_MESSAGE: + dev_err(hsw->dev, "error: stage msg not implemented 0x%8.8x\n", + header); + break; + case IPC_STR_NOTIFICATION: + schedule_work(&stream->notify_work); + break; + default: + /* handle pending message complete request */ + handled = hsw_process_reply(hsw, header); + break; + } + + return handled; +} + +static int hsw_log_message(struct sst_hsw *hsw, u32 header) +{ + u32 operation = (header & IPC_LOG_OP_MASK) >> IPC_LOG_OP_SHIFT; + struct sst_hsw_log_stream *stream = &hsw->log_stream; + int ret = 1; + + if (operation != IPC_DEBUG_REQUEST_LOG_DUMP) { + dev_err(hsw->dev, + "error: log msg not implemented 0x%8.8x\n", header); + return 0; + } + + mutex_lock(&stream->rw_mutex); + stream->last_pos = stream->curr_pos; + sst_dsp_inbox_read( + hsw->dsp, &stream->curr_pos, sizeof(stream->curr_pos)); + mutex_unlock(&stream->rw_mutex); + + schedule_work(&stream->notify_work); + + return ret; +} + +static int hsw_process_notification(struct sst_hsw *hsw) +{ + struct sst_dsp *sst = hsw->dsp; + u32 type, header; + int handled = 1; + + header = sst_dsp_shim_read_unlocked(sst, SST_IPCD); + type = msg_get_global_type(header); + + trace_ipc_request("processing -->", header); + + /* FW Ready is a special case */ + if (!hsw->boot_complete && header & IPC_FW_READY) { + hsw_fw_ready(hsw, header); + return handled; + } + + switch (type) { + case IPC_GLB_GET_FW_VERSION: + case IPC_GLB_ALLOCATE_STREAM: + case IPC_GLB_FREE_STREAM: + case IPC_GLB_GET_FW_CAPABILITIES: + case IPC_GLB_REQUEST_DUMP: + case IPC_GLB_GET_DEVICE_FORMATS: + case IPC_GLB_SET_DEVICE_FORMATS: + case IPC_GLB_ENTER_DX_STATE: + case IPC_GLB_GET_MIXER_STREAM_INFO: + case IPC_GLB_MAX_IPC_MESSAGE_TYPE: + case IPC_GLB_RESTORE_CONTEXT: + case IPC_GLB_SHORT_REPLY: + dev_err(hsw->dev, "error: message type %d header 0x%x\n", + type, header); + break; + case IPC_GLB_STREAM_MESSAGE: + handled = hsw_stream_message(hsw, header); + break; + case IPC_GLB_DEBUG_LOG_MESSAGE: + handled = hsw_log_message(hsw, header); + break; + default: + dev_err(hsw->dev, "error: unexpected type %d hdr 0x%8.8x\n", + type, header); + break; + } + + return handled; +} + +static irqreturn_t hsw_irq_thread(int irq, void *context) +{ + struct sst_dsp *sst = (struct sst_dsp *) context; + struct sst_hsw *hsw = sst_dsp_get_thread_context(sst); + u32 ipcx, ipcd; + int handled; + unsigned long flags; + + spin_lock_irqsave(&sst->spinlock, flags); + + ipcx = sst_dsp_ipc_msg_rx(hsw->dsp); + ipcd = sst_dsp_shim_read_unlocked(sst, SST_IPCD); + + /* reply message from DSP */ + if (ipcx & SST_IPCX_DONE) { + + /* Handle Immediate reply from DSP Core */ + handled = hsw_process_reply(hsw, ipcx); + + if (handled > 0) { + /* clear DONE bit - tell DSP we have completed */ + sst_dsp_shim_update_bits_unlocked(sst, SST_IPCX, + SST_IPCX_DONE, 0); + + /* unmask Done interrupt */ + sst_dsp_shim_update_bits_unlocked(sst, SST_IMRX, + SST_IMRX_DONE, 0); + } + } + + /* new message from DSP */ + if (ipcd & SST_IPCD_BUSY) { + + /* Handle Notification and Delayed reply from DSP Core */ + handled = hsw_process_notification(hsw); + + /* clear BUSY bit and set DONE bit - accept new messages */ + if (handled > 0) { + sst_dsp_shim_update_bits_unlocked(sst, SST_IPCD, + SST_IPCD_BUSY | SST_IPCD_DONE, SST_IPCD_DONE); + + /* unmask busy interrupt */ + sst_dsp_shim_update_bits_unlocked(sst, SST_IMRX, + SST_IMRX_BUSY, 0); + } + } + + spin_unlock_irqrestore(&sst->spinlock, flags); + + /* continue to send any remaining messages... */ + queue_kthread_work(&hsw->kworker, &hsw->kwork); + + return IRQ_HANDLED; +} + +int sst_hsw_fw_get_version(struct sst_hsw *hsw, + struct sst_hsw_ipc_fw_version *version) +{ + int ret; + + ret = ipc_tx_message_wait(hsw, IPC_GLB_TYPE(IPC_GLB_GET_FW_VERSION), + NULL, 0, version, sizeof(*version)); + if (ret < 0) + dev_err(hsw->dev, "error: get version failed\n"); + + return ret; +} + +/* Mixer Controls */ +int sst_hsw_stream_mute(struct sst_hsw *hsw, struct sst_hsw_stream *stream, + u32 stage_id, u32 channel) +{ + int ret; + + ret = sst_hsw_stream_get_volume(hsw, stream, stage_id, channel, + &stream->mute_volume[channel]); + if (ret < 0) + return ret; + + ret = sst_hsw_stream_set_volume(hsw, stream, stage_id, channel, 0); + if (ret < 0) { + dev_err(hsw->dev, "error: can't unmute stream %d channel %d\n", + stream->reply.stream_hw_id, channel); + return ret; + } + + stream->mute[channel] = 1; + return 0; +} + +int sst_hsw_stream_unmute(struct sst_hsw *hsw, struct sst_hsw_stream *stream, + u32 stage_id, u32 channel) + +{ + int ret; + + stream->mute[channel] = 0; + ret = sst_hsw_stream_set_volume(hsw, stream, stage_id, channel, + stream->mute_volume[channel]); + if (ret < 0) { + dev_err(hsw->dev, "error: can't unmute stream %d channel %d\n", + stream->reply.stream_hw_id, channel); + return ret; + } + + return 0; +} + +int sst_hsw_stream_get_volume(struct sst_hsw *hsw, struct sst_hsw_stream *stream, + u32 stage_id, u32 channel, u32 *volume) +{ + if (channel > 1) + return -EINVAL; + + sst_dsp_read(hsw->dsp, volume, + stream->reply.volume_register_address[channel], sizeof(volume)); + + return 0; +} + +int sst_hsw_stream_set_volume_curve(struct sst_hsw *hsw, + struct sst_hsw_stream *stream, u64 curve_duration, + enum sst_hsw_volume_curve curve) +{ + /* curve duration in steps of 100ns */ + stream->vol_req.curve_duration = curve_duration; + stream->vol_req.curve_type = curve; + + return 0; +} + +/* stream volume */ +int sst_hsw_stream_set_volume(struct sst_hsw *hsw, + struct sst_hsw_stream *stream, u32 stage_id, u32 channel, u32 volume) +{ + struct sst_hsw_ipc_volume_req *req; + u32 header; + int ret; + + trace_ipc_request("set stream volume", stream->reply.stream_hw_id); + + if (channel > 1) + return -EINVAL; + + if (stream->mute[channel]) { + stream->mute_volume[channel] = volume; + return 0; + } + + header = IPC_GLB_TYPE(IPC_GLB_STREAM_MESSAGE) | + IPC_STR_TYPE(IPC_STR_STAGE_MESSAGE); + header |= (stream->reply.stream_hw_id << IPC_STR_ID_SHIFT); + header |= (IPC_STG_SET_VOLUME << IPC_STG_TYPE_SHIFT); + header |= (stage_id << IPC_STG_ID_SHIFT); + + req = &stream->vol_req; + req->channel = channel; + req->target_volume = volume; + + ret = ipc_tx_message_wait(hsw, header, req, sizeof(*req), NULL, 0); + if (ret < 0) { + dev_err(hsw->dev, "error: set stream volume failed\n"); + return ret; + } + + return 0; +} + +int sst_hsw_mixer_mute(struct sst_hsw *hsw, u32 stage_id, u32 channel) +{ + int ret; + + ret = sst_hsw_mixer_get_volume(hsw, stage_id, channel, + &hsw->mute_volume[channel]); + if (ret < 0) + return ret; + + ret = sst_hsw_mixer_set_volume(hsw, stage_id, channel, 0); + if (ret < 0) { + dev_err(hsw->dev, "error: failed to unmute mixer channel %d\n", + channel); + return ret; + } + + hsw->mute[channel] = 1; + return 0; +} + +int sst_hsw_mixer_unmute(struct sst_hsw *hsw, u32 stage_id, u32 channel) +{ + int ret; + + ret = sst_hsw_mixer_set_volume(hsw, stage_id, channel, + hsw->mixer_info.volume_register_address[channel]); + if (ret < 0) { + dev_err(hsw->dev, "error: failed to unmute mixer channel %d\n", + channel); + return ret; + } + + hsw->mute[channel] = 0; + return 0; +} + +int sst_hsw_mixer_get_volume(struct sst_hsw *hsw, u32 stage_id, u32 channel, + u32 *volume) +{ + if (channel > 1) + return -EINVAL; + + sst_dsp_read(hsw->dsp, volume, + hsw->mixer_info.volume_register_address[channel], + sizeof(*volume)); + + return 0; +} + +int sst_hsw_mixer_set_volume_curve(struct sst_hsw *hsw, + u64 curve_duration, enum sst_hsw_volume_curve curve) +{ + /* curve duration in steps of 100ns */ + hsw->curve_duration = curve_duration; + hsw->curve_type = curve; + + return 0; +} + +/* global mixer volume */ +int sst_hsw_mixer_set_volume(struct sst_hsw *hsw, u32 stage_id, u32 channel, + u32 volume) +{ + struct sst_hsw_ipc_volume_req req; + u32 header; + int ret; + + trace_ipc_request("set mixer volume", volume); + + /* set both at same time ? */ + if (channel == 2) { + if (hsw->mute[0] && hsw->mute[1]) { + hsw->mute_volume[0] = hsw->mute_volume[1] = volume; + return 0; + } else if (hsw->mute[0]) + req.channel = 1; + else if (hsw->mute[1]) + req.channel = 0; + else + req.channel = 0xffffffff; + } else { + /* set only 1 channel */ + if (hsw->mute[channel]) { + hsw->mute_volume[channel] = volume; + return 0; + } + req.channel = channel; + } + + header = IPC_GLB_TYPE(IPC_GLB_STREAM_MESSAGE) | + IPC_STR_TYPE(IPC_STR_STAGE_MESSAGE); + header |= (hsw->mixer_info.mixer_hw_id << IPC_STR_ID_SHIFT); + header |= (IPC_STG_SET_VOLUME << IPC_STG_TYPE_SHIFT); + header |= (stage_id << IPC_STG_ID_SHIFT); + + req.curve_duration = hsw->curve_duration; + req.curve_type = hsw->curve_type; + req.target_volume = volume; + + ret = ipc_tx_message_wait(hsw, header, &req, sizeof(req), NULL, 0); + if (ret < 0) { + dev_err(hsw->dev, "error: set mixer volume failed\n"); + return ret; + } + + return 0; +} + +/* Stream API */ +struct sst_hsw_stream *sst_hsw_stream_new(struct sst_hsw *hsw, int id, + u32 (*notify_position)(struct sst_hsw_stream *stream, void *data), + void *data) +{ + struct sst_hsw_stream *stream; + + stream = kzalloc(sizeof(*stream), GFP_KERNEL); + if (stream == NULL) + return NULL; + + list_add(&stream->node, &hsw->stream_list); + stream->notify_position = notify_position; + stream->pdata = data; + stream->hsw = hsw; + stream->host_id = id; + + /* work to process notification messages */ + INIT_WORK(&stream->notify_work, hsw_notification_work); + + return stream; +} + +int sst_hsw_stream_free(struct sst_hsw *hsw, struct sst_hsw_stream *stream) +{ + u32 header; + int ret = 0; + + /* dont free DSP streams that are not commited */ + if (!stream->commited) + goto out; + + trace_ipc_request("stream free", stream->host_id); + + stream->free_req.stream_id = stream->reply.stream_hw_id; + header = IPC_GLB_TYPE(IPC_GLB_FREE_STREAM); + + ret = ipc_tx_message_wait(hsw, header, &stream->free_req, + sizeof(stream->free_req), NULL, 0); + if (ret < 0) { + dev_err(hsw->dev, "error: free stream %d failed\n", + stream->free_req.stream_id); + return -EAGAIN; + } + + trace_hsw_stream_free_req(stream, &stream->free_req); + +out: + list_del(&stream->node); + kfree(stream); + + return ret; +} + +int sst_hsw_stream_set_bits(struct sst_hsw *hsw, + struct sst_hsw_stream *stream, enum sst_hsw_bitdepth bits) +{ + if (stream->commited) { + dev_err(hsw->dev, "error: stream committed for set bits\n"); + return -EINVAL; + } + + stream->request.format.bitdepth = bits; + return 0; +} + +int sst_hsw_stream_set_channels(struct sst_hsw *hsw, + struct sst_hsw_stream *stream, int channels) +{ + if (stream->commited) { + dev_err(hsw->dev, "error: stream committed for set channels\n"); + return -EINVAL; + } + + /* stereo is only supported atm */ + if (channels != 2) + return -EINVAL; + + stream->request.format.ch_num = channels; + return 0; +} + +int sst_hsw_stream_set_rate(struct sst_hsw *hsw, + struct sst_hsw_stream *stream, int rate) +{ + if (stream->commited) { + dev_err(hsw->dev, "error: stream committed for set rate\n"); + return -EINVAL; + } + + stream->request.format.frequency = rate; + return 0; +} + +int sst_hsw_stream_set_map_config(struct sst_hsw *hsw, + struct sst_hsw_stream *stream, u32 map, + enum sst_hsw_channel_config config) +{ + if (stream->commited) { + dev_err(hsw->dev, "error: stream committed for set map\n"); + return -EINVAL; + } + + stream->request.format.map = map; + stream->request.format.config = config; + return 0; +} + +int sst_hsw_stream_set_style(struct sst_hsw *hsw, + struct sst_hsw_stream *stream, enum sst_hsw_interleaving style) +{ + if (stream->commited) { + dev_err(hsw->dev, "error: stream committed for set style\n"); + return -EINVAL; + } + + stream->request.format.style = style; + return 0; +} + +int sst_hsw_stream_set_valid(struct sst_hsw *hsw, + struct sst_hsw_stream *stream, u32 bits) +{ + if (stream->commited) { + dev_err(hsw->dev, "error: stream committed for set valid bits\n"); + return -EINVAL; + } + + stream->request.format.valid_bit = bits; + return 0; +} + +/* Stream Configuration */ +int sst_hsw_stream_format(struct sst_hsw *hsw, struct sst_hsw_stream *stream, + enum sst_hsw_stream_path_id path_id, + enum sst_hsw_stream_type stream_type, + enum sst_hsw_stream_format format_id) +{ + if (stream->commited) { + dev_err(hsw->dev, "error: stream committed for set format\n"); + return -EINVAL; + } + + stream->request.path_id = path_id; + stream->request.stream_type = stream_type; + stream->request.format_id = format_id; + + trace_hsw_stream_alloc_request(stream, &stream->request); + + return 0; +} + +int sst_hsw_stream_buffer(struct sst_hsw *hsw, struct sst_hsw_stream *stream, + u32 ring_pt_address, u32 num_pages, + u32 ring_size, u32 ring_offset, u32 ring_first_pfn) +{ + if (stream->commited) { + dev_err(hsw->dev, "error: stream committed for buffer\n"); + return -EINVAL; + } + + stream->request.ringinfo.ring_pt_address = ring_pt_address; + stream->request.ringinfo.num_pages = num_pages; + stream->request.ringinfo.ring_size = ring_size; + stream->request.ringinfo.ring_offset = ring_offset; + stream->request.ringinfo.ring_first_pfn = ring_first_pfn; + + trace_hsw_stream_buffer(stream); + + return 0; +} + +int sst_hsw_stream_set_module_info(struct sst_hsw *hsw, + struct sst_hsw_stream *stream, enum sst_hsw_module_id module_id, + u32 entry_point) +{ + struct sst_hsw_module_map *map = &stream->request.map; + + if (stream->commited) { + dev_err(hsw->dev, "error: stream committed for set module\n"); + return -EINVAL; + } + + /* only support initial module atm */ + map->module_entries_count = 1; + map->module_entries[0].module_id = module_id; + map->module_entries[0].entry_point = entry_point; + + return 0; +} + +int sst_hsw_stream_set_pmemory_info(struct sst_hsw *hsw, + struct sst_hsw_stream *stream, u32 offset, u32 size) +{ + if (stream->commited) { + dev_err(hsw->dev, "error: stream committed for set pmem\n"); + return -EINVAL; + } + + stream->request.persistent_mem.offset = offset; + stream->request.persistent_mem.size = size; + + return 0; +} + +int sst_hsw_stream_set_smemory_info(struct sst_hsw *hsw, + struct sst_hsw_stream *stream, u32 offset, u32 size) +{ + if (stream->commited) { + dev_err(hsw->dev, "error: stream committed for set smem\n"); + return -EINVAL; + } + + stream->request.scratch_mem.offset = offset; + stream->request.scratch_mem.size = size; + + return 0; +} + +int sst_hsw_stream_commit(struct sst_hsw *hsw, struct sst_hsw_stream *stream) +{ + struct sst_hsw_ipc_stream_alloc_req *str_req = &stream->request; + struct sst_hsw_ipc_stream_alloc_reply *reply = &stream->reply; + u32 header; + int ret; + + trace_ipc_request("stream alloc", stream->host_id); + + header = IPC_GLB_TYPE(IPC_GLB_ALLOCATE_STREAM); + + ret = ipc_tx_message_wait(hsw, header, str_req, sizeof(*str_req), + reply, sizeof(*reply)); + if (ret < 0) { + dev_err(hsw->dev, "error: stream commit failed\n"); + return ret; + } + + stream->commited = 1; + trace_hsw_stream_alloc_reply(stream); + + return 0; +} + +/* Stream Information - these calls could be inline but we want the IPC + ABI to be opaque to client PCM drivers to cope with any future ABI changes */ +int sst_hsw_stream_get_hw_id(struct sst_hsw *hsw, + struct sst_hsw_stream *stream) +{ + return stream->reply.stream_hw_id; +} + +int sst_hsw_stream_get_mixer_id(struct sst_hsw *hsw, + struct sst_hsw_stream *stream) +{ + return stream->reply.mixer_hw_id; +} + +u32 sst_hsw_stream_get_read_reg(struct sst_hsw *hsw, + struct sst_hsw_stream *stream) +{ + return stream->reply.read_position_register_address; +} + +u32 sst_hsw_stream_get_pointer_reg(struct sst_hsw *hsw, + struct sst_hsw_stream *stream) +{ + return stream->reply.presentation_position_register_address; +} + +u32 sst_hsw_stream_get_peak_reg(struct sst_hsw *hsw, + struct sst_hsw_stream *stream, u32 channel) +{ + if (channel >= 2) + return 0; + + return stream->reply.peak_meter_register_address[channel]; +} + +u32 sst_hsw_stream_get_vol_reg(struct sst_hsw *hsw, + struct sst_hsw_stream *stream, u32 channel) +{ + if (channel >= 2) + return 0; + + return stream->reply.volume_register_address[channel]; +} + +int sst_hsw_mixer_get_info(struct sst_hsw *hsw) +{ + struct sst_hsw_ipc_stream_info_reply *reply; + u32 header; + int ret; + + reply = &hsw->mixer_info; + header = IPC_GLB_TYPE(IPC_GLB_GET_MIXER_STREAM_INFO); + + trace_ipc_request("get global mixer info", 0); + + ret = ipc_tx_message_wait(hsw, header, NULL, 0, reply, sizeof(*reply)); + if (ret < 0) { + dev_err(hsw->dev, "error: get stream info failed\n"); + return ret; + } + + trace_hsw_mixer_info_reply(reply); + + return 0; +} + +/* Send stream command */ +static int sst_hsw_stream_operations(struct sst_hsw *hsw, int type, + int stream_id, int wait) +{ + u32 header; + + header = IPC_GLB_TYPE(IPC_GLB_STREAM_MESSAGE) | IPC_STR_TYPE(type); + header |= (stream_id << IPC_STR_ID_SHIFT); + + if (wait) + return ipc_tx_message_wait(hsw, header, NULL, 0, NULL, 0); + else + return ipc_tx_message_nowait(hsw, header, NULL, 0); +} + +/* Stream ALSA trigger operations */ +int sst_hsw_stream_pause(struct sst_hsw *hsw, struct sst_hsw_stream *stream, + int wait) +{ + int ret; + + trace_ipc_request("stream pause", stream->reply.stream_hw_id); + + ret = sst_hsw_stream_operations(hsw, IPC_STR_PAUSE, + stream->reply.stream_hw_id, wait); + if (ret < 0) + dev_err(hsw->dev, "error: failed to pause stream %d\n", + stream->reply.stream_hw_id); + + return ret; +} + +int sst_hsw_stream_resume(struct sst_hsw *hsw, struct sst_hsw_stream *stream, + int wait) +{ + int ret; + + trace_ipc_request("stream resume", stream->reply.stream_hw_id); + + ret = sst_hsw_stream_operations(hsw, IPC_STR_RESUME, + stream->reply.stream_hw_id, wait); + if (ret < 0) + dev_err(hsw->dev, "error: failed to resume stream %d\n", + stream->reply.stream_hw_id); + + return ret; +} + +int sst_hsw_stream_reset(struct sst_hsw *hsw, struct sst_hsw_stream *stream) +{ + int ret, tries = 10; + + /* dont reset streams that are not commited */ + if (!stream->commited) + return 0; + + /* wait for pause to complete before we reset the stream */ + while (stream->running && tries--) + msleep(1); + if (!tries) { + dev_err(hsw->dev, "error: reset stream %d still running\n", + stream->reply.stream_hw_id); + return -EINVAL; + } + + trace_ipc_request("stream reset", stream->reply.stream_hw_id); + + ret = sst_hsw_stream_operations(hsw, IPC_STR_RESET, + stream->reply.stream_hw_id, 1); + if (ret < 0) + dev_err(hsw->dev, "error: failed to reset stream %d\n", + stream->reply.stream_hw_id); + return ret; +} + +/* Stream pointer positions */ +int sst_hsw_get_dsp_position(struct sst_hsw *hsw, + struct sst_hsw_stream *stream) +{ + return stream->rpos.position; +} + +int sst_hsw_stream_set_write_position(struct sst_hsw *hsw, + struct sst_hsw_stream *stream, u32 stage_id, u32 position) +{ + u32 header; + int ret; + + trace_stream_write_position(stream->reply.stream_hw_id, position); + + header = IPC_GLB_TYPE(IPC_GLB_STREAM_MESSAGE) | + IPC_STR_TYPE(IPC_STR_STAGE_MESSAGE); + header |= (stream->reply.stream_hw_id << IPC_STR_ID_SHIFT); + header |= (IPC_STG_SET_WRITE_POSITION << IPC_STG_TYPE_SHIFT); + header |= (stage_id << IPC_STG_ID_SHIFT); + stream->wpos.position = position; + + ret = ipc_tx_message_nowait(hsw, header, &stream->wpos, + sizeof(stream->wpos)); + if (ret < 0) + dev_err(hsw->dev, "error: stream %d set position %d failed\n", + stream->reply.stream_hw_id, position); + + return ret; +} + +/* physical BE config */ +int sst_hsw_device_set_config(struct sst_hsw *hsw, + enum sst_hsw_device_id dev, enum sst_hsw_device_mclk mclk, + enum sst_hsw_device_mode mode, u32 clock_divider) +{ + struct sst_hsw_ipc_device_config_req config; + u32 header; + int ret; + + trace_ipc_request("set device config", dev); + + config.ssp_interface = dev; + config.clock_frequency = mclk; + config.mode = mode; + config.clock_divider = clock_divider; + + trace_hsw_device_config_req(&config); + + header = IPC_GLB_TYPE(IPC_GLB_SET_DEVICE_FORMATS); + + ret = ipc_tx_message_wait(hsw, header, &config, sizeof(config), + NULL, 0); + if (ret < 0) + dev_err(hsw->dev, "error: set device formats failed\n"); + + return ret; +} +EXPORT_SYMBOL_GPL(sst_hsw_device_set_config); + +/* DX Config */ +int sst_hsw_dx_set_state(struct sst_hsw *hsw, + enum sst_hsw_dx_state state, struct sst_hsw_ipc_dx_reply *dx) +{ + u32 header, state_; + int ret; + + header = IPC_GLB_TYPE(IPC_GLB_ENTER_DX_STATE); + state_ = state; + + trace_ipc_request("PM enter Dx state", state); + + ret = ipc_tx_message_wait(hsw, header, &state_, sizeof(state_), + dx, sizeof(dx)); + if (ret < 0) { + dev_err(hsw->dev, "ipc: error set dx state %d failed\n", state); + return ret; + } + + dev_dbg(hsw->dev, "ipc: got %d entry numbers for state %d\n", + dx->entries_no, state); + + memcpy(&hsw->dx, dx, sizeof(*dx)); + return 0; +} + +/* Used to save state into hsw->dx_reply */ +int sst_hsw_dx_get_state(struct sst_hsw *hsw, u32 item, + u32 *offset, u32 *size, u32 *source) +{ + struct sst_hsw_ipc_dx_memory_item *dx_mem; + struct sst_hsw_ipc_dx_reply *dx_reply; + int entry_no; + + dx_reply = &hsw->dx; + entry_no = dx_reply->entries_no; + + trace_ipc_request("PM get Dx state", entry_no); + + if (item >= entry_no) + return -EINVAL; + + dx_mem = &dx_reply->mem_info[item]; + *offset = dx_mem->offset; + *size = dx_mem->size; + *source = dx_mem->source; + + return 0; +} + +static int msg_empty_list_init(struct sst_hsw *hsw) +{ + int i; + + hsw->msg = kzalloc(sizeof(struct ipc_message) * + IPC_EMPTY_LIST_SIZE, GFP_KERNEL); + if (hsw->msg == NULL) + return -ENOMEM; + + for (i = 0; i < IPC_EMPTY_LIST_SIZE; i++) { + init_waitqueue_head(&hsw->msg[i].waitq); + list_add(&hsw->msg[i].list, &hsw->empty_list); + } + + return 0; +} + +void sst_hsw_set_scratch_module(struct sst_hsw *hsw, + struct sst_module *scratch) +{ + hsw->scratch = scratch; +} + +struct sst_dsp *sst_hsw_get_dsp(struct sst_hsw *hsw) +{ + return hsw->dsp; +} + +static struct sst_dsp_device hsw_dev = { + .thread = hsw_irq_thread, + .ops = &haswell_ops, +}; + +int sst_hsw_dsp_init(struct device *dev, struct sst_pdata *pdata) +{ + struct sst_hsw_ipc_fw_version version; + struct sst_hsw *hsw; + struct sst_fw *hsw_sst_fw; + int ret; + + dev_dbg(dev, "initialising Audio DSP IPC\n"); + + hsw = devm_kzalloc(dev, sizeof(*hsw), GFP_KERNEL); + if (hsw == NULL) + return -ENOMEM; + + hsw->dev = dev; + INIT_LIST_HEAD(&hsw->stream_list); + INIT_LIST_HEAD(&hsw->tx_list); + INIT_LIST_HEAD(&hsw->rx_list); + INIT_LIST_HEAD(&hsw->empty_list); + init_waitqueue_head(&hsw->boot_wait); + init_waitqueue_head(&hsw->wait_txq); + + ret = msg_empty_list_init(hsw); + if (ret < 0) + goto list_err; + + /* start the IPC message thread */ + init_kthread_worker(&hsw->kworker); + hsw->tx_thread = kthread_run(kthread_worker_fn, + &hsw->kworker, + dev_name(hsw->dev)); + if (IS_ERR(hsw->tx_thread)) { + ret = PTR_ERR(hsw->tx_thread); + dev_err(hsw->dev, "error: failed to create message TX task\n"); + goto list_err; + } + init_kthread_work(&hsw->kwork, ipc_tx_msgs); + + hsw_dev.thread_context = hsw; + + /* init SST shim */ + hsw->dsp = sst_dsp_new(dev, &hsw_dev, pdata); + if (hsw->dsp == NULL) { + ret = -ENODEV; + goto list_err; + } + + /* keep the DSP in reset state for base FW loading */ + sst_dsp_reset(hsw->dsp); + + hsw_sst_fw = sst_fw_new(hsw->dsp, pdata->fw, hsw); + + if (hsw_sst_fw == NULL) { + ret = -ENODEV; + dev_err(dev, "error: failed to load firmware\n"); + goto fw_err; + } + + /* wait for DSP boot completion */ + sst_dsp_boot(hsw->dsp); + ret = wait_event_timeout(hsw->boot_wait, hsw->boot_complete, + msecs_to_jiffies(IPC_BOOT_MSECS)); + if (ret == 0) { + ret = -EIO; + dev_err(hsw->dev, "error: ADSP boot timeout\n"); + goto boot_err; + } + + /* get the FW version */ + sst_hsw_fw_get_version(hsw, &version); + dev_info(hsw->dev, "FW loaded: type %d - version: %d.%d build %d\n", + version.type, version.major, version.minor, version.build); + + /* get the globalmixer */ + ret = sst_hsw_mixer_get_info(hsw); + if (ret < 0) { + dev_err(hsw->dev, "error: failed to get stream info\n"); + goto boot_err; + } + + pdata->dsp = hsw; + return 0; + +boot_err: + sst_dsp_reset(hsw->dsp); + sst_fw_free(hsw_sst_fw); +fw_err: + sst_dsp_free(hsw->dsp); + kfree(hsw->msg); +list_err: + return ret; +} +EXPORT_SYMBOL_GPL(sst_hsw_dsp_init); + +void sst_hsw_dsp_free(struct device *dev, struct sst_pdata *pdata) +{ + struct sst_hsw *hsw = pdata->dsp; + + sst_dsp_reset(hsw->dsp); + sst_fw_free_all(hsw->dsp); + sst_dsp_free(hsw->dsp); + kfree(hsw->scratch); + kfree(hsw->msg); +} +EXPORT_SYMBOL_GPL(sst_hsw_dsp_free); diff --git a/sound/soc/intel/sst-haswell-ipc.h b/sound/soc/intel/sst-haswell-ipc.h new file mode 100644 index 00000000000..d517929ccc3 --- /dev/null +++ b/sound/soc/intel/sst-haswell-ipc.h @@ -0,0 +1,488 @@ +/* + * Intel SST Haswell/Broadwell IPC Support + * + * Copyright (C) 2013, Intel Corporation. All rights reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License version + * 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +#ifndef __SST_HASWELL_IPC_H +#define __SST_HASWELL_IPC_H + +#include <linux/types.h> +#include <linux/kernel.h> +#include <linux/platform_device.h> + +#define SST_HSW_NO_CHANNELS 2 +#define SST_HSW_MAX_DX_REGIONS 14 + +#define SST_HSW_FW_LOG_CONFIG_DWORDS 12 +#define SST_HSW_GLOBAL_LOG 15 + +/** + * Upfront defined maximum message size that is + * expected by the in/out communication pipes in FW. + */ +#define SST_HSW_IPC_MAX_PAYLOAD_SIZE 400 +#define SST_HSW_MAX_INFO_SIZE 64 +#define SST_HSW_BUILD_HASH_LENGTH 40 + +struct sst_hsw; +struct sst_hsw_stream; +struct sst_hsw_log_stream; +struct sst_pdata; +struct sst_module; +extern struct sst_ops haswell_ops; + +/* Stream Allocate Path ID */ +enum sst_hsw_stream_path_id { + SST_HSW_STREAM_PATH_SSP0_OUT = 0, + SST_HSW_STREAM_PATH_SSP0_IN = 1, + SST_HSW_STREAM_PATH_MAX_PATH_ID = 2, +}; + +/* Stream Allocate Stream Type */ +enum sst_hsw_stream_type { + SST_HSW_STREAM_TYPE_RENDER = 0, + SST_HSW_STREAM_TYPE_SYSTEM = 1, + SST_HSW_STREAM_TYPE_CAPTURE = 2, + SST_HSW_STREAM_TYPE_LOOPBACK = 3, + SST_HSW_STREAM_TYPE_MAX_STREAM_TYPE = 4, +}; + +/* Stream Allocate Stream Format */ +enum sst_hsw_stream_format { + SST_HSW_STREAM_FORMAT_PCM_FORMAT = 0, + SST_HSW_STREAM_FORMAT_MP3_FORMAT = 1, + SST_HSW_STREAM_FORMAT_AAC_FORMAT = 2, + SST_HSW_STREAM_FORMAT_MAX_FORMAT_ID = 3, +}; + +/* Device ID */ +enum sst_hsw_device_id { + SST_HSW_DEVICE_SSP_0 = 0, + SST_HSW_DEVICE_SSP_1 = 1, +}; + +/* Device Master Clock Frequency */ +enum sst_hsw_device_mclk { + SST_HSW_DEVICE_MCLK_OFF = 0, + SST_HSW_DEVICE_MCLK_FREQ_6_MHZ = 1, + SST_HSW_DEVICE_MCLK_FREQ_12_MHZ = 2, + SST_HSW_DEVICE_MCLK_FREQ_24_MHZ = 3, +}; + +/* Device Clock Master */ +enum sst_hsw_device_mode { + SST_HSW_DEVICE_CLOCK_SLAVE = 0, + SST_HSW_DEVICE_CLOCK_MASTER = 1, +}; + +/* DX Power State */ +enum sst_hsw_dx_state { + SST_HSW_DX_STATE_D0 = 0, + SST_HSW_DX_STATE_D1 = 1, + SST_HSW_DX_STATE_D3 = 3, + SST_HSW_DX_STATE_MAX = 3, +}; + +/* Audio stream stage IDs */ +enum sst_hsw_fx_stage_id { + SST_HSW_STAGE_ID_WAVES = 0, + SST_HSW_STAGE_ID_DTS = 1, + SST_HSW_STAGE_ID_DOLBY = 2, + SST_HSW_STAGE_ID_BOOST = 3, + SST_HSW_STAGE_ID_MAX_FX_ID +}; + +/* DX State Type */ +enum sst_hsw_dx_type { + SST_HSW_DX_TYPE_FW_IMAGE = 0, + SST_HSW_DX_TYPE_MEMORY_DUMP = 1 +}; + +/* Volume Curve Type*/ +enum sst_hsw_volume_curve { + SST_HSW_VOLUME_CURVE_NONE = 0, + SST_HSW_VOLUME_CURVE_FADE = 1 +}; + +/* Sample ordering */ +enum sst_hsw_interleaving { + SST_HSW_INTERLEAVING_PER_CHANNEL = 0, + SST_HSW_INTERLEAVING_PER_SAMPLE = 1, +}; + +/* Channel indices */ +enum sst_hsw_channel_index { + SST_HSW_CHANNEL_LEFT = 0, + SST_HSW_CHANNEL_CENTER = 1, + SST_HSW_CHANNEL_RIGHT = 2, + SST_HSW_CHANNEL_LEFT_SURROUND = 3, + SST_HSW_CHANNEL_CENTER_SURROUND = 3, + SST_HSW_CHANNEL_RIGHT_SURROUND = 4, + SST_HSW_CHANNEL_LFE = 7, + SST_HSW_CHANNEL_INVALID = 0xF, +}; + +/* List of supported channel maps. */ +enum sst_hsw_channel_config { + SST_HSW_CHANNEL_CONFIG_MONO = 0, /* mono only. */ + SST_HSW_CHANNEL_CONFIG_STEREO = 1, /* L & R. */ + SST_HSW_CHANNEL_CONFIG_2_POINT_1 = 2, /* L, R & LFE; PCM only. */ + SST_HSW_CHANNEL_CONFIG_3_POINT_0 = 3, /* L, C & R; MP3 & AAC only. */ + SST_HSW_CHANNEL_CONFIG_3_POINT_1 = 4, /* L, C, R & LFE; PCM only. */ + SST_HSW_CHANNEL_CONFIG_QUATRO = 5, /* L, R, Ls & Rs; PCM only. */ + SST_HSW_CHANNEL_CONFIG_4_POINT_0 = 6, /* L, C, R & Cs; MP3 & AAC only. */ + SST_HSW_CHANNEL_CONFIG_5_POINT_0 = 7, /* L, C, R, Ls & Rs. */ + SST_HSW_CHANNEL_CONFIG_5_POINT_1 = 8, /* L, C, R, Ls, Rs & LFE. */ + SST_HSW_CHANNEL_CONFIG_DUAL_MONO = 9, /* One channel replicated in two. */ + SST_HSW_CHANNEL_CONFIG_INVALID, +}; + +/* List of supported bit depths. */ +enum sst_hsw_bitdepth { + SST_HSW_DEPTH_8BIT = 8, + SST_HSW_DEPTH_16BIT = 16, + SST_HSW_DEPTH_24BIT = 24, /* Default. */ + SST_HSW_DEPTH_32BIT = 32, + SST_HSW_DEPTH_INVALID = 33, +}; + +enum sst_hsw_module_id { + SST_HSW_MODULE_BASE_FW = 0x0, + SST_HSW_MODULE_MP3 = 0x1, + SST_HSW_MODULE_AAC_5_1 = 0x2, + SST_HSW_MODULE_AAC_2_0 = 0x3, + SST_HSW_MODULE_SRC = 0x4, + SST_HSW_MODULE_WAVES = 0x5, + SST_HSW_MODULE_DOLBY = 0x6, + SST_HSW_MODULE_BOOST = 0x7, + SST_HSW_MODULE_LPAL = 0x8, + SST_HSW_MODULE_DTS = 0x9, + SST_HSW_MODULE_PCM_CAPTURE = 0xA, + SST_HSW_MODULE_PCM_SYSTEM = 0xB, + SST_HSW_MODULE_PCM_REFERENCE = 0xC, + SST_HSW_MODULE_PCM = 0xD, + SST_HSW_MODULE_BLUETOOTH_RENDER_MODULE = 0xE, + SST_HSW_MODULE_BLUETOOTH_CAPTURE_MODULE = 0xF, + SST_HSW_MAX_MODULE_ID, +}; + +enum sst_hsw_performance_action { + SST_HSW_PERF_START = 0, + SST_HSW_PERF_STOP = 1, +}; + +/* SST firmware module info */ +struct sst_hsw_module_info { + u8 name[SST_HSW_MAX_INFO_SIZE]; + u8 version[SST_HSW_MAX_INFO_SIZE]; +} __attribute__((packed)); + +/* Module entry point */ +struct sst_hsw_module_entry { + enum sst_hsw_module_id module_id; + u32 entry_point; +} __attribute__((packed)); + +/* Module map - alignement matches DSP */ +struct sst_hsw_module_map { + u8 module_entries_count; + struct sst_hsw_module_entry module_entries[1]; +} __attribute__((packed)); + +struct sst_hsw_memory_info { + u32 offset; + u32 size; +} __attribute__((packed)); + +struct sst_hsw_fx_enable { + struct sst_hsw_module_map module_map; + struct sst_hsw_memory_info persistent_mem; +} __attribute__((packed)); + +struct sst_hsw_get_fx_param { + u32 parameter_id; + u32 param_size; +} __attribute__((packed)); + +struct sst_hsw_perf_action { + u32 action; +} __attribute__((packed)); + +struct sst_hsw_perf_data { + u64 timestamp; + u64 cycles; + u64 datatime; +} __attribute__((packed)); + +/* FW version */ +struct sst_hsw_ipc_fw_version { + u8 build; + u8 minor; + u8 major; + u8 type; + u8 fw_build_hash[SST_HSW_BUILD_HASH_LENGTH]; + u32 fw_log_providers_hash; +} __attribute__((packed)); + +/* Stream ring info */ +struct sst_hsw_ipc_stream_ring { + u32 ring_pt_address; + u32 num_pages; + u32 ring_size; + u32 ring_offset; + u32 ring_first_pfn; +} __attribute__((packed)); + +/* Debug Dump Log Enable Request */ +struct sst_hsw_ipc_debug_log_enable_req { + struct sst_hsw_ipc_stream_ring ringinfo; + u32 config[SST_HSW_FW_LOG_CONFIG_DWORDS]; +} __attribute__((packed)); + +/* Debug Dump Log Reply */ +struct sst_hsw_ipc_debug_log_reply { + u32 log_buffer_begining; + u32 log_buffer_size; +} __attribute__((packed)); + +/* Stream glitch position */ +struct sst_hsw_ipc_stream_glitch_position { + u32 glitch_type; + u32 present_pos; + u32 write_pos; +} __attribute__((packed)); + +/* Stream get position */ +struct sst_hsw_ipc_stream_get_position { + u32 position; + u32 fw_cycle_count; +} __attribute__((packed)); + +/* Stream set position */ +struct sst_hsw_ipc_stream_set_position { + u32 position; + u32 end_of_buffer; +} __attribute__((packed)); + +/* Stream Free Request */ +struct sst_hsw_ipc_stream_free_req { + u8 stream_id; + u8 reserved[3]; +} __attribute__((packed)); + +/* Set Volume Request */ +struct sst_hsw_ipc_volume_req { + u32 channel; + u32 target_volume; + u64 curve_duration; + u32 curve_type; +} __attribute__((packed)); + +/* Device Configuration Request */ +struct sst_hsw_ipc_device_config_req { + u32 ssp_interface; + u32 clock_frequency; + u32 mode; + u16 clock_divider; + u16 reserved; +} __attribute__((packed)); + +/* Audio Data formats */ +struct sst_hsw_audio_data_format_ipc { + u32 frequency; + u32 bitdepth; + u32 map; + u32 config; + u32 style; + u8 ch_num; + u8 valid_bit; + u8 reserved[2]; +} __attribute__((packed)); + +/* Stream Allocate Request */ +struct sst_hsw_ipc_stream_alloc_req { + u8 path_id; + u8 stream_type; + u8 format_id; + u8 reserved; + struct sst_hsw_audio_data_format_ipc format; + struct sst_hsw_ipc_stream_ring ringinfo; + struct sst_hsw_module_map map; + struct sst_hsw_memory_info persistent_mem; + struct sst_hsw_memory_info scratch_mem; + u32 number_of_notifications; +} __attribute__((packed)); + +/* Stream Allocate Reply */ +struct sst_hsw_ipc_stream_alloc_reply { + u32 stream_hw_id; + u32 mixer_hw_id; // returns rate ???? + u32 read_position_register_address; + u32 presentation_position_register_address; + u32 peak_meter_register_address[SST_HSW_NO_CHANNELS]; + u32 volume_register_address[SST_HSW_NO_CHANNELS]; +} __attribute__((packed)); + +/* Get Mixer Stream Info */ +struct sst_hsw_ipc_stream_info_reply { + u32 mixer_hw_id; + u32 peak_meter_register_address[SST_HSW_NO_CHANNELS]; + u32 volume_register_address[SST_HSW_NO_CHANNELS]; +} __attribute__((packed)); + +/* DX State Request */ +struct sst_hsw_ipc_dx_req { + u8 state; + u8 reserved[3]; +} __attribute__((packed)); + +/* DX State Reply Memory Info Item */ +struct sst_hsw_ipc_dx_memory_item { + u32 offset; + u32 size; + u32 source; +} __attribute__((packed)); + +/* DX State Reply */ +struct sst_hsw_ipc_dx_reply { + u32 entries_no; + struct sst_hsw_ipc_dx_memory_item mem_info[SST_HSW_MAX_DX_REGIONS]; +} __attribute__((packed)); + +struct sst_hsw_ipc_fw_version; + +/* SST Init & Free */ +struct sst_hsw *sst_hsw_new(struct device *dev, const u8 *fw, size_t fw_length, + u32 fw_offset); +void sst_hsw_free(struct sst_hsw *hsw); +int sst_hsw_fw_get_version(struct sst_hsw *hsw, + struct sst_hsw_ipc_fw_version *version); +u32 create_channel_map(enum sst_hsw_channel_config config); + +/* Stream Mixer Controls - */ +int sst_hsw_stream_mute(struct sst_hsw *hsw, struct sst_hsw_stream *stream, + u32 stage_id, u32 channel); +int sst_hsw_stream_unmute(struct sst_hsw *hsw, struct sst_hsw_stream *stream, + u32 stage_id, u32 channel); + +int sst_hsw_stream_set_volume(struct sst_hsw *hsw, + struct sst_hsw_stream *stream, u32 stage_id, u32 channel, u32 volume); +int sst_hsw_stream_get_volume(struct sst_hsw *hsw, + struct sst_hsw_stream *stream, u32 stage_id, u32 channel, u32 *volume); + +int sst_hsw_stream_set_volume_curve(struct sst_hsw *hsw, + struct sst_hsw_stream *stream, u64 curve_duration, + enum sst_hsw_volume_curve curve); + +/* Global Mixer Controls - */ +int sst_hsw_mixer_mute(struct sst_hsw *hsw, u32 stage_id, u32 channel); +int sst_hsw_mixer_unmute(struct sst_hsw *hsw, u32 stage_id, u32 channel); + +int sst_hsw_mixer_set_volume(struct sst_hsw *hsw, u32 stage_id, u32 channel, + u32 volume); +int sst_hsw_mixer_get_volume(struct sst_hsw *hsw, u32 stage_id, u32 channel, + u32 *volume); + +int sst_hsw_mixer_set_volume_curve(struct sst_hsw *hsw, + u64 curve_duration, enum sst_hsw_volume_curve curve); + +/* Stream API */ +struct sst_hsw_stream *sst_hsw_stream_new(struct sst_hsw *hsw, int id, + u32 (*get_write_position)(struct sst_hsw_stream *stream, void *data), + void *data); + +int sst_hsw_stream_free(struct sst_hsw *hsw, struct sst_hsw_stream *stream); + +/* Stream Configuration */ +int sst_hsw_stream_format(struct sst_hsw *hsw, struct sst_hsw_stream *stream, + enum sst_hsw_stream_path_id path_id, + enum sst_hsw_stream_type stream_type, + enum sst_hsw_stream_format format_id); + +int sst_hsw_stream_buffer(struct sst_hsw *hsw, struct sst_hsw_stream *stream, + u32 ring_pt_address, u32 num_pages, + u32 ring_size, u32 ring_offset, u32 ring_first_pfn); + +int sst_hsw_stream_commit(struct sst_hsw *hsw, struct sst_hsw_stream *stream); + +int sst_hsw_stream_set_valid(struct sst_hsw *hsw, struct sst_hsw_stream *stream, + u32 bits); +int sst_hsw_stream_set_rate(struct sst_hsw *hsw, struct sst_hsw_stream *stream, + int rate); +int sst_hsw_stream_set_bits(struct sst_hsw *hsw, struct sst_hsw_stream *stream, + enum sst_hsw_bitdepth bits); +int sst_hsw_stream_set_channels(struct sst_hsw *hsw, + struct sst_hsw_stream *stream, int channels); +int sst_hsw_stream_set_map_config(struct sst_hsw *hsw, + struct sst_hsw_stream *stream, u32 map, + enum sst_hsw_channel_config config); +int sst_hsw_stream_set_style(struct sst_hsw *hsw, struct sst_hsw_stream *stream, + enum sst_hsw_interleaving style); +int sst_hsw_stream_set_module_info(struct sst_hsw *hsw, + struct sst_hsw_stream *stream, enum sst_hsw_module_id module_id, + u32 entry_point); +int sst_hsw_stream_set_pmemory_info(struct sst_hsw *hsw, + struct sst_hsw_stream *stream, u32 offset, u32 size); +int sst_hsw_stream_set_smemory_info(struct sst_hsw *hsw, + struct sst_hsw_stream *stream, u32 offset, u32 size); +int sst_hsw_stream_get_hw_id(struct sst_hsw *hsw, + struct sst_hsw_stream *stream); +int sst_hsw_stream_get_mixer_id(struct sst_hsw *hsw, + struct sst_hsw_stream *stream); +u32 sst_hsw_stream_get_read_reg(struct sst_hsw *hsw, + struct sst_hsw_stream *stream); +u32 sst_hsw_stream_get_pointer_reg(struct sst_hsw *hsw, + struct sst_hsw_stream *stream); +u32 sst_hsw_stream_get_peak_reg(struct sst_hsw *hsw, + struct sst_hsw_stream *stream, u32 channel); +u32 sst_hsw_stream_get_vol_reg(struct sst_hsw *hsw, + struct sst_hsw_stream *stream, u32 channel); +int sst_hsw_mixer_get_info(struct sst_hsw *hsw); + +/* Stream ALSA trigger operations */ +int sst_hsw_stream_pause(struct sst_hsw *hsw, struct sst_hsw_stream *stream, + int wait); +int sst_hsw_stream_resume(struct sst_hsw *hsw, struct sst_hsw_stream *stream, + int wait); +int sst_hsw_stream_reset(struct sst_hsw *hsw, struct sst_hsw_stream *stream); + +/* Stream pointer positions */ +int sst_hsw_stream_get_read_pos(struct sst_hsw *hsw, + struct sst_hsw_stream *stream, u32 *position); +int sst_hsw_stream_get_write_pos(struct sst_hsw *hsw, + struct sst_hsw_stream *stream, u32 *position); +int sst_hsw_stream_set_write_position(struct sst_hsw *hsw, + struct sst_hsw_stream *stream, u32 stage_id, u32 position); +int sst_hsw_get_dsp_position(struct sst_hsw *hsw, + struct sst_hsw_stream *stream); + +/* HW port config */ +int sst_hsw_device_set_config(struct sst_hsw *hsw, + enum sst_hsw_device_id dev, enum sst_hsw_device_mclk mclk, + enum sst_hsw_device_mode mode, u32 clock_divider); + +/* DX Config */ +int sst_hsw_dx_set_state(struct sst_hsw *hsw, + enum sst_hsw_dx_state state, struct sst_hsw_ipc_dx_reply *dx); +int sst_hsw_dx_get_state(struct sst_hsw *hsw, u32 item, + u32 *offset, u32 *size, u32 *source); + +/* init */ +int sst_hsw_dsp_init(struct device *dev, struct sst_pdata *pdata); +void sst_hsw_dsp_free(struct device *dev, struct sst_pdata *pdata); +struct sst_dsp *sst_hsw_get_dsp(struct sst_hsw *hsw); +void sst_hsw_set_scratch_module(struct sst_hsw *hsw, + struct sst_module *scratch); + +#endif diff --git a/sound/soc/intel/sst-haswell-pcm.c b/sound/soc/intel/sst-haswell-pcm.c new file mode 100644 index 00000000000..0a32dd13a23 --- /dev/null +++ b/sound/soc/intel/sst-haswell-pcm.c @@ -0,0 +1,872 @@ +/* + * Intel SST Haswell/Broadwell PCM Support + * + * Copyright (C) 2013, Intel Corporation. All rights reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License version + * 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +#include <linux/module.h> +#include <linux/dma-mapping.h> +#include <linux/slab.h> +#include <linux/module.h> +#include <linux/delay.h> +#include <asm/page.h> +#include <asm/pgtable.h> +#include <sound/core.h> +#include <sound/pcm.h> +#include <sound/pcm_params.h> +#include <sound/dmaengine_pcm.h> +#include <sound/soc.h> +#include <sound/tlv.h> +#include <sound/compress_driver.h> + +#include "sst-haswell-ipc.h" +#include "sst-dsp-priv.h" +#include "sst-dsp.h" + +#define HSW_PCM_COUNT 6 +#define HSW_VOLUME_MAX 0x7FFFFFFF /* 0dB */ + +/* simple volume table */ +static const u32 volume_map[] = { + HSW_VOLUME_MAX >> 30, + HSW_VOLUME_MAX >> 29, + HSW_VOLUME_MAX >> 28, + HSW_VOLUME_MAX >> 27, + HSW_VOLUME_MAX >> 26, + HSW_VOLUME_MAX >> 25, + HSW_VOLUME_MAX >> 24, + HSW_VOLUME_MAX >> 23, + HSW_VOLUME_MAX >> 22, + HSW_VOLUME_MAX >> 21, + HSW_VOLUME_MAX >> 20, + HSW_VOLUME_MAX >> 19, + HSW_VOLUME_MAX >> 18, + HSW_VOLUME_MAX >> 17, + HSW_VOLUME_MAX >> 16, + HSW_VOLUME_MAX >> 15, + HSW_VOLUME_MAX >> 14, + HSW_VOLUME_MAX >> 13, + HSW_VOLUME_MAX >> 12, + HSW_VOLUME_MAX >> 11, + HSW_VOLUME_MAX >> 10, + HSW_VOLUME_MAX >> 9, + HSW_VOLUME_MAX >> 8, + HSW_VOLUME_MAX >> 7, + HSW_VOLUME_MAX >> 6, + HSW_VOLUME_MAX >> 5, + HSW_VOLUME_MAX >> 4, + HSW_VOLUME_MAX >> 3, + HSW_VOLUME_MAX >> 2, + HSW_VOLUME_MAX >> 1, + HSW_VOLUME_MAX >> 0, +}; + +#define HSW_PCM_PERIODS_MAX 64 +#define HSW_PCM_PERIODS_MIN 2 + +static const struct snd_pcm_hardware hsw_pcm_hardware = { + .info = SNDRV_PCM_INFO_MMAP | + SNDRV_PCM_INFO_MMAP_VALID | + SNDRV_PCM_INFO_INTERLEAVED | + SNDRV_PCM_INFO_PAUSE | + SNDRV_PCM_INFO_RESUME | + SNDRV_PCM_INFO_NO_PERIOD_WAKEUP, + .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FORMAT_S24_LE | + SNDRV_PCM_FMTBIT_S32_LE, + .period_bytes_min = PAGE_SIZE, + .period_bytes_max = (HSW_PCM_PERIODS_MAX / HSW_PCM_PERIODS_MIN) * PAGE_SIZE, + .periods_min = HSW_PCM_PERIODS_MIN, + .periods_max = HSW_PCM_PERIODS_MAX, + .buffer_bytes_max = HSW_PCM_PERIODS_MAX * PAGE_SIZE, +}; + +/* private data for each PCM DSP stream */ +struct hsw_pcm_data { + int dai_id; + struct sst_hsw_stream *stream; + u32 volume[2]; + struct snd_pcm_substream *substream; + struct snd_compr_stream *cstream; + unsigned int wpos; + struct mutex mutex; +}; + +/* private data for the driver */ +struct hsw_priv_data { + /* runtime DSP */ + struct sst_hsw *hsw; + + /* page tables */ + unsigned char *pcm_pg[HSW_PCM_COUNT][2]; + + /* DAI data */ + struct hsw_pcm_data pcm[HSW_PCM_COUNT]; +}; + +static inline u32 hsw_mixer_to_ipc(unsigned int value) +{ + if (value >= ARRAY_SIZE(volume_map)) + return volume_map[0]; + else + return volume_map[value]; +} + +static inline unsigned int hsw_ipc_to_mixer(u32 value) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(volume_map); i++) { + if (volume_map[i] >= value) + return i; + } + + return i - 1; +} + +static int hsw_stream_volume_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_platform *platform = snd_kcontrol_chip(kcontrol); + struct soc_mixer_control *mc = + (struct soc_mixer_control *)kcontrol->private_value; + struct hsw_priv_data *pdata = + snd_soc_platform_get_drvdata(platform); + struct hsw_pcm_data *pcm_data = &pdata->pcm[mc->reg]; + struct sst_hsw *hsw = pdata->hsw; + u32 volume; + + mutex_lock(&pcm_data->mutex); + + if (!pcm_data->stream) { + pcm_data->volume[0] = + hsw_mixer_to_ipc(ucontrol->value.integer.value[0]); + pcm_data->volume[1] = + hsw_mixer_to_ipc(ucontrol->value.integer.value[1]); + mutex_unlock(&pcm_data->mutex); + return 0; + } + + if (ucontrol->value.integer.value[0] == + ucontrol->value.integer.value[1]) { + volume = hsw_mixer_to_ipc(ucontrol->value.integer.value[0]); + sst_hsw_stream_set_volume(hsw, pcm_data->stream, 0, 2, volume); + } else { + volume = hsw_mixer_to_ipc(ucontrol->value.integer.value[0]); + sst_hsw_stream_set_volume(hsw, pcm_data->stream, 0, 0, volume); + volume = hsw_mixer_to_ipc(ucontrol->value.integer.value[1]); + sst_hsw_stream_set_volume(hsw, pcm_data->stream, 0, 1, volume); + } + + mutex_unlock(&pcm_data->mutex); + return 0; +} + +static int hsw_stream_volume_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_platform *platform = snd_kcontrol_chip(kcontrol); + struct soc_mixer_control *mc = + (struct soc_mixer_control *)kcontrol->private_value; + struct hsw_priv_data *pdata = + snd_soc_platform_get_drvdata(platform); + struct hsw_pcm_data *pcm_data = &pdata->pcm[mc->reg]; + struct sst_hsw *hsw = pdata->hsw; + u32 volume; + + mutex_lock(&pcm_data->mutex); + + if (!pcm_data->stream) { + ucontrol->value.integer.value[0] = + hsw_ipc_to_mixer(pcm_data->volume[0]); + ucontrol->value.integer.value[1] = + hsw_ipc_to_mixer(pcm_data->volume[1]); + mutex_unlock(&pcm_data->mutex); + return 0; + } + + sst_hsw_stream_get_volume(hsw, pcm_data->stream, 0, 0, &volume); + ucontrol->value.integer.value[0] = hsw_ipc_to_mixer(volume); + sst_hsw_stream_get_volume(hsw, pcm_data->stream, 0, 1, &volume); + ucontrol->value.integer.value[1] = hsw_ipc_to_mixer(volume); + mutex_unlock(&pcm_data->mutex); + + return 0; +} + +static int hsw_volume_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_platform *platform = snd_kcontrol_chip(kcontrol); + struct hsw_priv_data *pdata = snd_soc_platform_get_drvdata(platform); + struct sst_hsw *hsw = pdata->hsw; + u32 volume; + + if (ucontrol->value.integer.value[0] == + ucontrol->value.integer.value[1]) { + + volume = hsw_mixer_to_ipc(ucontrol->value.integer.value[0]); + sst_hsw_mixer_set_volume(hsw, 0, 2, volume); + + } else { + volume = hsw_mixer_to_ipc(ucontrol->value.integer.value[0]); + sst_hsw_mixer_set_volume(hsw, 0, 0, volume); + + volume = hsw_mixer_to_ipc(ucontrol->value.integer.value[1]); + sst_hsw_mixer_set_volume(hsw, 0, 1, volume); + } + + return 0; +} + +static int hsw_volume_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_platform *platform = snd_kcontrol_chip(kcontrol); + struct hsw_priv_data *pdata = snd_soc_platform_get_drvdata(platform); + struct sst_hsw *hsw = pdata->hsw; + unsigned int volume = 0; + + sst_hsw_mixer_get_volume(hsw, 0, 0, &volume); + ucontrol->value.integer.value[0] = hsw_ipc_to_mixer(volume); + + sst_hsw_mixer_get_volume(hsw, 0, 1, &volume); + ucontrol->value.integer.value[1] = hsw_ipc_to_mixer(volume); + + return 0; +} + +/* TLV used by both global and stream volumes */ +static const DECLARE_TLV_DB_SCALE(hsw_vol_tlv, -9000, 300, 1); + +/* System Pin has no volume control */ +static const struct snd_kcontrol_new hsw_volume_controls[] = { + /* Global DSP volume */ + SOC_DOUBLE_EXT_TLV("Master Playback Volume", 0, 0, 8, + ARRAY_SIZE(volume_map) -1, 0, + hsw_volume_get, hsw_volume_put, hsw_vol_tlv), + /* Offload 0 volume */ + SOC_DOUBLE_EXT_TLV("Media0 Playback Volume", 1, 0, 8, + ARRAY_SIZE(volume_map), 0, + hsw_stream_volume_get, hsw_stream_volume_put, hsw_vol_tlv), + /* Offload 1 volume */ + SOC_DOUBLE_EXT_TLV("Media1 Playback Volume", 2, 0, 8, + ARRAY_SIZE(volume_map), 0, + hsw_stream_volume_get, hsw_stream_volume_put, hsw_vol_tlv), + /* Loopback volume */ + SOC_DOUBLE_EXT_TLV("Loopback Capture Volume", 3, 0, 8, + ARRAY_SIZE(volume_map), 0, + hsw_stream_volume_get, hsw_stream_volume_put, hsw_vol_tlv), + /* Mic Capture volume */ + SOC_DOUBLE_EXT_TLV("Mic Capture Volume", 4, 0, 8, + ARRAY_SIZE(volume_map), 0, + hsw_stream_volume_get, hsw_stream_volume_put, hsw_vol_tlv), +}; + +/* Create DMA buffer page table for DSP */ +static int create_adsp_page_table(struct hsw_priv_data *pdata, + struct snd_soc_pcm_runtime *rtd, + unsigned char *dma_area, size_t size, int pcm, int stream) +{ + int i, pages; + + if (size % PAGE_SIZE) + pages = (size / PAGE_SIZE) + 1; + else + pages = size / PAGE_SIZE; + + dev_dbg(rtd->dev, "generating page table for %p size 0x%zu pages %d\n", + dma_area, size, pages); + + for (i = 0; i < pages; i++) { + u32 idx = (((i << 2) + i)) >> 1; + u32 pfn = (virt_to_phys(dma_area + i * PAGE_SIZE)) >> PAGE_SHIFT; + u32 *pg_table; + + dev_dbg(rtd->dev, "pfn i %i idx %d pfn %x\n", i, idx, pfn); + + pg_table = (u32*)(pdata->pcm_pg[pcm][stream] + idx); + + if (i & 1) + *pg_table |= (pfn << 4); + else + *pg_table |= pfn; + } + + return 0; +} + +/* this may get called several times by oss emulation */ +static int hsw_pcm_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params) +{ + struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_pcm_runtime *runtime = substream->runtime; + struct hsw_priv_data *pdata = + snd_soc_platform_get_drvdata(rtd->platform); + struct hsw_pcm_data *pcm_data = snd_soc_pcm_get_drvdata(rtd); + struct sst_hsw *hsw = pdata->hsw; + struct sst_module *module_data; + struct sst_dsp *dsp; + enum sst_hsw_stream_type stream_type; + enum sst_hsw_stream_path_id path_id; + u32 rate, bits, map, pages, module_id; + u8 channels; + int ret; + + /* stream direction */ + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) + path_id = SST_HSW_STREAM_PATH_SSP0_OUT; + else + path_id = SST_HSW_STREAM_PATH_SSP0_IN; + + /* DSP stream type depends on DAI ID */ + switch (rtd->cpu_dai->id) { + case 0: + stream_type = SST_HSW_STREAM_TYPE_SYSTEM; + module_id = SST_HSW_MODULE_PCM_SYSTEM; + break; + case 1: + case 2: + stream_type = SST_HSW_STREAM_TYPE_RENDER; + module_id = SST_HSW_MODULE_PCM; + break; + case 3: + /* path ID needs to be OUT for loopback */ + stream_type = SST_HSW_STREAM_TYPE_LOOPBACK; + path_id = SST_HSW_STREAM_PATH_SSP0_OUT; + module_id = SST_HSW_MODULE_PCM_REFERENCE; + break; + case 4: + stream_type = SST_HSW_STREAM_TYPE_CAPTURE; + module_id = SST_HSW_MODULE_PCM_CAPTURE; + break; + default: + dev_err(rtd->dev, "error: invalid DAI ID %d\n", + rtd->cpu_dai->id); + return -EINVAL; + }; + + ret = sst_hsw_stream_format(hsw, pcm_data->stream, + path_id, stream_type, SST_HSW_STREAM_FORMAT_PCM_FORMAT); + if (ret < 0) { + dev_err(rtd->dev, "error: failed to set format %d\n", ret); + return ret; + } + + rate = params_rate(params); + ret = sst_hsw_stream_set_rate(hsw, pcm_data->stream, rate); + if (ret < 0) { + dev_err(rtd->dev, "error: could not set rate %d\n", rate); + return ret; + } + + switch (params_format(params)) { + case SNDRV_PCM_FORMAT_S16_LE: + bits = SST_HSW_DEPTH_16BIT; + sst_hsw_stream_set_valid(hsw, pcm_data->stream, 16); + break; + case SNDRV_PCM_FORMAT_S24_LE: + bits = SST_HSW_DEPTH_24BIT; + sst_hsw_stream_set_valid(hsw, pcm_data->stream, 32); + break; + default: + dev_err(rtd->dev, "error: invalid format %d\n", + params_format(params)); + return -EINVAL; + } + + ret = sst_hsw_stream_set_bits(hsw, pcm_data->stream, bits); + if (ret < 0) { + dev_err(rtd->dev, "error: could not set bits %d\n", bits); + return ret; + } + + /* we only support stereo atm */ + channels = params_channels(params); + if (channels != 2) { + dev_err(rtd->dev, "error: invalid channels %d\n", channels); + return -EINVAL; + } + + map = create_channel_map(SST_HSW_CHANNEL_CONFIG_STEREO); + sst_hsw_stream_set_map_config(hsw, pcm_data->stream, + map, SST_HSW_CHANNEL_CONFIG_STEREO); + + ret = sst_hsw_stream_set_channels(hsw, pcm_data->stream, channels); + if (ret < 0) { + dev_err(rtd->dev, "error: could not set channels %d\n", + channels); + return ret; + } + + ret = snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(params)); + if (ret < 0) { + dev_err(rtd->dev, "error: could not allocate %d bytes for PCM %d\n", + params_buffer_bytes(params), ret); + return ret; + } + + ret = create_adsp_page_table(pdata, rtd, runtime->dma_area, + runtime->dma_bytes, rtd->cpu_dai->id, substream->stream); + if (ret < 0) + return ret; + + sst_hsw_stream_set_style(hsw, pcm_data->stream, + SST_HSW_INTERLEAVING_PER_CHANNEL); + + if (runtime->dma_bytes % PAGE_SIZE) + pages = (runtime->dma_bytes / PAGE_SIZE) + 1; + else + pages = runtime->dma_bytes / PAGE_SIZE; + + ret = sst_hsw_stream_buffer(hsw, pcm_data->stream, + virt_to_phys(pdata->pcm_pg[rtd->cpu_dai->id][substream->stream]), + pages, runtime->dma_bytes, 0, + (u32)(virt_to_phys(runtime->dma_area) >> PAGE_SHIFT)); + if (ret < 0) { + dev_err(rtd->dev, "error: failed to set DMA buffer %d\n", ret); + return ret; + } + + dsp = sst_hsw_get_dsp(hsw); + + module_data = sst_module_get_from_id(dsp, module_id); + if (module_data == NULL) { + dev_err(rtd->dev, "error: failed to get module config\n"); + return -EINVAL; + } + + /* we use hardcoded memory offsets atm, will be updated for new FW */ + if (stream_type == SST_HSW_STREAM_TYPE_CAPTURE) { + sst_hsw_stream_set_module_info(hsw, pcm_data->stream, + SST_HSW_MODULE_PCM_CAPTURE, module_data->entry); + sst_hsw_stream_set_pmemory_info(hsw, pcm_data->stream, + 0x449400, 0x4000); + sst_hsw_stream_set_smemory_info(hsw, pcm_data->stream, + 0x400000, 0); + } else { /* stream_type == SST_HSW_STREAM_TYPE_SYSTEM */ + sst_hsw_stream_set_module_info(hsw, pcm_data->stream, + SST_HSW_MODULE_PCM_SYSTEM, module_data->entry); + + sst_hsw_stream_set_pmemory_info(hsw, pcm_data->stream, + module_data->offset, module_data->size); + sst_hsw_stream_set_pmemory_info(hsw, pcm_data->stream, + 0x44d400, 0x3800); + + sst_hsw_stream_set_smemory_info(hsw, pcm_data->stream, + module_data->offset, module_data->size); + sst_hsw_stream_set_smemory_info(hsw, pcm_data->stream, + 0x400000, 0); + } + + ret = sst_hsw_stream_commit(hsw, pcm_data->stream); + if (ret < 0) { + dev_err(rtd->dev, "error: failed to commit stream %d\n", ret); + return ret; + } + + ret = sst_hsw_stream_pause(hsw, pcm_data->stream, 1); + if (ret < 0) + dev_err(rtd->dev, "error: failed to pause %d\n", ret); + + return 0; +} + +static int hsw_pcm_hw_free(struct snd_pcm_substream *substream) +{ + snd_pcm_lib_free_pages(substream); + return 0; +} + +static int hsw_pcm_trigger(struct snd_pcm_substream *substream, int cmd) +{ + struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct hsw_priv_data *pdata = + snd_soc_platform_get_drvdata(rtd->platform); + struct hsw_pcm_data *pcm_data = snd_soc_pcm_get_drvdata(rtd); + struct sst_hsw *hsw = pdata->hsw; + + switch (cmd) { + case SNDRV_PCM_TRIGGER_START: + case SNDRV_PCM_TRIGGER_RESUME: + case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: + sst_hsw_stream_resume(hsw, pcm_data->stream, 0); + break; + case SNDRV_PCM_TRIGGER_STOP: + case SNDRV_PCM_TRIGGER_SUSPEND: + case SNDRV_PCM_TRIGGER_PAUSE_PUSH: + sst_hsw_stream_pause(hsw, pcm_data->stream, 0); + break; + default: + break; + } + + return 0; +} + +static u32 hsw_notify_pointer(struct sst_hsw_stream *stream, void *data) +{ + struct hsw_pcm_data *pcm_data = data; + struct snd_pcm_substream *substream = pcm_data->substream; + struct snd_pcm_runtime *runtime = substream->runtime; + struct snd_soc_pcm_runtime *rtd = substream->private_data; + u32 pos; + + pos = frames_to_bytes(runtime, + (runtime->control->appl_ptr % runtime->buffer_size)); + + dev_dbg(rtd->dev, "PCM: App pointer %d bytes\n", pos); + + /* let alsa know we have play a period */ + snd_pcm_period_elapsed(substream); + return pos; +} + +static snd_pcm_uframes_t hsw_pcm_pointer(struct snd_pcm_substream *substream) +{ + struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_pcm_runtime *runtime = substream->runtime; + struct hsw_priv_data *pdata = + snd_soc_platform_get_drvdata(rtd->platform); + struct hsw_pcm_data *pcm_data = snd_soc_pcm_get_drvdata(rtd); + struct sst_hsw *hsw = pdata->hsw; + snd_pcm_uframes_t offset; + + offset = bytes_to_frames(runtime, + sst_hsw_get_dsp_position(hsw, pcm_data->stream)); + + dev_dbg(rtd->dev, "PCM: DMA pointer %zu bytes\n", + frames_to_bytes(runtime, (u32)offset)); + return offset; +} + +static int hsw_pcm_open(struct snd_pcm_substream *substream) +{ + struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct hsw_priv_data *pdata = + snd_soc_platform_get_drvdata(rtd->platform); + struct hsw_pcm_data *pcm_data; + struct sst_hsw *hsw = pdata->hsw; + + pcm_data = &pdata->pcm[rtd->cpu_dai->id]; + + mutex_lock(&pcm_data->mutex); + + snd_soc_pcm_set_drvdata(rtd, pcm_data); + pcm_data->substream = substream; + + snd_soc_set_runtime_hwparams(substream, &hsw_pcm_hardware); + + pcm_data->stream = sst_hsw_stream_new(hsw, rtd->cpu_dai->id, + hsw_notify_pointer, pcm_data); + if (pcm_data->stream == NULL) { + dev_err(rtd->dev, "error: failed to create stream\n"); + mutex_unlock(&pcm_data->mutex); + return -EINVAL; + } + + /* Set previous saved volume */ + sst_hsw_stream_set_volume(hsw, pcm_data->stream, 0, + 0, pcm_data->volume[0]); + sst_hsw_stream_set_volume(hsw, pcm_data->stream, 0, + 1, pcm_data->volume[1]); + + mutex_unlock(&pcm_data->mutex); + return 0; +} + +static int hsw_pcm_close(struct snd_pcm_substream *substream) +{ + struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct hsw_priv_data *pdata = + snd_soc_platform_get_drvdata(rtd->platform); + struct hsw_pcm_data *pcm_data = snd_soc_pcm_get_drvdata(rtd); + struct sst_hsw *hsw = pdata->hsw; + int ret; + + mutex_lock(&pcm_data->mutex); + ret = sst_hsw_stream_reset(hsw, pcm_data->stream); + if (ret < 0) { + dev_dbg(rtd->dev, "error: reset stream failed %d\n", ret); + goto out; + } + + ret = sst_hsw_stream_free(hsw, pcm_data->stream); + if (ret < 0) { + dev_dbg(rtd->dev, "error: free stream failed %d\n", ret); + goto out; + } + pcm_data->stream = NULL; + +out: + mutex_unlock(&pcm_data->mutex); + return ret; +} + +static struct snd_pcm_ops hsw_pcm_ops = { + .open = hsw_pcm_open, + .close = hsw_pcm_close, + .ioctl = snd_pcm_lib_ioctl, + .hw_params = hsw_pcm_hw_params, + .hw_free = hsw_pcm_hw_free, + .trigger = hsw_pcm_trigger, + .pointer = hsw_pcm_pointer, + .mmap = snd_pcm_lib_default_mmap, +}; + +static void hsw_pcm_free(struct snd_pcm *pcm) +{ + snd_pcm_lib_preallocate_free_for_all(pcm); +} + +static int hsw_pcm_new(struct snd_soc_pcm_runtime *rtd) +{ + struct snd_pcm *pcm = rtd->pcm; + int ret = 0; + + ret = dma_coerce_mask_and_coherent(rtd->card->dev, DMA_BIT_MASK(32)); + if (ret) + return ret; + + if (pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream || + pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream) { + ret = snd_pcm_lib_preallocate_pages_for_all(pcm, + SNDRV_DMA_TYPE_DEV, + rtd->card->dev, + hsw_pcm_hardware.buffer_bytes_max, + hsw_pcm_hardware.buffer_bytes_max); + if (ret) { + dev_err(rtd->dev, "dma buffer allocation failed %d\n", + ret); + return ret; + } + } + + return ret; +} + +#define HSW_FORMATS \ + (SNDRV_PCM_FMTBIT_S20_3LE | SNDRV_PCM_FMTBIT_S16_LE |\ + SNDRV_PCM_FMTBIT_S32_LE) + +static struct snd_soc_dai_driver hsw_dais[] = { + { + .name = "System Pin", + .playback = { + .stream_name = "System Playback", + .channels_min = 2, + .channels_max = 2, + .rates = SNDRV_PCM_RATE_48000, + .formats = SNDRV_PCM_FMTBIT_S16_LE, + }, + }, + { + /* PCM */ + .name = "Offload0 Pin", + .playback = { + .stream_name = "Offload0 Playback", + .channels_min = 2, + .channels_max = 2, + .rates = SNDRV_PCM_RATE_8000_192000, + .formats = HSW_FORMATS, + }, + }, + { + /* PCM */ + .name = "Offload1 Pin", + .playback = { + .stream_name = "Offload1 Playback", + .channels_min = 2, + .channels_max = 2, + .rates = SNDRV_PCM_RATE_8000_192000, + .formats = HSW_FORMATS, + }, + }, + { + .name = "Loopback Pin", + .capture = { + .stream_name = "Loopback Capture", + .channels_min = 2, + .channels_max = 2, + .rates = SNDRV_PCM_RATE_8000_192000, + .formats = HSW_FORMATS, + }, + }, + { + .name = "Capture Pin", + .capture = { + .stream_name = "Analog Capture", + .channels_min = 2, + .channels_max = 2, + .rates = SNDRV_PCM_RATE_8000_192000, + .formats = HSW_FORMATS, + }, + }, +}; + +static const struct snd_soc_dapm_widget widgets[] = { + + /* Backend DAIs */ + SND_SOC_DAPM_AIF_IN("SSP0 CODEC IN", NULL, 0, SND_SOC_NOPM, 0, 0), + SND_SOC_DAPM_AIF_OUT("SSP0 CODEC OUT", NULL, 0, SND_SOC_NOPM, 0, 0), + SND_SOC_DAPM_AIF_IN("SSP1 BT IN", NULL, 0, SND_SOC_NOPM, 0, 0), + SND_SOC_DAPM_AIF_OUT("SSP1 BT OUT", NULL, 0, SND_SOC_NOPM, 0, 0), + + /* Global Playback Mixer */ + SND_SOC_DAPM_MIXER("Playback VMixer", SND_SOC_NOPM, 0, 0, NULL, 0), +}; + +static const struct snd_soc_dapm_route graph[] = { + + /* Playback Mixer */ + {"Playback VMixer", NULL, "System Playback"}, + {"Playback VMixer", NULL, "Offload0 Playback"}, + {"Playback VMixer", NULL, "Offload1 Playback"}, + + {"SSP0 CODEC OUT", NULL, "Playback VMixer"}, + + {"Analog Capture", NULL, "SSP0 CODEC IN"}, +}; + +static int hsw_pcm_probe(struct snd_soc_platform *platform) +{ + struct sst_pdata *pdata = dev_get_platdata(platform->dev); + struct hsw_priv_data *priv_data; + int i; + + if (!pdata) + return -ENODEV; + + priv_data = devm_kzalloc(platform->dev, sizeof(*priv_data), GFP_KERNEL); + priv_data->hsw = pdata->dsp; + snd_soc_platform_set_drvdata(platform, priv_data); + + /* allocate DSP buffer page tables */ + for (i = 0; i < ARRAY_SIZE(hsw_dais); i++) { + + mutex_init(&priv_data->pcm[i].mutex); + + /* playback */ + if (hsw_dais[i].playback.channels_min) { + priv_data->pcm_pg[i][0] = kzalloc(PAGE_SIZE, GFP_DMA); + if (priv_data->pcm_pg[i][0] == NULL) + goto err; + } + + /* capture */ + if (hsw_dais[i].capture.channels_min) { + priv_data->pcm_pg[i][1] = kzalloc(PAGE_SIZE, GFP_DMA); + if (priv_data->pcm_pg[i][1] == NULL) + goto err; + } + } + + return 0; + +err: + for (;i >= 0; i--) { + if (hsw_dais[i].playback.channels_min) + kfree(priv_data->pcm_pg[i][0]); + if (hsw_dais[i].capture.channels_min) + kfree(priv_data->pcm_pg[i][1]); + } + return -ENOMEM; +} + +static int hsw_pcm_remove(struct snd_soc_platform *platform) +{ + struct hsw_priv_data *priv_data = + snd_soc_platform_get_drvdata(platform); + int i; + + for (i = 0; i < ARRAY_SIZE(hsw_dais); i++) { + if (hsw_dais[i].playback.channels_min) + kfree(priv_data->pcm_pg[i][0]); + if (hsw_dais[i].capture.channels_min) + kfree(priv_data->pcm_pg[i][1]); + } + + return 0; +} + +static struct snd_soc_platform_driver hsw_soc_platform = { + .probe = hsw_pcm_probe, + .remove = hsw_pcm_remove, + .ops = &hsw_pcm_ops, + .pcm_new = hsw_pcm_new, + .pcm_free = hsw_pcm_free, + .controls = hsw_volume_controls, + .num_controls = ARRAY_SIZE(hsw_volume_controls), + .dapm_widgets = widgets, + .num_dapm_widgets = ARRAY_SIZE(widgets), + .dapm_routes = graph, + .num_dapm_routes = ARRAY_SIZE(graph), +}; + +static const struct snd_soc_component_driver hsw_dai_component = { + .name = "haswell-dai", +}; + +static int hsw_pcm_dev_probe(struct platform_device *pdev) +{ + struct sst_pdata *sst_pdata = dev_get_platdata(&pdev->dev); + int ret; + + ret = sst_hsw_dsp_init(&pdev->dev, sst_pdata); + if (ret < 0) + return -ENODEV; + + ret = snd_soc_register_platform(&pdev->dev, &hsw_soc_platform); + if (ret < 0) + goto err_plat; + + ret = snd_soc_register_component(&pdev->dev, &hsw_dai_component, + hsw_dais, ARRAY_SIZE(hsw_dais)); + if (ret < 0) + goto err_comp; + + return 0; + +err_comp: + snd_soc_unregister_platform(&pdev->dev); +err_plat: + sst_hsw_dsp_free(&pdev->dev, sst_pdata); + return 0; +} + +static int hsw_pcm_dev_remove(struct platform_device *pdev) +{ + struct sst_pdata *sst_pdata = dev_get_platdata(&pdev->dev); + + snd_soc_unregister_platform(&pdev->dev); + snd_soc_unregister_component(&pdev->dev); + sst_hsw_dsp_free(&pdev->dev, sst_pdata); + + return 0; +} + +static struct platform_driver hsw_pcm_driver = { + .driver = { + .name = "haswell-pcm-audio", + .owner = THIS_MODULE, + }, + + .probe = hsw_pcm_dev_probe, + .remove = hsw_pcm_dev_remove, +}; +module_platform_driver(hsw_pcm_driver); + +MODULE_AUTHOR("Liam Girdwood, Xingchao Wang"); +MODULE_DESCRIPTION("Haswell/Lynxpoint + Broadwell/Wildcatpoint PCM"); +MODULE_LICENSE("GPL v2"); +MODULE_ALIAS("platform:haswell-pcm-audio"); diff --git a/sound/soc/intel/sst_dsp.h b/sound/soc/intel/sst-mfld-dsp.h index 0fce1de284f..3b63edc04b7 100644 --- a/sound/soc/intel/sst_dsp.h +++ b/sound/soc/intel/sst-mfld-dsp.h @@ -1,7 +1,7 @@ -#ifndef __SST_DSP_H__ -#define __SST_DSP_H__ +#ifndef __SST_MFLD_DSP_H__ +#define __SST_MFLD_DSP_H__ /* - * sst_dsp.h - Intel SST Driver for audio engine + * sst_mfld_dsp.h - Intel SST Driver for audio engine * * Copyright (C) 2008-12 Intel Corporation * Authors: Vinod Koul <vinod.koul@linux.intel.com> @@ -131,4 +131,4 @@ struct snd_sst_params { struct snd_sst_alloc_params_ext aparams; }; -#endif /* __SST_DSP_H__ */ +#endif /* __SST_MFLD_DSP_H__ */ diff --git a/sound/soc/intel/sst_platform.c b/sound/soc/intel/sst-mfld-platform.c index f465a818086..840306c2ef1 100644 --- a/sound/soc/intel/sst_platform.c +++ b/sound/soc/intel/sst-mfld-platform.c @@ -1,5 +1,5 @@ /* - * sst_platform.c - Intel MID Platform driver + * sst_mfld_platform.c - Intel MID Platform driver * * Copyright (C) 2010-2013 Intel Corp * Author: Vinod Koul <vinod.koul@intel.com> @@ -33,7 +33,7 @@ #include <sound/pcm_params.h> #include <sound/soc.h> #include <sound/compress_driver.h> -#include "sst_platform.h" +#include "sst-mfld-platform.h" static struct sst_device *sst; static DEFINE_MUTEX(sst_lock); @@ -709,7 +709,7 @@ static int sst_platform_remove(struct platform_device *pdev) static struct platform_driver sst_platform_driver = { .driver = { - .name = "sst-platform", + .name = "sst-mfld-platform", .owner = THIS_MODULE, }, .probe = sst_platform_probe, @@ -722,4 +722,4 @@ MODULE_DESCRIPTION("ASoC Intel(R) MID Platform driver"); MODULE_AUTHOR("Vinod Koul <vinod.koul@intel.com>"); MODULE_AUTHOR("Harsha Priya <priya.harsha@intel.com>"); MODULE_LICENSE("GPL v2"); -MODULE_ALIAS("platform:sst-platform"); +MODULE_ALIAS("platform:sst-mfld-platform"); diff --git a/sound/soc/intel/sst_platform.h b/sound/soc/intel/sst-mfld-platform.h index bee64fb7d2e..0c4e2ddcecb 100644 --- a/sound/soc/intel/sst_platform.h +++ b/sound/soc/intel/sst-mfld-platform.h @@ -1,5 +1,5 @@ /* - * sst_platform.h - Intel MID Platform driver header file + * sst_mfld_platform.h - Intel MID Platform driver header file * * Copyright (C) 2010 Intel Corp * Author: Vinod Koul <vinod.koul@intel.com> @@ -27,7 +27,7 @@ #ifndef __SST_PLATFORMDRV_H__ #define __SST_PLATFORMDRV_H__ -#include "sst_dsp.h" +#include "sst-mfld-dsp.h" #define SST_MONO 1 #define SST_STEREO 2 diff --git a/sound/soc/kirkwood/Kconfig b/sound/soc/kirkwood/Kconfig index 78ed4a42ad2..49f8437665d 100644 --- a/sound/soc/kirkwood/Kconfig +++ b/sound/soc/kirkwood/Kconfig @@ -1,11 +1,20 @@ config SND_KIRKWOOD_SOC tristate "SoC Audio for the Marvell Kirkwood and Dove chips" - depends on ARCH_KIRKWOOD || ARCH_DOVE || COMPILE_TEST + depends on ARCH_KIRKWOOD || ARCH_DOVE || ARCH_MVEBU || COMPILE_TEST help Say Y or M if you want to add support for codecs attached to the Kirkwood I2S interface. You will also need to select the audio interfaces to support below. +config SND_KIRKWOOD_SOC_ARMADA370_DB + tristate "SoC Audio support for Armada 370 DB" + depends on SND_KIRKWOOD_SOC && (ARCH_MVEBU || COMPILE_TEST) && I2C + select SND_SOC_CS42L51 + select SND_SOC_SPDIF + help + Say Y if you want to add support for SoC audio on + the Armada 370 Development Board. + config SND_KIRKWOOD_SOC_OPENRD tristate "SoC Audio support for Kirkwood Openrd Client" depends on SND_KIRKWOOD_SOC && (MACH_OPENRD_CLIENT || MACH_OPENRD_ULTIMATE || COMPILE_TEST) diff --git a/sound/soc/kirkwood/Makefile b/sound/soc/kirkwood/Makefile index 9e781385cb8..7c1d8fe09e6 100644 --- a/sound/soc/kirkwood/Makefile +++ b/sound/soc/kirkwood/Makefile @@ -4,6 +4,8 @@ obj-$(CONFIG_SND_KIRKWOOD_SOC) += snd-soc-kirkwood.o snd-soc-openrd-objs := kirkwood-openrd.o snd-soc-t5325-objs := kirkwood-t5325.o +snd-soc-armada-370-db-objs := armada-370-db.o +obj-$(CONFIG_SND_KIRKWOOD_SOC_ARMADA370_DB) += snd-soc-armada-370-db.o obj-$(CONFIG_SND_KIRKWOOD_SOC_OPENRD) += snd-soc-openrd.o obj-$(CONFIG_SND_KIRKWOOD_SOC_T5325) += snd-soc-t5325.o diff --git a/sound/soc/kirkwood/armada-370-db.c b/sound/soc/kirkwood/armada-370-db.c new file mode 100644 index 00000000000..c4433384925 --- /dev/null +++ b/sound/soc/kirkwood/armada-370-db.c @@ -0,0 +1,148 @@ +/* + * Copyright (C) 2014 Marvell + * + * Thomas Petazzoni <thomas.petazzoni@free-electrons.com> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + */ + +#include <linux/module.h> +#include <linux/moduleparam.h> +#include <linux/interrupt.h> +#include <linux/platform_device.h> +#include <linux/slab.h> +#include <sound/soc.h> +#include <linux/of.h> +#include <linux/platform_data/asoc-kirkwood.h> +#include "../codecs/cs42l51.h" + +static int a370db_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params) +{ + struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_dai *codec_dai = rtd->codec_dai; + unsigned int freq; + + switch (params_rate(params)) { + default: + case 44100: + freq = 11289600; + break; + case 48000: + freq = 12288000; + break; + case 96000: + freq = 24576000; + break; + } + + return snd_soc_dai_set_sysclk(codec_dai, 0, freq, SND_SOC_CLOCK_IN); +} + +static struct snd_soc_ops a370db_ops = { + .hw_params = a370db_hw_params, +}; + +static const struct snd_soc_dapm_widget a370db_dapm_widgets[] = { + SND_SOC_DAPM_HP("Out Jack", NULL), + SND_SOC_DAPM_LINE("In Jack", NULL), +}; + +static const struct snd_soc_dapm_route a370db_route[] = { + { "Out Jack", NULL, "HPL" }, + { "Out Jack", NULL, "HPR" }, + { "AIN1L", NULL, "In Jack" }, + { "AIN1L", NULL, "In Jack" }, +}; + +static struct snd_soc_dai_link a370db_dai[] = { +{ + .name = "CS42L51", + .stream_name = "analog", + .cpu_dai_name = "i2s", + .codec_dai_name = "cs42l51-hifi", + .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_CBS_CFS, + .ops = &a370db_ops, +}, +{ + .name = "S/PDIF out", + .stream_name = "spdif-out", + .cpu_dai_name = "spdif", + .codec_dai_name = "dit-hifi", + .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_CBS_CFS, +}, +{ + .name = "S/PDIF in", + .stream_name = "spdif-in", + .cpu_dai_name = "spdif", + .codec_dai_name = "dir-hifi", + .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_CBS_CFS, +}, +}; + +static struct snd_soc_card a370db = { + .name = "a370db", + .owner = THIS_MODULE, + .dai_link = a370db_dai, + .num_links = ARRAY_SIZE(a370db_dai), + .dapm_widgets = a370db_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(a370db_dapm_widgets), + .dapm_routes = a370db_route, + .num_dapm_routes = ARRAY_SIZE(a370db_route), +}; + +static int a370db_probe(struct platform_device *pdev) +{ + struct snd_soc_card *card = &a370db; + + card->dev = &pdev->dev; + + a370db_dai[0].cpu_of_node = + of_parse_phandle(pdev->dev.of_node, + "marvell,audio-controller", 0); + a370db_dai[0].platform_of_node = a370db_dai[0].cpu_of_node; + + a370db_dai[0].codec_of_node = + of_parse_phandle(pdev->dev.of_node, + "marvell,audio-codec", 0); + + a370db_dai[1].cpu_of_node = a370db_dai[0].cpu_of_node; + a370db_dai[1].platform_of_node = a370db_dai[0].cpu_of_node; + + a370db_dai[1].codec_of_node = + of_parse_phandle(pdev->dev.of_node, + "marvell,audio-codec", 1); + + a370db_dai[2].cpu_of_node = a370db_dai[0].cpu_of_node; + a370db_dai[2].platform_of_node = a370db_dai[0].cpu_of_node; + + a370db_dai[2].codec_of_node = + of_parse_phandle(pdev->dev.of_node, + "marvell,audio-codec", 2); + + return devm_snd_soc_register_card(card->dev, card); +} + +static const struct of_device_id a370db_dt_ids[] = { + { .compatible = "marvell,a370db-audio" }, + { }, +}; + +static struct platform_driver a370db_driver = { + .driver = { + .name = "a370db-audio", + .owner = THIS_MODULE, + .of_match_table = of_match_ptr(a370db_dt_ids), + }, + .probe = a370db_probe, +}; + +module_platform_driver(a370db_driver); + +MODULE_AUTHOR("Thomas Petazzoni <thomas.petazzoni@free-electrons.com>"); +MODULE_DESCRIPTION("ALSA SoC a370db audio client"); +MODULE_LICENSE("GPL"); +MODULE_ALIAS("platform:a370db-audio"); diff --git a/sound/soc/kirkwood/kirkwood-i2s.c b/sound/soc/kirkwood/kirkwood-i2s.c index 3920a5e8125..9f842222e79 100644 --- a/sound/soc/kirkwood/kirkwood-i2s.c +++ b/sound/soc/kirkwood/kirkwood-i2s.c @@ -633,6 +633,7 @@ static int kirkwood_i2s_dev_remove(struct platform_device *pdev) static struct of_device_id mvebu_audio_of_match[] = { { .compatible = "marvell,kirkwood-audio" }, { .compatible = "marvell,dove-audio" }, + { .compatible = "marvell,armada370-audio" }, { } }; MODULE_DEVICE_TABLE(of, mvebu_audio_of_match); diff --git a/sound/soc/omap/Kconfig b/sound/soc/omap/Kconfig index 22ad9c5654b..e00659351a4 100644 --- a/sound/soc/omap/Kconfig +++ b/sound/soc/omap/Kconfig @@ -58,7 +58,7 @@ config SND_OMAP_SOC_OSK5912 tristate "SoC Audio support for omap osk5912" depends on SND_OMAP_SOC && MACH_OMAP_OSK && I2C select SND_OMAP_SOC_MCBSP - select SND_SOC_TLV320AIC23 + select SND_SOC_TLV320AIC23_I2C help Say Y if you want to add support for SoC audio on osk5912. @@ -66,7 +66,7 @@ config SND_OMAP_SOC_AM3517EVM tristate "SoC Audio support for OMAP3517 / AM3517 EVM" depends on SND_OMAP_SOC && MACH_OMAP3517EVM && I2C select SND_OMAP_SOC_MCBSP - select SND_SOC_TLV320AIC23 + select SND_SOC_TLV320AIC23_I2C help Say Y if you want to add support for SoC audio on the OMAP3517 / AM3517 EVM. diff --git a/sound/soc/omap/ams-delta.c b/sound/soc/omap/ams-delta.c index 629446482a9..56a5219c0a0 100644 --- a/sound/soc/omap/ams-delta.c +++ b/sound/soc/omap/ams-delta.c @@ -103,60 +103,62 @@ static int ams_delta_set_audio_mode(struct snd_kcontrol *kcontrol, if (!codec->hw_write) return -EUNATCH; - if (ucontrol->value.enumerated.item[0] >= control->max) + if (ucontrol->value.enumerated.item[0] >= control->items) return -EINVAL; - mutex_lock(&codec->mutex); + snd_soc_dapm_mutex_lock(dapm); /* Translate selection to bitmap */ pins = ams_delta_audio_mode_pins[ucontrol->value.enumerated.item[0]]; /* Setup pins after corresponding bits if changed */ pin = !!(pins & (1 << AMS_DELTA_MOUTHPIECE)); + if (pin != snd_soc_dapm_get_pin_status(dapm, "Mouthpiece")) { changed = 1; if (pin) - snd_soc_dapm_enable_pin(dapm, "Mouthpiece"); + snd_soc_dapm_enable_pin_unlocked(dapm, "Mouthpiece"); else - snd_soc_dapm_disable_pin(dapm, "Mouthpiece"); + snd_soc_dapm_disable_pin_unlocked(dapm, "Mouthpiece"); } pin = !!(pins & (1 << AMS_DELTA_EARPIECE)); if (pin != snd_soc_dapm_get_pin_status(dapm, "Earpiece")) { changed = 1; if (pin) - snd_soc_dapm_enable_pin(dapm, "Earpiece"); + snd_soc_dapm_enable_pin_unlocked(dapm, "Earpiece"); else - snd_soc_dapm_disable_pin(dapm, "Earpiece"); + snd_soc_dapm_disable_pin_unlocked(dapm, "Earpiece"); } pin = !!(pins & (1 << AMS_DELTA_MICROPHONE)); if (pin != snd_soc_dapm_get_pin_status(dapm, "Microphone")) { changed = 1; if (pin) - snd_soc_dapm_enable_pin(dapm, "Microphone"); + snd_soc_dapm_enable_pin_unlocked(dapm, "Microphone"); else - snd_soc_dapm_disable_pin(dapm, "Microphone"); + snd_soc_dapm_disable_pin_unlocked(dapm, "Microphone"); } pin = !!(pins & (1 << AMS_DELTA_SPEAKER)); if (pin != snd_soc_dapm_get_pin_status(dapm, "Speaker")) { changed = 1; if (pin) - snd_soc_dapm_enable_pin(dapm, "Speaker"); + snd_soc_dapm_enable_pin_unlocked(dapm, "Speaker"); else - snd_soc_dapm_disable_pin(dapm, "Speaker"); + snd_soc_dapm_disable_pin_unlocked(dapm, "Speaker"); } pin = !!(pins & (1 << AMS_DELTA_AGC)); if (pin != ams_delta_audio_agc) { ams_delta_audio_agc = pin; changed = 1; if (pin) - snd_soc_dapm_enable_pin(dapm, "AGCIN"); + snd_soc_dapm_enable_pin_unlocked(dapm, "AGCIN"); else - snd_soc_dapm_disable_pin(dapm, "AGCIN"); + snd_soc_dapm_disable_pin_unlocked(dapm, "AGCIN"); } + if (changed) - snd_soc_dapm_sync(dapm); + snd_soc_dapm_sync_unlocked(dapm); - mutex_unlock(&codec->mutex); + snd_soc_dapm_mutex_unlock(dapm); return changed; } @@ -194,13 +196,11 @@ static int ams_delta_get_audio_mode(struct snd_kcontrol *kcontrol, return 0; } -static const struct soc_enum ams_delta_audio_enum[] = { - SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(ams_delta_audio_mode), - ams_delta_audio_mode), -}; +static const SOC_ENUM_SINGLE_EXT_DECL(ams_delta_audio_enum, + ams_delta_audio_mode); static const struct snd_kcontrol_new ams_delta_audio_controls[] = { - SOC_ENUM_EXT("Audio Mode", ams_delta_audio_enum[0], + SOC_ENUM_EXT("Audio Mode", ams_delta_audio_enum, ams_delta_get_audio_mode, ams_delta_set_audio_mode), }; @@ -315,12 +315,17 @@ static void cx81801_close(struct tty_struct *tty) v253_ops.close(tty); /* Revert back to default audio input/output constellation */ - snd_soc_dapm_disable_pin(dapm, "Mouthpiece"); - snd_soc_dapm_enable_pin(dapm, "Earpiece"); - snd_soc_dapm_enable_pin(dapm, "Microphone"); - snd_soc_dapm_disable_pin(dapm, "Speaker"); - snd_soc_dapm_disable_pin(dapm, "AGCIN"); - snd_soc_dapm_sync(dapm); + snd_soc_dapm_mutex_lock(dapm); + + snd_soc_dapm_disable_pin_unlocked(dapm, "Mouthpiece"); + snd_soc_dapm_enable_pin_unlocked(dapm, "Earpiece"); + snd_soc_dapm_enable_pin_unlocked(dapm, "Microphone"); + snd_soc_dapm_disable_pin_unlocked(dapm, "Speaker"); + snd_soc_dapm_disable_pin_unlocked(dapm, "AGCIN"); + + snd_soc_dapm_sync_unlocked(dapm); + + snd_soc_dapm_mutex_unlock(dapm); } /* Line discipline .hangup() */ diff --git a/sound/soc/omap/n810.c b/sound/soc/omap/n810.c index d163e18d85d..fd4d9c809e5 100644 --- a/sound/soc/omap/n810.c +++ b/sound/soc/omap/n810.c @@ -68,26 +68,30 @@ static void n810_ext_control(struct snd_soc_dapm_context *dapm) break; } + snd_soc_dapm_mutex_lock(dapm); + if (n810_spk_func) - snd_soc_dapm_enable_pin(dapm, "Ext Spk"); + snd_soc_dapm_enable_pin_unlocked(dapm, "Ext Spk"); else - snd_soc_dapm_disable_pin(dapm, "Ext Spk"); + snd_soc_dapm_disable_pin_unlocked(dapm, "Ext Spk"); if (hp) - snd_soc_dapm_enable_pin(dapm, "Headphone Jack"); + snd_soc_dapm_enable_pin_unlocked(dapm, "Headphone Jack"); else - snd_soc_dapm_disable_pin(dapm, "Headphone Jack"); + snd_soc_dapm_disable_pin_unlocked(dapm, "Headphone Jack"); if (line1l) - snd_soc_dapm_enable_pin(dapm, "LINE1L"); + snd_soc_dapm_enable_pin_unlocked(dapm, "LINE1L"); else - snd_soc_dapm_disable_pin(dapm, "LINE1L"); + snd_soc_dapm_disable_pin_unlocked(dapm, "LINE1L"); if (n810_dmic_func) - snd_soc_dapm_enable_pin(dapm, "DMic"); + snd_soc_dapm_enable_pin_unlocked(dapm, "DMic"); else - snd_soc_dapm_disable_pin(dapm, "DMic"); + snd_soc_dapm_disable_pin_unlocked(dapm, "DMic"); + + snd_soc_dapm_sync_unlocked(dapm); - snd_soc_dapm_sync(dapm); + snd_soc_dapm_mutex_unlock(dapm); } static int n810_startup(struct snd_pcm_substream *substream) diff --git a/sound/soc/omap/omap-abe-twl6040.c b/sound/soc/omap/omap-abe-twl6040.c index ebb13906b3a..024dafc3e29 100644 --- a/sound/soc/omap/omap-abe-twl6040.c +++ b/sound/soc/omap/omap-abe-twl6040.c @@ -203,8 +203,7 @@ static const struct snd_soc_dapm_route dmic_audio_map[] = { static int omap_abe_dmic_init(struct snd_soc_pcm_runtime *rtd) { - struct snd_soc_codec *codec = rtd->codec; - struct snd_soc_dapm_context *dapm = &codec->dapm; + struct snd_soc_dapm_context *dapm = &rtd->card->dapm; return snd_soc_dapm_add_routes(dapm, dmic_audio_map, ARRAY_SIZE(dmic_audio_map)); diff --git a/sound/soc/omap/rx51.c b/sound/soc/omap/rx51.c index 611179c3bca..7fb3d4b1037 100644 --- a/sound/soc/omap/rx51.c +++ b/sound/soc/omap/rx51.c @@ -74,26 +74,30 @@ static void rx51_ext_control(struct snd_soc_dapm_context *dapm) break; } + snd_soc_dapm_mutex_lock(dapm); + if (rx51_spk_func) - snd_soc_dapm_enable_pin(dapm, "Ext Spk"); + snd_soc_dapm_enable_pin_unlocked(dapm, "Ext Spk"); else - snd_soc_dapm_disable_pin(dapm, "Ext Spk"); + snd_soc_dapm_disable_pin_unlocked(dapm, "Ext Spk"); if (rx51_dmic_func) - snd_soc_dapm_enable_pin(dapm, "DMic"); + snd_soc_dapm_enable_pin_unlocked(dapm, "DMic"); else - snd_soc_dapm_disable_pin(dapm, "DMic"); + snd_soc_dapm_disable_pin_unlocked(dapm, "DMic"); if (hp) - snd_soc_dapm_enable_pin(dapm, "Headphone Jack"); + snd_soc_dapm_enable_pin_unlocked(dapm, "Headphone Jack"); else - snd_soc_dapm_disable_pin(dapm, "Headphone Jack"); + snd_soc_dapm_disable_pin_unlocked(dapm, "Headphone Jack"); if (hs) - snd_soc_dapm_enable_pin(dapm, "HS Mic"); + snd_soc_dapm_enable_pin_unlocked(dapm, "HS Mic"); else - snd_soc_dapm_disable_pin(dapm, "HS Mic"); + snd_soc_dapm_disable_pin_unlocked(dapm, "HS Mic"); gpio_set_value(RX51_TVOUT_SEL_GPIO, tvout); - snd_soc_dapm_sync(dapm); + snd_soc_dapm_sync_unlocked(dapm); + + snd_soc_dapm_mutex_unlock(dapm); } static int rx51_startup(struct snd_pcm_substream *substream) diff --git a/sound/soc/pxa/corgi.c b/sound/soc/pxa/corgi.c index 1853d41034b..5a88136aa80 100644 --- a/sound/soc/pxa/corgi.c +++ b/sound/soc/pxa/corgi.c @@ -47,64 +47,63 @@ static int corgi_spk_func; static void corgi_ext_control(struct snd_soc_dapm_context *dapm) { + snd_soc_dapm_mutex_lock(dapm); + /* set up jack connection */ switch (corgi_jack_func) { case CORGI_HP: /* set = unmute headphone */ gpio_set_value(CORGI_GPIO_MUTE_L, 1); gpio_set_value(CORGI_GPIO_MUTE_R, 1); - snd_soc_dapm_disable_pin(dapm, "Mic Jack"); - snd_soc_dapm_disable_pin(dapm, "Line Jack"); - snd_soc_dapm_enable_pin(dapm, "Headphone Jack"); - snd_soc_dapm_disable_pin(dapm, "Headset Jack"); + snd_soc_dapm_disable_pin_unlocked(dapm, "Mic Jack"); + snd_soc_dapm_disable_pin_unlocked(dapm, "Line Jack"); + snd_soc_dapm_enable_pin_unlocked(dapm, "Headphone Jack"); + snd_soc_dapm_disable_pin_unlocked(dapm, "Headset Jack"); break; case CORGI_MIC: /* reset = mute headphone */ gpio_set_value(CORGI_GPIO_MUTE_L, 0); gpio_set_value(CORGI_GPIO_MUTE_R, 0); - snd_soc_dapm_enable_pin(dapm, "Mic Jack"); - snd_soc_dapm_disable_pin(dapm, "Line Jack"); - snd_soc_dapm_disable_pin(dapm, "Headphone Jack"); - snd_soc_dapm_disable_pin(dapm, "Headset Jack"); + snd_soc_dapm_enable_pin_unlocked(dapm, "Mic Jack"); + snd_soc_dapm_disable_pin_unlocked(dapm, "Line Jack"); + snd_soc_dapm_disable_pin_unlocked(dapm, "Headphone Jack"); + snd_soc_dapm_disable_pin_unlocked(dapm, "Headset Jack"); break; case CORGI_LINE: gpio_set_value(CORGI_GPIO_MUTE_L, 0); gpio_set_value(CORGI_GPIO_MUTE_R, 0); - snd_soc_dapm_disable_pin(dapm, "Mic Jack"); - snd_soc_dapm_enable_pin(dapm, "Line Jack"); - snd_soc_dapm_disable_pin(dapm, "Headphone Jack"); - snd_soc_dapm_disable_pin(dapm, "Headset Jack"); + snd_soc_dapm_disable_pin_unlocked(dapm, "Mic Jack"); + snd_soc_dapm_enable_pin_unlocked(dapm, "Line Jack"); + snd_soc_dapm_disable_pin_unlocked(dapm, "Headphone Jack"); + snd_soc_dapm_disable_pin_unlocked(dapm, "Headset Jack"); break; case CORGI_HEADSET: gpio_set_value(CORGI_GPIO_MUTE_L, 0); gpio_set_value(CORGI_GPIO_MUTE_R, 1); - snd_soc_dapm_enable_pin(dapm, "Mic Jack"); - snd_soc_dapm_disable_pin(dapm, "Line Jack"); - snd_soc_dapm_disable_pin(dapm, "Headphone Jack"); - snd_soc_dapm_enable_pin(dapm, "Headset Jack"); + snd_soc_dapm_enable_pin_unlocked(dapm, "Mic Jack"); + snd_soc_dapm_disable_pin_unlocked(dapm, "Line Jack"); + snd_soc_dapm_disable_pin_unlocked(dapm, "Headphone Jack"); + snd_soc_dapm_enable_pin_unlocked(dapm, "Headset Jack"); break; } if (corgi_spk_func == CORGI_SPK_ON) - snd_soc_dapm_enable_pin(dapm, "Ext Spk"); + snd_soc_dapm_enable_pin_unlocked(dapm, "Ext Spk"); else - snd_soc_dapm_disable_pin(dapm, "Ext Spk"); + snd_soc_dapm_disable_pin_unlocked(dapm, "Ext Spk"); /* signal a DAPM event */ - snd_soc_dapm_sync(dapm); + snd_soc_dapm_sync_unlocked(dapm); + + snd_soc_dapm_mutex_unlock(dapm); } static int corgi_startup(struct snd_pcm_substream *substream) { struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_codec *codec = rtd->codec; - - mutex_lock(&codec->mutex); /* check the jack status at stream startup */ - corgi_ext_control(&codec->dapm); - - mutex_unlock(&codec->mutex); + corgi_ext_control(&rtd->card->dapm); return 0; } diff --git a/sound/soc/pxa/e740_wm9705.c b/sound/soc/pxa/e740_wm9705.c index 44b5c09d296..c29fedab2f4 100644 --- a/sound/soc/pxa/e740_wm9705.c +++ b/sound/soc/pxa/e740_wm9705.c @@ -103,11 +103,6 @@ static int e740_ac97_init(struct snd_soc_pcm_runtime *rtd) snd_soc_dapm_nc_pin(dapm, "PCBEEP"); snd_soc_dapm_nc_pin(dapm, "MIC2"); - snd_soc_dapm_new_controls(dapm, e740_dapm_widgets, - ARRAY_SIZE(e740_dapm_widgets)); - - snd_soc_dapm_add_routes(dapm, audio_map, ARRAY_SIZE(audio_map)); - return 0; } @@ -136,6 +131,11 @@ static struct snd_soc_card e740 = { .owner = THIS_MODULE, .dai_link = e740_dai, .num_links = ARRAY_SIZE(e740_dai), + + .dapm_widgets = e740_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(e740_dapm_widgets), + .dapm_routes = audio_map, + .num_dapm_routes = ARRAY_SIZE(audio_map), }; static struct gpio e740_audio_gpios[] = { diff --git a/sound/soc/pxa/e750_wm9705.c b/sound/soc/pxa/e750_wm9705.c index c34e447eb99..ee36aba8806 100644 --- a/sound/soc/pxa/e750_wm9705.c +++ b/sound/soc/pxa/e750_wm9705.c @@ -85,11 +85,6 @@ static int e750_ac97_init(struct snd_soc_pcm_runtime *rtd) snd_soc_dapm_nc_pin(dapm, "PCBEEP"); snd_soc_dapm_nc_pin(dapm, "MIC2"); - snd_soc_dapm_new_controls(dapm, e750_dapm_widgets, - ARRAY_SIZE(e750_dapm_widgets)); - - snd_soc_dapm_add_routes(dapm, audio_map, ARRAY_SIZE(audio_map)); - return 0; } @@ -119,6 +114,11 @@ static struct snd_soc_card e750 = { .owner = THIS_MODULE, .dai_link = e750_dai, .num_links = ARRAY_SIZE(e750_dai), + + .dapm_widgets = e750_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(e750_dapm_widgets), + .dapm_routes = audio_map, + .num_dapm_routes = ARRAY_SIZE(audio_map), }; static struct gpio e750_audio_gpios[] = { diff --git a/sound/soc/pxa/e800_wm9712.c b/sound/soc/pxa/e800_wm9712.c index 3137f800b43..24c2078ce70 100644 --- a/sound/soc/pxa/e800_wm9712.c +++ b/sound/soc/pxa/e800_wm9712.c @@ -71,19 +71,6 @@ static const struct snd_soc_dapm_route audio_map[] = { {"MIC2", NULL, "Mic (Internal2)"}, }; -static int e800_ac97_init(struct snd_soc_pcm_runtime *rtd) -{ - struct snd_soc_codec *codec = rtd->codec; - struct snd_soc_dapm_context *dapm = &codec->dapm; - - snd_soc_dapm_new_controls(dapm, e800_dapm_widgets, - ARRAY_SIZE(e800_dapm_widgets)); - - snd_soc_dapm_add_routes(dapm, audio_map, ARRAY_SIZE(audio_map)); - - return 0; -} - static struct snd_soc_dai_link e800_dai[] = { { .name = "AC97", @@ -92,7 +79,6 @@ static struct snd_soc_dai_link e800_dai[] = { .codec_dai_name = "wm9712-hifi", .platform_name = "pxa-pcm-audio", .codec_name = "wm9712-codec", - .init = e800_ac97_init, }, { .name = "AC97 Aux", @@ -109,6 +95,11 @@ static struct snd_soc_card e800 = { .owner = THIS_MODULE, .dai_link = e800_dai, .num_links = ARRAY_SIZE(e800_dai), + + .dapm_widgets = e800_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(e800_dapm_widgets), + .dapm_routes = audio_map, + .num_dapm_routes = ARRAY_SIZE(audio_map), }; static struct gpio e800_audio_gpios[] = { diff --git a/sound/soc/pxa/magician.c b/sound/soc/pxa/magician.c index aace19e0fe2..259e048681c 100644 --- a/sound/soc/pxa/magician.c +++ b/sound/soc/pxa/magician.c @@ -41,44 +41,42 @@ static int magician_hp_switch; static int magician_spk_switch = 1; static int magician_in_sel = MAGICIAN_MIC; -static void magician_ext_control(struct snd_soc_codec *codec) +static void magician_ext_control(struct snd_soc_dapm_context *dapm) { - struct snd_soc_dapm_context *dapm = &codec->dapm; + + snd_soc_dapm_mutex_lock(dapm); if (magician_spk_switch) - snd_soc_dapm_enable_pin(dapm, "Speaker"); + snd_soc_dapm_enable_pin_unlocked(dapm, "Speaker"); else - snd_soc_dapm_disable_pin(dapm, "Speaker"); + snd_soc_dapm_disable_pin_unlocked(dapm, "Speaker"); if (magician_hp_switch) - snd_soc_dapm_enable_pin(dapm, "Headphone Jack"); + snd_soc_dapm_enable_pin_unlocked(dapm, "Headphone Jack"); else - snd_soc_dapm_disable_pin(dapm, "Headphone Jack"); + snd_soc_dapm_disable_pin_unlocked(dapm, "Headphone Jack"); switch (magician_in_sel) { case MAGICIAN_MIC: - snd_soc_dapm_disable_pin(dapm, "Headset Mic"); - snd_soc_dapm_enable_pin(dapm, "Call Mic"); + snd_soc_dapm_disable_pin_unlocked(dapm, "Headset Mic"); + snd_soc_dapm_enable_pin_unlocked(dapm, "Call Mic"); break; case MAGICIAN_MIC_EXT: - snd_soc_dapm_disable_pin(dapm, "Call Mic"); - snd_soc_dapm_enable_pin(dapm, "Headset Mic"); + snd_soc_dapm_disable_pin_unlocked(dapm, "Call Mic"); + snd_soc_dapm_enable_pin_unlocked(dapm, "Headset Mic"); break; } - snd_soc_dapm_sync(dapm); + snd_soc_dapm_sync_unlocked(dapm); + + snd_soc_dapm_mutex_unlock(dapm); } static int magician_startup(struct snd_pcm_substream *substream) { struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_codec *codec = rtd->codec; - - mutex_lock(&codec->mutex); /* check the jack status at stream startup */ - magician_ext_control(codec); - - mutex_unlock(&codec->mutex); + magician_ext_control(&rtd->card->dapm); return 0; } @@ -277,13 +275,13 @@ static int magician_get_hp(struct snd_kcontrol *kcontrol, static int magician_set_hp(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { - struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); + struct snd_soc_card *card = snd_kcontrol_chip(kcontrol); if (magician_hp_switch == ucontrol->value.integer.value[0]) return 0; magician_hp_switch = ucontrol->value.integer.value[0]; - magician_ext_control(codec); + magician_ext_control(&card->dapm); return 1; } @@ -297,13 +295,13 @@ static int magician_get_spk(struct snd_kcontrol *kcontrol, static int magician_set_spk(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { - struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); + struct snd_soc_card *card = snd_kcontrol_chip(kcontrol); if (magician_spk_switch == ucontrol->value.integer.value[0]) return 0; magician_spk_switch = ucontrol->value.integer.value[0]; - magician_ext_control(codec); + magician_ext_control(&card->dapm); return 1; } @@ -400,7 +398,6 @@ static int magician_uda1380_init(struct snd_soc_pcm_runtime *rtd) { struct snd_soc_codec *codec = rtd->codec; struct snd_soc_dapm_context *dapm = &codec->dapm; - int err; /* NC codec pins */ snd_soc_dapm_nc_pin(dapm, "VOUTLHP"); @@ -410,19 +407,6 @@ static int magician_uda1380_init(struct snd_soc_pcm_runtime *rtd) snd_soc_dapm_nc_pin(dapm, "VINL"); snd_soc_dapm_nc_pin(dapm, "VINR"); - /* Add magician specific controls */ - err = snd_soc_add_codec_controls(codec, uda1380_magician_controls, - ARRAY_SIZE(uda1380_magician_controls)); - if (err < 0) - return err; - - /* Add magician specific widgets */ - snd_soc_dapm_new_controls(dapm, uda1380_dapm_widgets, - ARRAY_SIZE(uda1380_dapm_widgets)); - - /* Set up magician specific audio path interconnects */ - snd_soc_dapm_add_routes(dapm, audio_map, ARRAY_SIZE(audio_map)); - return 0; } @@ -456,6 +440,12 @@ static struct snd_soc_card snd_soc_card_magician = { .dai_link = magician_dai, .num_links = ARRAY_SIZE(magician_dai), + .controls = uda1380_magician_controls, + .num_controls = ARRAY_SIZE(uda1380_magician_controls), + .dapm_widgets = uda1380_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(uda1380_dapm_widgets), + .dapm_routes = audio_map, + .num_dapm_routes = ARRAY_SIZE(audio_map), }; static struct platform_device *magician_snd_device; diff --git a/sound/soc/pxa/mioa701_wm9713.c b/sound/soc/pxa/mioa701_wm9713.c index 160c5245448..595eee341e9 100644 --- a/sound/soc/pxa/mioa701_wm9713.c +++ b/sound/soc/pxa/mioa701_wm9713.c @@ -127,16 +127,8 @@ static const struct snd_soc_dapm_route audio_map[] = { static int mioa701_wm9713_init(struct snd_soc_pcm_runtime *rtd) { struct snd_soc_codec *codec = rtd->codec; - struct snd_soc_dapm_context *dapm = &codec->dapm; unsigned short reg; - /* Add mioa701 specific widgets */ - snd_soc_dapm_new_controls(dapm, mioa701_dapm_widgets, - ARRAY_SIZE(mioa701_dapm_widgets)); - - /* Set up mioa701 specific audio path audio_mapnects */ - snd_soc_dapm_add_routes(dapm, audio_map, ARRAY_SIZE(audio_map)); - /* Prepare GPIO8 for rear speaker amplifier */ reg = codec->driver->read(codec, AC97_GPIO_CFG); codec->driver->write(codec, AC97_GPIO_CFG, reg | 0x0100); @@ -145,12 +137,6 @@ static int mioa701_wm9713_init(struct snd_soc_pcm_runtime *rtd) reg = codec->driver->read(codec, AC97_3D_CONTROL); codec->driver->write(codec, AC97_3D_CONTROL, reg | 0xc000); - snd_soc_dapm_enable_pin(dapm, "Front Speaker"); - snd_soc_dapm_enable_pin(dapm, "Rear Speaker"); - snd_soc_dapm_enable_pin(dapm, "Front Mic"); - snd_soc_dapm_enable_pin(dapm, "GSM Line In"); - snd_soc_dapm_enable_pin(dapm, "GSM Line Out"); - return 0; } @@ -183,6 +169,11 @@ static struct snd_soc_card mioa701 = { .owner = THIS_MODULE, .dai_link = mioa701_dai, .num_links = ARRAY_SIZE(mioa701_dai), + + .dapm_widgets = mioa701_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(mioa701_dapm_widgets), + .dapm_routes = audio_map, + .num_dapm_routes = ARRAY_SIZE(audio_map), }; static int mioa701_wm9713_probe(struct platform_device *pdev) diff --git a/sound/soc/pxa/poodle.c b/sound/soc/pxa/poodle.c index c93e138d8dc..c6bdc6c0eff 100644 --- a/sound/soc/pxa/poodle.c +++ b/sound/soc/pxa/poodle.c @@ -74,14 +74,9 @@ static void poodle_ext_control(struct snd_soc_dapm_context *dapm) static int poodle_startup(struct snd_pcm_substream *substream) { struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_codec *codec = rtd->codec; - - mutex_lock(&codec->mutex); /* check the jack status at stream startup */ - poodle_ext_control(&codec->dapm); - - mutex_unlock(&codec->mutex); + poodle_ext_control(&rtd->card->dapm); return 0; } diff --git a/sound/soc/pxa/spitz.c b/sound/soc/pxa/spitz.c index fc052d8247f..1373b017a95 100644 --- a/sound/soc/pxa/spitz.c +++ b/sound/soc/pxa/spitz.c @@ -46,74 +46,74 @@ static int spitz_mic_gpio; static void spitz_ext_control(struct snd_soc_dapm_context *dapm) { + snd_soc_dapm_mutex_lock(dapm); + if (spitz_spk_func == SPITZ_SPK_ON) - snd_soc_dapm_enable_pin(dapm, "Ext Spk"); + snd_soc_dapm_enable_pin_unlocked(dapm, "Ext Spk"); else - snd_soc_dapm_disable_pin(dapm, "Ext Spk"); + snd_soc_dapm_disable_pin_unlocked(dapm, "Ext Spk"); /* set up jack connection */ switch (spitz_jack_func) { case SPITZ_HP: /* enable and unmute hp jack, disable mic bias */ - snd_soc_dapm_disable_pin(dapm, "Headset Jack"); - snd_soc_dapm_disable_pin(dapm, "Mic Jack"); - snd_soc_dapm_disable_pin(dapm, "Line Jack"); - snd_soc_dapm_enable_pin(dapm, "Headphone Jack"); + snd_soc_dapm_disable_pin_unlocked(dapm, "Headset Jack"); + snd_soc_dapm_disable_pin_unlocked(dapm, "Mic Jack"); + snd_soc_dapm_disable_pin_unlocked(dapm, "Line Jack"); + snd_soc_dapm_enable_pin_unlocked(dapm, "Headphone Jack"); gpio_set_value(SPITZ_GPIO_MUTE_L, 1); gpio_set_value(SPITZ_GPIO_MUTE_R, 1); break; case SPITZ_MIC: /* enable mic jack and bias, mute hp */ - snd_soc_dapm_disable_pin(dapm, "Headphone Jack"); - snd_soc_dapm_disable_pin(dapm, "Headset Jack"); - snd_soc_dapm_disable_pin(dapm, "Line Jack"); - snd_soc_dapm_enable_pin(dapm, "Mic Jack"); + snd_soc_dapm_disable_pin_unlocked(dapm, "Headphone Jack"); + snd_soc_dapm_disable_pin_unlocked(dapm, "Headset Jack"); + snd_soc_dapm_disable_pin_unlocked(dapm, "Line Jack"); + snd_soc_dapm_enable_pin_unlocked(dapm, "Mic Jack"); gpio_set_value(SPITZ_GPIO_MUTE_L, 0); gpio_set_value(SPITZ_GPIO_MUTE_R, 0); break; case SPITZ_LINE: /* enable line jack, disable mic bias and mute hp */ - snd_soc_dapm_disable_pin(dapm, "Headphone Jack"); - snd_soc_dapm_disable_pin(dapm, "Headset Jack"); - snd_soc_dapm_disable_pin(dapm, "Mic Jack"); - snd_soc_dapm_enable_pin(dapm, "Line Jack"); + snd_soc_dapm_disable_pin_unlocked(dapm, "Headphone Jack"); + snd_soc_dapm_disable_pin_unlocked(dapm, "Headset Jack"); + snd_soc_dapm_disable_pin_unlocked(dapm, "Mic Jack"); + snd_soc_dapm_enable_pin_unlocked(dapm, "Line Jack"); gpio_set_value(SPITZ_GPIO_MUTE_L, 0); gpio_set_value(SPITZ_GPIO_MUTE_R, 0); break; case SPITZ_HEADSET: /* enable and unmute headset jack enable mic bias, mute L hp */ - snd_soc_dapm_disable_pin(dapm, "Headphone Jack"); - snd_soc_dapm_enable_pin(dapm, "Mic Jack"); - snd_soc_dapm_disable_pin(dapm, "Line Jack"); - snd_soc_dapm_enable_pin(dapm, "Headset Jack"); + snd_soc_dapm_disable_pin_unlocked(dapm, "Headphone Jack"); + snd_soc_dapm_enable_pin_unlocked(dapm, "Mic Jack"); + snd_soc_dapm_disable_pin_unlocked(dapm, "Line Jack"); + snd_soc_dapm_enable_pin_unlocked(dapm, "Headset Jack"); gpio_set_value(SPITZ_GPIO_MUTE_L, 0); gpio_set_value(SPITZ_GPIO_MUTE_R, 1); break; case SPITZ_HP_OFF: /* jack removed, everything off */ - snd_soc_dapm_disable_pin(dapm, "Headphone Jack"); - snd_soc_dapm_disable_pin(dapm, "Headset Jack"); - snd_soc_dapm_disable_pin(dapm, "Mic Jack"); - snd_soc_dapm_disable_pin(dapm, "Line Jack"); + snd_soc_dapm_disable_pin_unlocked(dapm, "Headphone Jack"); + snd_soc_dapm_disable_pin_unlocked(dapm, "Headset Jack"); + snd_soc_dapm_disable_pin_unlocked(dapm, "Mic Jack"); + snd_soc_dapm_disable_pin_unlocked(dapm, "Line Jack"); gpio_set_value(SPITZ_GPIO_MUTE_L, 0); gpio_set_value(SPITZ_GPIO_MUTE_R, 0); break; } - snd_soc_dapm_sync(dapm); + + snd_soc_dapm_sync_unlocked(dapm); + + snd_soc_dapm_mutex_unlock(dapm); } static int spitz_startup(struct snd_pcm_substream *substream) { struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_codec *codec = rtd->codec; - - mutex_lock(&codec->mutex); /* check the jack status at stream startup */ - spitz_ext_control(&codec->dapm); - - mutex_unlock(&codec->mutex); + spitz_ext_control(&rtd->card->dapm); return 0; } diff --git a/sound/soc/pxa/tosa.c b/sound/soc/pxa/tosa.c index 1d9c2ed223b..4a956d1cb26 100644 --- a/sound/soc/pxa/tosa.c +++ b/sound/soc/pxa/tosa.c @@ -44,48 +44,46 @@ static int tosa_jack_func; static int tosa_spk_func; -static void tosa_ext_control(struct snd_soc_codec *codec) +static void tosa_ext_control(struct snd_soc_dapm_context *dapm) { - struct snd_soc_dapm_context *dapm = &codec->dapm; + + snd_soc_dapm_mutex_lock(dapm); /* set up jack connection */ switch (tosa_jack_func) { case TOSA_HP: - snd_soc_dapm_disable_pin(dapm, "Mic (Internal)"); - snd_soc_dapm_enable_pin(dapm, "Headphone Jack"); - snd_soc_dapm_disable_pin(dapm, "Headset Jack"); + snd_soc_dapm_disable_pin_unlocked(dapm, "Mic (Internal)"); + snd_soc_dapm_enable_pin_unlocked(dapm, "Headphone Jack"); + snd_soc_dapm_disable_pin_unlocked(dapm, "Headset Jack"); break; case TOSA_MIC_INT: - snd_soc_dapm_enable_pin(dapm, "Mic (Internal)"); - snd_soc_dapm_disable_pin(dapm, "Headphone Jack"); - snd_soc_dapm_disable_pin(dapm, "Headset Jack"); + snd_soc_dapm_enable_pin_unlocked(dapm, "Mic (Internal)"); + snd_soc_dapm_disable_pin_unlocked(dapm, "Headphone Jack"); + snd_soc_dapm_disable_pin_unlocked(dapm, "Headset Jack"); break; case TOSA_HEADSET: - snd_soc_dapm_disable_pin(dapm, "Mic (Internal)"); - snd_soc_dapm_disable_pin(dapm, "Headphone Jack"); - snd_soc_dapm_enable_pin(dapm, "Headset Jack"); + snd_soc_dapm_disable_pin_unlocked(dapm, "Mic (Internal)"); + snd_soc_dapm_disable_pin_unlocked(dapm, "Headphone Jack"); + snd_soc_dapm_enable_pin_unlocked(dapm, "Headset Jack"); break; } if (tosa_spk_func == TOSA_SPK_ON) - snd_soc_dapm_enable_pin(dapm, "Speaker"); + snd_soc_dapm_enable_pin_unlocked(dapm, "Speaker"); else - snd_soc_dapm_disable_pin(dapm, "Speaker"); + snd_soc_dapm_disable_pin_unlocked(dapm, "Speaker"); + + snd_soc_dapm_sync_unlocked(dapm); - snd_soc_dapm_sync(dapm); + snd_soc_dapm_mutex_unlock(dapm); } static int tosa_startup(struct snd_pcm_substream *substream) { struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_codec *codec = rtd->codec; - - mutex_lock(&codec->mutex); /* check the jack status at stream startup */ - tosa_ext_control(codec); - - mutex_unlock(&codec->mutex); + tosa_ext_control(&rtd->card->dapm); return 0; } @@ -104,13 +102,13 @@ static int tosa_get_jack(struct snd_kcontrol *kcontrol, static int tosa_set_jack(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { - struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); + struct snd_soc_card *card = snd_kcontrol_chip(kcontrol); if (tosa_jack_func == ucontrol->value.integer.value[0]) return 0; tosa_jack_func = ucontrol->value.integer.value[0]; - tosa_ext_control(codec); + tosa_ext_control(&card->dapm); return 1; } @@ -124,13 +122,13 @@ static int tosa_get_spk(struct snd_kcontrol *kcontrol, static int tosa_set_spk(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { - struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); + struct snd_soc_card *card = snd_kcontrol_chip(kcontrol); if (tosa_spk_func == ucontrol->value.integer.value[0]) return 0; tosa_spk_func = ucontrol->value.integer.value[0]; - tosa_ext_control(codec); + tosa_ext_control(&card->dapm); return 1; } @@ -191,24 +189,10 @@ static int tosa_ac97_init(struct snd_soc_pcm_runtime *rtd) { struct snd_soc_codec *codec = rtd->codec; struct snd_soc_dapm_context *dapm = &codec->dapm; - int err; snd_soc_dapm_nc_pin(dapm, "OUT3"); snd_soc_dapm_nc_pin(dapm, "MONOOUT"); - /* add tosa specific controls */ - err = snd_soc_add_codec_controls(codec, tosa_controls, - ARRAY_SIZE(tosa_controls)); - if (err < 0) - return err; - - /* add tosa specific widgets */ - snd_soc_dapm_new_controls(dapm, tosa_dapm_widgets, - ARRAY_SIZE(tosa_dapm_widgets)); - - /* set up tosa specific audio path audio_map */ - snd_soc_dapm_add_routes(dapm, audio_map, ARRAY_SIZE(audio_map)); - return 0; } @@ -239,6 +223,13 @@ static struct snd_soc_card tosa = { .owner = THIS_MODULE, .dai_link = tosa_dai, .num_links = ARRAY_SIZE(tosa_dai), + + .controls = tosa_controls, + .num_controls = ARRAY_SIZE(tosa_controls), + .dapm_widgets = tosa_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(tosa_dapm_widgets), + .dapm_routes = audio_map, + .num_dapm_routes = ARRAY_SIZE(audio_map), }; static int tosa_probe(struct platform_device *pdev) diff --git a/sound/soc/pxa/zylonite.c b/sound/soc/pxa/zylonite.c index db8aadf8932..23bf991e95d 100644 --- a/sound/soc/pxa/zylonite.c +++ b/sound/soc/pxa/zylonite.c @@ -71,22 +71,10 @@ static const struct snd_soc_dapm_route audio_map[] = { static int zylonite_wm9713_init(struct snd_soc_pcm_runtime *rtd) { - struct snd_soc_codec *codec = rtd->codec; - struct snd_soc_dapm_context *dapm = &codec->dapm; - if (clk_pout) snd_soc_dai_set_pll(rtd->codec_dai, 0, 0, clk_get_rate(pout), 0); - snd_soc_dapm_new_controls(dapm, zylonite_dapm_widgets, - ARRAY_SIZE(zylonite_dapm_widgets)); - - snd_soc_dapm_add_routes(dapm, audio_map, ARRAY_SIZE(audio_map)); - - /* Static setup for now */ - snd_soc_dapm_enable_pin(dapm, "Headphone"); - snd_soc_dapm_enable_pin(dapm, "Headset Earpiece"); - return 0; } @@ -256,6 +244,11 @@ static struct snd_soc_card zylonite = { .resume_pre = &zylonite_resume_pre, .dai_link = zylonite_dai, .num_links = ARRAY_SIZE(zylonite_dai), + + .dapm_widgets = zylonite_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(zylonite_dapm_widgets), + .dapm_routes = audio_map, + .num_dapm_routes = ARRAY_SIZE(audio_map), }; static struct platform_device *zylonite_snd_ac97_device; diff --git a/sound/soc/s6000/s6105-ipcam.c b/sound/soc/s6000/s6105-ipcam.c index 945e8abdc10..0b21d1dc80c 100644 --- a/sound/soc/s6000/s6105-ipcam.c +++ b/sound/soc/s6000/s6105-ipcam.c @@ -104,8 +104,8 @@ static int output_type_get(struct snd_kcontrol *kcontrol, static int output_type_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { - struct snd_soc_codec *codec = kcontrol->private_data; - struct snd_soc_dapm_context *dapm = &codec->dapm; + struct snd_soc_card *card = kcontrol->private_data; + struct snd_soc_dapm_context *dapm = &card->dapm; unsigned int val = (ucontrol->value.enumerated.item[0] != 0); char *differential = "Audio Out Differential"; char *stereo = "Audio Out Stereo"; @@ -137,13 +137,7 @@ static int s6105_aic3x_init(struct snd_soc_pcm_runtime *rtd) { struct snd_soc_codec *codec = rtd->codec; struct snd_soc_dapm_context *dapm = &codec->dapm; - - /* Add s6105 specific widgets */ - snd_soc_dapm_new_controls(dapm, aic3x_dapm_widgets, - ARRAY_SIZE(aic3x_dapm_widgets)); - - /* Set up s6105 specific audio path audio_map */ - snd_soc_dapm_add_routes(dapm, audio_map, ARRAY_SIZE(audio_map)); + struct snd_soc_card *card = rtd->card; /* not present */ snd_soc_dapm_nc_pin(dapm, "MONO_LOUT"); @@ -157,17 +151,10 @@ static int s6105_aic3x_init(struct snd_soc_pcm_runtime *rtd) snd_soc_dapm_nc_pin(dapm, "RLOUT"); snd_soc_dapm_nc_pin(dapm, "HPRCOM"); - /* always connected */ - snd_soc_dapm_enable_pin(dapm, "Audio In"); - /* must correspond to audio_out_mux.private_value initializer */ - snd_soc_dapm_disable_pin(dapm, "Audio Out Differential"); - snd_soc_dapm_sync(dapm); - snd_soc_dapm_enable_pin(dapm, "Audio Out Stereo"); - - snd_soc_dapm_sync(dapm); + snd_soc_dapm_disable_pin(&card->dapm, "Audio Out Differential"); - snd_ctl_add(codec->card->snd_card, snd_ctl_new1(&audio_out_mux, codec)); + snd_ctl_add(card->snd_card, snd_ctl_new1(&audio_out_mux, card)); return 0; } @@ -190,6 +177,11 @@ static struct snd_soc_card snd_soc_card_s6105 = { .owner = THIS_MODULE, .dai_link = &s6105_dai, .num_links = 1, + + .dapm_widgets = aic3x_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(aic3x_dapm_widgets), + .dapm_routes = audio_map, + .num_dapm_routes = ARRAY_SIZE(audio_map), }; static struct s6000_snd_platform_data s6105_snd_data __initdata = { diff --git a/sound/soc/samsung/Kconfig b/sound/soc/samsung/Kconfig index 35075740039..f2e289180e4 100644 --- a/sound/soc/samsung/Kconfig +++ b/sound/soc/samsung/Kconfig @@ -117,7 +117,7 @@ config SND_SOC_SAMSUNG_SIMTEC_TLV320AIC23 tristate "SoC I2S Audio support for TLV320AIC23 on Simtec boards" depends on SND_SOC_SAMSUNG && ARCH_S3C24XX select SND_S3C24XX_I2S - select SND_SOC_TLV320AIC23 + select SND_SOC_TLV320AIC23_I2C select SND_SOC_SAMSUNG_SIMTEC config SND_SOC_SAMSUNG_SIMTEC_HERMES diff --git a/sound/soc/samsung/h1940_uda1380.c b/sound/soc/samsung/h1940_uda1380.c index fbced589d07..88b09e02250 100644 --- a/sound/soc/samsung/h1940_uda1380.c +++ b/sound/soc/samsung/h1940_uda1380.c @@ -66,10 +66,6 @@ static int h1940_startup(struct snd_pcm_substream *substream) { struct snd_pcm_runtime *runtime = substream->runtime; - runtime->hw.rate_min = hw_rates.list[0]; - runtime->hw.rate_max = hw_rates.list[hw_rates.count - 1]; - runtime->hw.rates = SNDRV_PCM_RATE_KNOT; - return snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, &hw_rates); @@ -94,7 +90,7 @@ static int h1940_hw_params(struct snd_pcm_substream *substream, div++; break; default: - dev_err(&rtd->dev, "%s: rate %d is not supported\n", + dev_err(rtd->dev, "%s: rate %d is not supported\n", __func__, rate); return -EINVAL; } @@ -181,7 +177,6 @@ static int h1940_uda1380_init(struct snd_soc_pcm_runtime *rtd) { struct snd_soc_codec *codec = rtd->codec; struct snd_soc_dapm_context *dapm = &codec->dapm; - int err; snd_soc_dapm_enable_pin(dapm, "Headphone Jack"); snd_soc_dapm_enable_pin(dapm, "Speaker"); diff --git a/sound/soc/samsung/neo1973_wm8753.c b/sound/soc/samsung/neo1973_wm8753.c index 98a04c11202..b0800337b79 100644 --- a/sound/soc/samsung/neo1973_wm8753.c +++ b/sound/soc/samsung/neo1973_wm8753.c @@ -192,44 +192,6 @@ static struct snd_soc_ops neo1973_voice_ops = { .hw_free = neo1973_voice_hw_free, }; -/* Shared routes and controls */ - -static const struct snd_soc_dapm_widget neo1973_wm8753_dapm_widgets[] = { - SND_SOC_DAPM_LINE("GSM Line Out", NULL), - SND_SOC_DAPM_LINE("GSM Line In", NULL), - SND_SOC_DAPM_MIC("Headset Mic", NULL), - SND_SOC_DAPM_MIC("Handset Mic", NULL), -}; - -static const struct snd_soc_dapm_route neo1973_wm8753_routes[] = { - /* Connections to the GSM Module */ - {"GSM Line Out", NULL, "MONO1"}, - {"GSM Line Out", NULL, "MONO2"}, - {"RXP", NULL, "GSM Line In"}, - {"RXN", NULL, "GSM Line In"}, - - /* Connections to Headset */ - {"MIC1", NULL, "Mic Bias"}, - {"Mic Bias", NULL, "Headset Mic"}, - - /* Call Mic */ - {"MIC2", NULL, "Mic Bias"}, - {"MIC2N", NULL, "Mic Bias"}, - {"Mic Bias", NULL, "Handset Mic"}, - - /* Connect the ALC pins */ - {"ACIN", NULL, "ACOP"}, -}; - -static const struct snd_kcontrol_new neo1973_wm8753_controls[] = { - SOC_DAPM_PIN_SWITCH("GSM Line Out"), - SOC_DAPM_PIN_SWITCH("GSM Line In"), - SOC_DAPM_PIN_SWITCH("Headset Mic"), - SOC_DAPM_PIN_SWITCH("Handset Mic"), -}; - -/* GTA02 specific routes and controls */ - static int gta02_speaker_enabled; static int lm4853_set_spk(struct snd_kcontrol *kcontrol, @@ -257,7 +219,34 @@ static int lm4853_event(struct snd_soc_dapm_widget *w, return 0; } -static const struct snd_soc_dapm_route neo1973_gta02_routes[] = { +static const struct snd_soc_dapm_widget neo1973_wm8753_dapm_widgets[] = { + SND_SOC_DAPM_LINE("GSM Line Out", NULL), + SND_SOC_DAPM_LINE("GSM Line In", NULL), + SND_SOC_DAPM_MIC("Headset Mic", NULL), + SND_SOC_DAPM_MIC("Handset Mic", NULL), + SND_SOC_DAPM_SPK("Handset Spk", NULL), + SND_SOC_DAPM_SPK("Stereo Out", lm4853_event), +}; + +static const struct snd_soc_dapm_route neo1973_wm8753_routes[] = { + /* Connections to the GSM Module */ + {"GSM Line Out", NULL, "MONO1"}, + {"GSM Line Out", NULL, "MONO2"}, + {"RXP", NULL, "GSM Line In"}, + {"RXN", NULL, "GSM Line In"}, + + /* Connections to Headset */ + {"MIC1", NULL, "Mic Bias"}, + {"Mic Bias", NULL, "Headset Mic"}, + + /* Call Mic */ + {"MIC2", NULL, "Mic Bias"}, + {"MIC2N", NULL, "Mic Bias"}, + {"Mic Bias", NULL, "Handset Mic"}, + + /* Connect the ALC pins */ + {"ACIN", NULL, "ACOP"}, + /* Connections to the amp */ {"Stereo Out", NULL, "LOUT1"}, {"Stereo Out", NULL, "ROUT1"}, @@ -267,7 +256,11 @@ static const struct snd_soc_dapm_route neo1973_gta02_routes[] = { {"Handset Spk", NULL, "ROUT2"}, }; -static const struct snd_kcontrol_new neo1973_gta02_wm8753_controls[] = { +static const struct snd_kcontrol_new neo1973_wm8753_controls[] = { + SOC_DAPM_PIN_SWITCH("GSM Line Out"), + SOC_DAPM_PIN_SWITCH("GSM Line In"), + SOC_DAPM_PIN_SWITCH("Headset Mic"), + SOC_DAPM_PIN_SWITCH("Handset Mic"), SOC_DAPM_PIN_SWITCH("Handset Spk"), SOC_DAPM_PIN_SWITCH("Stereo Out"), @@ -276,86 +269,32 @@ static const struct snd_kcontrol_new neo1973_gta02_wm8753_controls[] = { lm4853_set_spk), }; -static const struct snd_soc_dapm_widget neo1973_gta02_wm8753_dapm_widgets[] = { - SND_SOC_DAPM_SPK("Handset Spk", NULL), - SND_SOC_DAPM_SPK("Stereo Out", lm4853_event), -}; - -static int neo1973_gta02_wm8753_init(struct snd_soc_codec *codec) -{ - struct snd_soc_dapm_context *dapm = &codec->dapm; - int ret; - - ret = snd_soc_dapm_new_controls(dapm, neo1973_gta02_wm8753_dapm_widgets, - ARRAY_SIZE(neo1973_gta02_wm8753_dapm_widgets)); - if (ret) - return ret; - - ret = snd_soc_dapm_add_routes(dapm, neo1973_gta02_routes, - ARRAY_SIZE(neo1973_gta02_routes)); - if (ret) - return ret; - - ret = snd_soc_add_card_controls(codec->card, neo1973_gta02_wm8753_controls, - ARRAY_SIZE(neo1973_gta02_wm8753_controls)); - if (ret) - return ret; - - snd_soc_dapm_disable_pin(dapm, "Stereo Out"); - snd_soc_dapm_disable_pin(dapm, "Handset Spk"); - snd_soc_dapm_ignore_suspend(dapm, "Stereo Out"); - snd_soc_dapm_ignore_suspend(dapm, "Handset Spk"); - - return 0; -} - static int neo1973_wm8753_init(struct snd_soc_pcm_runtime *rtd) { struct snd_soc_codec *codec = rtd->codec; - struct snd_soc_dapm_context *dapm = &codec->dapm; - int ret; + struct snd_soc_card *card = rtd->card; /* set up NC codec pins */ - snd_soc_dapm_nc_pin(dapm, "OUT3"); - snd_soc_dapm_nc_pin(dapm, "OUT4"); - snd_soc_dapm_nc_pin(dapm, "LINE1"); - snd_soc_dapm_nc_pin(dapm, "LINE2"); - - /* Add neo1973 specific widgets */ - ret = snd_soc_dapm_new_controls(dapm, neo1973_wm8753_dapm_widgets, - ARRAY_SIZE(neo1973_wm8753_dapm_widgets)); - if (ret) - return ret; - - /* add neo1973 specific controls */ - ret = snd_soc_add_card_controls(rtd->card, neo1973_wm8753_controls, - ARRAY_SIZE(neo1973_wm8753_controls)); - if (ret) - return ret; - - /* set up neo1973 specific audio routes */ - ret = snd_soc_dapm_add_routes(dapm, neo1973_wm8753_routes, - ARRAY_SIZE(neo1973_wm8753_routes)); - if (ret) - return ret; + snd_soc_dapm_nc_pin(&codec->dapm, "OUT3"); + snd_soc_dapm_nc_pin(&codec->dapm, "OUT4"); + snd_soc_dapm_nc_pin(&codec->dapm, "LINE1"); + snd_soc_dapm_nc_pin(&codec->dapm, "LINE2"); /* set endpoints to default off mode */ - snd_soc_dapm_disable_pin(dapm, "GSM Line Out"); - snd_soc_dapm_disable_pin(dapm, "GSM Line In"); - snd_soc_dapm_disable_pin(dapm, "Headset Mic"); - snd_soc_dapm_disable_pin(dapm, "Handset Mic"); + snd_soc_dapm_disable_pin(&card->dapm, "GSM Line Out"); + snd_soc_dapm_disable_pin(&card->dapm, "GSM Line In"); + snd_soc_dapm_disable_pin(&card->dapm, "Headset Mic"); + snd_soc_dapm_disable_pin(&card->dapm, "Handset Mic"); + snd_soc_dapm_disable_pin(&card->dapm, "Stereo Out"); + snd_soc_dapm_disable_pin(&card->dapm, "Handset Spk"); /* allow audio paths from the GSM modem to run during suspend */ - snd_soc_dapm_ignore_suspend(dapm, "GSM Line Out"); - snd_soc_dapm_ignore_suspend(dapm, "GSM Line In"); - snd_soc_dapm_ignore_suspend(dapm, "Headset Mic"); - snd_soc_dapm_ignore_suspend(dapm, "Handset Mic"); - - if (machine_is_neo1973_gta02()) { - ret = neo1973_gta02_wm8753_init(codec); - if (ret) - return ret; - } + snd_soc_dapm_ignore_suspend(&card->dapm, "GSM Line Out"); + snd_soc_dapm_ignore_suspend(&card->dapm, "GSM Line In"); + snd_soc_dapm_ignore_suspend(&card->dapm, "Headset Mic"); + snd_soc_dapm_ignore_suspend(&card->dapm, "Handset Mic"); + snd_soc_dapm_ignore_suspend(&card->dapm, "Stereo Out"); + snd_soc_dapm_ignore_suspend(&card->dapm, "Handset Spk"); return 0; } @@ -409,6 +348,13 @@ static struct snd_soc_card neo1973 = { .num_aux_devs = ARRAY_SIZE(neo1973_aux_devs), .codec_conf = neo1973_codec_conf, .num_configs = ARRAY_SIZE(neo1973_codec_conf), + + .controls = neo1973_wm8753_controls, + .num_controls = ARRAY_SIZE(neo1973_wm8753_controls), + .dapm_widgets = neo1973_wm8753_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(neo1973_wm8753_dapm_widgets), + .dapm_routes = neo1973_wm8753_routes, + .num_dapm_routes = ARRAY_SIZE(neo1973_wm8753_routes), }; static struct platform_device *neo1973_snd_device; diff --git a/sound/soc/samsung/rx1950_uda1380.c b/sound/soc/samsung/rx1950_uda1380.c index 06ebdc06177..2982d9e7f26 100644 --- a/sound/soc/samsung/rx1950_uda1380.c +++ b/sound/soc/samsung/rx1950_uda1380.c @@ -131,10 +131,6 @@ static int rx1950_startup(struct snd_pcm_substream *substream) { struct snd_pcm_runtime *runtime = substream->runtime; - runtime->hw.rate_min = hw_rates.list[0]; - runtime->hw.rate_max = hw_rates.list[hw_rates.count - 1]; - runtime->hw.rates = SNDRV_PCM_RATE_KNOT; - return snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, &hw_rates); @@ -226,7 +222,6 @@ static int rx1950_uda1380_init(struct snd_soc_pcm_runtime *rtd) { struct snd_soc_codec *codec = rtd->codec; struct snd_soc_dapm_context *dapm = &codec->dapm; - int err; snd_soc_dapm_enable_pin(dapm, "Headphone Jack"); snd_soc_dapm_enable_pin(dapm, "Speaker"); diff --git a/sound/soc/samsung/smdk_wm8994.c b/sound/soc/samsung/smdk_wm8994.c index d38ae98e2f3..682eb4f7ba0 100644 --- a/sound/soc/samsung/smdk_wm8994.c +++ b/sound/soc/samsung/smdk_wm8994.c @@ -202,7 +202,7 @@ static int smdk_audio_probe(struct platform_device *pdev) static struct platform_driver smdk_audio_driver = { .driver = { - .name = "smdk-audio-wm8894", + .name = "smdk-audio-wm8994", .owner = THIS_MODULE, .of_match_table = of_match_ptr(samsung_wm8994_of_match), .pm = &snd_soc_pm_ops, diff --git a/sound/soc/samsung/tobermory.c b/sound/soc/samsung/tobermory.c index f21ff608a81..1807b75ccc1 100644 --- a/sound/soc/samsung/tobermory.c +++ b/sound/soc/samsung/tobermory.c @@ -44,6 +44,8 @@ static int tobermory_set_bias_level(struct snd_soc_card *card, SND_SOC_CLOCK_IN); if (ret < 0) { pr_err("Failed to set SYSCLK: %d\n", ret); + snd_soc_dai_set_pll(codec_dai, WM8962_FLL, + 0, 0, 0); return ret; } } diff --git a/sound/soc/sh/fsi.c b/sound/soc/sh/fsi.c index 1967f44e7cd..710a079a737 100644 --- a/sound/soc/sh/fsi.c +++ b/sound/soc/sh/fsi.c @@ -1711,9 +1711,9 @@ static int fsi_dai_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) /* set master/slave audio interface */ switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { case SND_SOC_DAIFMT_CBM_CFM: - fsi->clk_master = 1; break; case SND_SOC_DAIFMT_CBS_CFS: + fsi->clk_master = 1; /* codec is slave, cpu is master */ break; default: return -EINVAL; diff --git a/sound/soc/sh/migor.c b/sound/soc/sh/migor.c index 5014a884afe..c58c2529f10 100644 --- a/sound/soc/sh/migor.c +++ b/sound/soc/sh/migor.c @@ -136,19 +136,6 @@ static const struct snd_soc_dapm_route audio_map[] = { { "Mic Bias", NULL, "External Microphone" }, }; -static int migor_dai_init(struct snd_soc_pcm_runtime *rtd) -{ - struct snd_soc_codec *codec = rtd->codec; - struct snd_soc_dapm_context *dapm = &codec->dapm; - - snd_soc_dapm_new_controls(dapm, migor_dapm_widgets, - ARRAY_SIZE(migor_dapm_widgets)); - - snd_soc_dapm_add_routes(dapm, audio_map, ARRAY_SIZE(audio_map)); - - return 0; -} - /* migor digital audio interface glue - connects codec <--> CPU */ static struct snd_soc_dai_link migor_dai = { .name = "wm8978", @@ -158,7 +145,6 @@ static struct snd_soc_dai_link migor_dai = { .platform_name = "siu-pcm-audio", .codec_name = "wm8978.0-001a", .ops = &migor_dai_ops, - .init = migor_dai_init, }; /* migor audio machine driver */ @@ -167,6 +153,11 @@ static struct snd_soc_card snd_soc_migor = { .owner = THIS_MODULE, .dai_link = &migor_dai, .num_links = 1, + + .dapm_widgets = migor_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(migor_dapm_widgets), + .dapm_routes = audio_map, + .num_dapm_routes = ARRAY_SIZE(audio_map), }; static struct platform_device *migor_snd_device; diff --git a/sound/soc/sh/rcar/Makefile b/sound/soc/sh/rcar/Makefile index 0ff492df792..7d0051ced83 100644 --- a/sound/soc/sh/rcar/Makefile +++ b/sound/soc/sh/rcar/Makefile @@ -1,2 +1,2 @@ -snd-soc-rcar-objs := core.o gen.o scu.o adg.o ssi.o +snd-soc-rcar-objs := core.o gen.o src.o adg.o ssi.o obj-$(CONFIG_SND_SOC_RCAR) += snd-soc-rcar.o
\ No newline at end of file diff --git a/sound/soc/sh/rcar/adg.c b/sound/soc/sh/rcar/adg.c index a53235c4d1b..69c44269ebd 100644 --- a/sound/soc/sh/rcar/adg.c +++ b/sound/soc/sh/rcar/adg.c @@ -25,15 +25,165 @@ struct rsnd_adg { }; #define for_each_rsnd_clk(pos, adg, i) \ - for (i = 0, (pos) = adg->clk[i]; \ - i < CLKMAX; \ - i++, (pos) = adg->clk[i]) + for (i = 0; \ + (i < CLKMAX) && \ + ((pos) = adg->clk[i]); \ + i++) #define rsnd_priv_to_adg(priv) ((struct rsnd_adg *)(priv)->adg) -static int rsnd_adg_set_convert_clk_gen1(struct rsnd_priv *priv, - struct rsnd_mod *mod, - unsigned int src_rate, - unsigned int dst_rate) + +static u32 rsnd_adg_ssi_ws_timing_gen2(struct rsnd_dai_stream *io) +{ + struct rsnd_mod *mod = rsnd_io_to_mod_ssi(io); + struct rsnd_priv *priv = rsnd_mod_to_priv(mod); + int id = rsnd_mod_id(mod); + int ws = id; + + if (rsnd_ssi_is_pin_sharing(rsnd_ssi_mod_get(priv, id))) { + switch (id) { + case 1: + case 2: + ws = 0; + break; + case 4: + ws = 3; + break; + case 8: + ws = 7; + break; + } + } + + return (0x6 + ws) << 8; +} + +static int rsnd_adg_set_src_timsel_gen2(struct rsnd_dai *rdai, + struct rsnd_mod *mod, + struct rsnd_dai_stream *io, + u32 timsel) +{ + int is_play = rsnd_dai_is_play(rdai, io); + int id = rsnd_mod_id(mod); + int shift = (id % 2) ? 16 : 0; + u32 mask, ws; + u32 in, out; + + ws = rsnd_adg_ssi_ws_timing_gen2(io); + + in = (is_play) ? timsel : ws; + out = (is_play) ? ws : timsel; + + in = in << shift; + out = out << shift; + mask = 0xffff << shift; + + switch (id / 2) { + case 0: + rsnd_mod_bset(mod, SRCIN_TIMSEL0, mask, in); + rsnd_mod_bset(mod, SRCOUT_TIMSEL0, mask, out); + break; + case 1: + rsnd_mod_bset(mod, SRCIN_TIMSEL1, mask, in); + rsnd_mod_bset(mod, SRCOUT_TIMSEL1, mask, out); + break; + case 2: + rsnd_mod_bset(mod, SRCIN_TIMSEL2, mask, in); + rsnd_mod_bset(mod, SRCOUT_TIMSEL2, mask, out); + break; + case 3: + rsnd_mod_bset(mod, SRCIN_TIMSEL3, mask, in); + rsnd_mod_bset(mod, SRCOUT_TIMSEL3, mask, out); + break; + case 4: + rsnd_mod_bset(mod, SRCIN_TIMSEL4, mask, in); + rsnd_mod_bset(mod, SRCOUT_TIMSEL4, mask, out); + break; + } + + return 0; +} + +int rsnd_adg_set_convert_clk_gen2(struct rsnd_mod *mod, + struct rsnd_dai *rdai, + struct rsnd_dai_stream *io, + unsigned int src_rate, + unsigned int dst_rate) +{ + struct rsnd_priv *priv = rsnd_mod_to_priv(mod); + struct rsnd_adg *adg = rsnd_priv_to_adg(priv); + struct device *dev = rsnd_priv_to_dev(priv); + int idx, sel, div, step, ret; + u32 val, en; + unsigned int min, diff; + unsigned int sel_rate [] = { + clk_get_rate(adg->clk[CLKA]), /* 0000: CLKA */ + clk_get_rate(adg->clk[CLKB]), /* 0001: CLKB */ + clk_get_rate(adg->clk[CLKC]), /* 0010: CLKC */ + adg->rbga_rate_for_441khz_div_6,/* 0011: RBGA */ + adg->rbgb_rate_for_48khz_div_6, /* 0100: RBGB */ + }; + + min = ~0; + val = 0; + en = 0; + for (sel = 0; sel < ARRAY_SIZE(sel_rate); sel++) { + idx = 0; + step = 2; + + if (!sel_rate[sel]) + continue; + + for (div = 2; div <= 98304; div += step) { + diff = abs(src_rate - sel_rate[sel] / div); + if (min > diff) { + val = (sel << 8) | idx; + min = diff; + en = 1 << (sel + 1); /* fixme */ + } + + /* + * step of 0_0000 / 0_0001 / 0_1101 + * are out of order + */ + if ((idx > 2) && (idx % 2)) + step *= 2; + if (idx == 0x1c) { + div += step; + step *= 2; + } + idx++; + } + } + + if (min == ~0) { + dev_err(dev, "no Input clock\n"); + return -EIO; + } + + ret = rsnd_adg_set_src_timsel_gen2(rdai, mod, io, val); + if (ret < 0) { + dev_err(dev, "timsel error\n"); + return ret; + } + + rsnd_mod_bset(mod, DIV_EN, en, en); + + return 0; +} + +int rsnd_adg_set_convert_timing_gen2(struct rsnd_mod *mod, + struct rsnd_dai *rdai, + struct rsnd_dai_stream *io) +{ + u32 val = rsnd_adg_ssi_ws_timing_gen2(io); + + return rsnd_adg_set_src_timsel_gen2(rdai, mod, io, val); +} + +int rsnd_adg_set_convert_clk_gen1(struct rsnd_priv *priv, + struct rsnd_mod *mod, + unsigned int src_rate, + unsigned int dst_rate) { struct rsnd_adg *adg = rsnd_priv_to_adg(priv); struct device *dev = rsnd_priv_to_dev(priv); @@ -91,18 +241,6 @@ find_rate: return 0; } -int rsnd_adg_set_convert_clk(struct rsnd_priv *priv, - struct rsnd_mod *mod, - unsigned int src_rate, - unsigned int dst_rate) -{ - if (rsnd_is_gen1(priv)) - return rsnd_adg_set_convert_clk_gen1(priv, mod, - src_rate, dst_rate); - - return -EINVAL; -} - static void rsnd_adg_set_ssi_clk(struct rsnd_mod *mod, u32 val) { int id = rsnd_mod_id(mod); @@ -254,13 +392,14 @@ static void rsnd_adg_ssi_clk_init(struct rsnd_priv *priv, struct rsnd_adg *adg) } int rsnd_adg_probe(struct platform_device *pdev, - struct rcar_snd_info *info, + const struct rsnd_of_data *of_data, struct rsnd_priv *priv) { struct rsnd_adg *adg; struct device *dev = rsnd_priv_to_dev(priv); - struct clk *clk; + struct clk *clk, *clk_orig; int i; + bool use_old_style = false; adg = devm_kzalloc(dev, sizeof(*adg), GFP_KERNEL); if (!adg) { @@ -268,10 +407,39 @@ int rsnd_adg_probe(struct platform_device *pdev, return -ENOMEM; } - adg->clk[CLKA] = clk_get(NULL, "audio_clk_a"); - adg->clk[CLKB] = clk_get(NULL, "audio_clk_b"); - adg->clk[CLKC] = clk_get(NULL, "audio_clk_c"); - adg->clk[CLKI] = clk_get(NULL, "audio_clk_internal"); + clk_orig = devm_clk_get(dev, NULL); + adg->clk[CLKA] = devm_clk_get(dev, "clk_a"); + adg->clk[CLKB] = devm_clk_get(dev, "clk_b"); + adg->clk[CLKC] = devm_clk_get(dev, "clk_c"); + adg->clk[CLKI] = devm_clk_get(dev, "clk_i"); + + /* + * It request device dependent audio clock. + * But above all clks will indicate rsnd module clock + * if platform doesn't it + */ + for_each_rsnd_clk(clk, adg, i) { + if (clk_orig == clk) { + dev_warn(dev, + "doesn't have device dependent clock, use independent clock\n"); + use_old_style = true; + break; + } + } + + /* + * note: + * these exist in order to keep compatible with + * platform which has device independent audio clock, + * but will be removed soon + */ + if (use_old_style) { + adg->clk[CLKA] = devm_clk_get(NULL, "audio_clk_a"); + adg->clk[CLKB] = devm_clk_get(NULL, "audio_clk_b"); + adg->clk[CLKC] = devm_clk_get(NULL, "audio_clk_c"); + adg->clk[CLKI] = devm_clk_get(NULL, "audio_clk_internal"); + } + for_each_rsnd_clk(clk, adg, i) { if (IS_ERR(clk)) { dev_err(dev, "Audio clock failed\n"); @@ -287,14 +455,3 @@ int rsnd_adg_probe(struct platform_device *pdev, return 0; } - -void rsnd_adg_remove(struct platform_device *pdev, - struct rsnd_priv *priv) -{ - struct rsnd_adg *adg = priv->adg; - struct clk *clk; - int i; - - for_each_rsnd_clk(clk, adg, i) - clk_put(clk); -} diff --git a/sound/soc/sh/rcar/core.c b/sound/soc/sh/rcar/core.c index 743de5e3b1e..215b668166b 100644 --- a/sound/soc/sh/rcar/core.c +++ b/sound/soc/sh/rcar/core.c @@ -73,13 +73,13 @@ * | +- ssi[2] * | ... * | - * | ** these control scu + * | ** these control src * | - * +- scu + * +- src * | - * +- scu[0] - * +- scu[1] - * +- scu[2] + * +- src[0] + * +- src[1] + * +- src[2] * ... * * @@ -100,6 +100,21 @@ #define RSND_RATES SNDRV_PCM_RATE_8000_96000 #define RSND_FMTS (SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S16_LE) +static struct rsnd_of_data rsnd_of_data_gen1 = { + .flags = RSND_GEN1, +}; + +static struct rsnd_of_data rsnd_of_data_gen2 = { + .flags = RSND_GEN2, +}; + +static struct of_device_id rsnd_of_match[] = { + { .compatible = "renesas,rcar_sound-gen1", .data = &rsnd_of_data_gen1 }, + { .compatible = "renesas,rcar_sound-gen2", .data = &rsnd_of_data_gen2 }, + {}, +}; +MODULE_DEVICE_TABLE(of, rsnd_of_match); + /* * rsnd_platform functions */ @@ -107,6 +122,11 @@ (!(priv->info->func) ? 0 : \ priv->info->func(param)) +#define rsnd_is_enable_path(io, name) \ + ((io)->info ? (io)->info->name : NULL) +#define rsnd_info_id(priv, io, name) \ + ((io)->info->name - priv->info->name##_info) + /* * rsnd_mod functions */ @@ -121,17 +141,19 @@ char *rsnd_mod_name(struct rsnd_mod *mod) void rsnd_mod_init(struct rsnd_priv *priv, struct rsnd_mod *mod, struct rsnd_mod_ops *ops, + enum rsnd_mod_type type, int id) { mod->priv = priv; mod->id = id; mod->ops = ops; - INIT_LIST_HEAD(&mod->list); + mod->type = type; } /* * rsnd_dma functions */ +static void __rsnd_dma_start(struct rsnd_dma *dma); static void rsnd_dma_continue(struct rsnd_dma *dma) { /* push next A or B plane */ @@ -142,8 +164,9 @@ static void rsnd_dma_continue(struct rsnd_dma *dma) void rsnd_dma_start(struct rsnd_dma *dma) { /* push both A and B plane*/ + dma->offset = 0; dma->submit_loop = 2; - schedule_work(&dma->work); + __rsnd_dma_start(dma); } void rsnd_dma_stop(struct rsnd_dma *dma) @@ -156,12 +179,26 @@ void rsnd_dma_stop(struct rsnd_dma *dma) static void rsnd_dma_complete(void *data) { struct rsnd_dma *dma = (struct rsnd_dma *)data; - struct rsnd_priv *priv = dma->priv; + struct rsnd_mod *mod = rsnd_dma_to_mod(dma); + struct rsnd_priv *priv = rsnd_mod_to_priv(rsnd_dma_to_mod(dma)); + struct rsnd_dai_stream *io = rsnd_mod_to_io(mod); unsigned long flags; rsnd_lock(priv, flags); - dma->complete(dma); + /* + * Renesas sound Gen1 needs 1 DMAC, + * Gen2 needs 2 DMAC. + * In Gen2 case, it are Audio-DMAC, and Audio-DMAC-peri-peri. + * But, Audio-DMAC-peri-peri doesn't have interrupt, + * and this driver is assuming that here. + * + * If Audio-DMAC-peri-peri has interrpt, + * rsnd_dai_pointer_update() will be called twice, + * ant it will breaks io->byte_pos + */ + + rsnd_dai_pointer_update(io, io->byte_per_period); if (dma->submit_loop) rsnd_dma_continue(dma); @@ -169,20 +206,23 @@ static void rsnd_dma_complete(void *data) rsnd_unlock(priv, flags); } -static void rsnd_dma_do_work(struct work_struct *work) +static void __rsnd_dma_start(struct rsnd_dma *dma) { - struct rsnd_dma *dma = container_of(work, struct rsnd_dma, work); - struct rsnd_priv *priv = dma->priv; + struct rsnd_mod *mod = rsnd_dma_to_mod(dma); + struct rsnd_priv *priv = rsnd_mod_to_priv(mod); + struct rsnd_dai_stream *io = rsnd_mod_to_io(mod); + struct snd_pcm_runtime *runtime = rsnd_io_to_runtime(io); struct device *dev = rsnd_priv_to_dev(priv); struct dma_async_tx_descriptor *desc; dma_addr_t buf; - size_t len; + size_t len = io->byte_per_period; int i; for (i = 0; i < dma->submit_loop; i++) { - if (dma->inquiry(dma, &buf, &len) < 0) - return; + buf = runtime->dma_addr + + rsnd_dai_pointer_offset(io, dma->offset + len); + dma->offset = len; desc = dmaengine_prep_slave_single( dma->chan, buf, len, dma->dir, @@ -204,16 +244,20 @@ static void rsnd_dma_do_work(struct work_struct *work) } } +static void rsnd_dma_do_work(struct work_struct *work) +{ + struct rsnd_dma *dma = container_of(work, struct rsnd_dma, work); + + __rsnd_dma_start(dma); +} + int rsnd_dma_available(struct rsnd_dma *dma) { return !!dma->chan; } int rsnd_dma_init(struct rsnd_priv *priv, struct rsnd_dma *dma, - int is_play, int id, - int (*inquiry)(struct rsnd_dma *dma, - dma_addr_t *buf, int *len), - int (*complete)(struct rsnd_dma *dma)) + int is_play, int id) { struct device *dev = rsnd_priv_to_dev(priv); struct dma_slave_config cfg; @@ -246,9 +290,6 @@ int rsnd_dma_init(struct rsnd_priv *priv, struct rsnd_dma *dma, goto rsnd_dma_init_err; dma->dir = is_play ? DMA_TO_DEVICE : DMA_FROM_DEVICE; - dma->priv = priv; - dma->inquiry = inquiry; - dma->complete = complete; INIT_WORK(&dma->work, rsnd_dma_do_work); return 0; @@ -271,26 +312,42 @@ void rsnd_dma_quit(struct rsnd_priv *priv, /* * rsnd_dai functions */ -#define rsnd_dai_call(rdai, io, fn) \ -({ \ - struct rsnd_mod *mod, *n; \ - int ret = 0; \ - for_each_rsnd_mod(mod, n, io) { \ - ret = rsnd_mod_call(mod, fn, rdai, io); \ - if (ret < 0) \ - break; \ - } \ - ret; \ +#define __rsnd_mod_call(mod, func, rdai, io) \ +({ \ + struct rsnd_priv *priv = rsnd_mod_to_priv(mod); \ + struct device *dev = rsnd_priv_to_dev(priv); \ + dev_dbg(dev, "%s [%d] %s\n", \ + rsnd_mod_name(mod), rsnd_mod_id(mod), #func); \ + (mod)->ops->func(mod, rdai, io); \ +}) + +#define rsnd_mod_call(mod, func, rdai, io) \ + (!(mod) ? -ENODEV : \ + !((mod)->ops->func) ? 0 : \ + __rsnd_mod_call(mod, func, (rdai), (io))) + +#define rsnd_dai_call(rdai, io, fn) \ +({ \ + struct rsnd_mod *mod; \ + int ret = 0, i; \ + for (i = 0; i < RSND_MOD_MAX; i++) { \ + mod = (io)->mod[i]; \ + if (!mod) \ + continue; \ + ret = rsnd_mod_call(mod, fn, (rdai), (io)); \ + if (ret < 0) \ + break; \ + } \ + ret; \ }) -int rsnd_dai_connect(struct rsnd_dai *rdai, - struct rsnd_mod *mod, - struct rsnd_dai_stream *io) +static int rsnd_dai_connect(struct rsnd_mod *mod, + struct rsnd_dai_stream *io) { if (!mod) return -EIO; - if (!list_empty(&mod->list)) { + if (io->mod[mod->type]) { struct rsnd_priv *priv = rsnd_mod_to_priv(mod); struct device *dev = rsnd_priv_to_dev(priv); @@ -300,14 +357,8 @@ int rsnd_dai_connect(struct rsnd_dai *rdai, return -EIO; } - list_add_tail(&mod->list, &io->head); - - return 0; -} - -int rsnd_dai_disconnect(struct rsnd_mod *mod) -{ - list_del_init(&mod->list); + io->mod[mod->type] = mod; + mod->io = io; return 0; } @@ -316,7 +367,7 @@ int rsnd_dai_id(struct rsnd_priv *priv, struct rsnd_dai *rdai) { int id = rdai - priv->rdai; - if ((id < 0) || (id >= rsnd_dai_nr(priv))) + if ((id < 0) || (id >= rsnd_rdai_nr(priv))) return -EINVAL; return id; @@ -324,7 +375,7 @@ int rsnd_dai_id(struct rsnd_priv *priv, struct rsnd_dai *rdai) struct rsnd_dai *rsnd_dai_get(struct rsnd_priv *priv, int id) { - if ((id < 0) || (id >= rsnd_dai_nr(priv))) + if ((id < 0) || (id >= rsnd_rdai_nr(priv))) return NULL; return priv->rdai + id; @@ -382,10 +433,6 @@ static int rsnd_dai_stream_init(struct rsnd_dai_stream *io, { struct snd_pcm_runtime *runtime = substream->runtime; - if (!list_empty(&io->head)) - return -EIO; - - INIT_LIST_HEAD(&io->head); io->substream = substream; io->byte_pos = 0; io->period_pos = 0; @@ -440,10 +487,6 @@ static int rsnd_soc_dai_trigger(struct snd_pcm_substream *substream, int cmd, if (ret < 0) goto dai_trigger_end; - ret = rsnd_gen_path_init(priv, rdai, io); - if (ret < 0) - goto dai_trigger_end; - ret = rsnd_dai_call(rdai, io, init); if (ret < 0) goto dai_trigger_end; @@ -461,10 +504,6 @@ static int rsnd_soc_dai_trigger(struct snd_pcm_substream *substream, int cmd, if (ret < 0) goto dai_trigger_end; - ret = rsnd_gen_path_exit(priv, rdai, io); - if (ret < 0) - goto dai_trigger_end; - ret = rsnd_platform_call(priv, dai, stop, ssi_id); if (ret < 0) goto dai_trigger_end; @@ -486,10 +525,10 @@ static int rsnd_soc_dai_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) /* set master/slave audio interface */ switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { case SND_SOC_DAIFMT_CBM_CFM: - rdai->clk_master = 1; + rdai->clk_master = 0; break; case SND_SOC_DAIFMT_CBS_CFS: - rdai->clk_master = 0; + rdai->clk_master = 1; /* codec is slave, cpu is master */ break; default: return -EINVAL; @@ -540,24 +579,174 @@ static const struct snd_soc_dai_ops rsnd_soc_dai_ops = { .set_fmt = rsnd_soc_dai_set_fmt, }; +static int rsnd_path_init(struct rsnd_priv *priv, + struct rsnd_dai *rdai, + struct rsnd_dai_stream *io) +{ + struct rsnd_mod *mod; + struct rsnd_dai_platform_info *dai_info = rdai->info; + int ret; + int ssi_id = -1; + int src_id = -1; + + /* + * Gen1 is created by SRU/SSI, and this SRU is base module of + * Gen2's SCU/SSIU/SSI. (Gen2 SCU/SSIU came from SRU) + * + * Easy image is.. + * Gen1 SRU = Gen2 SCU + SSIU + etc + * + * Gen2 SCU path is very flexible, but, Gen1 SRU (SCU parts) is + * using fixed path. + */ + if (dai_info) { + if (rsnd_is_enable_path(io, ssi)) + ssi_id = rsnd_info_id(priv, io, ssi); + if (rsnd_is_enable_path(io, src)) + src_id = rsnd_info_id(priv, io, src); + } else { + /* get SSI's ID */ + mod = rsnd_ssi_mod_get_frm_dai(priv, + rsnd_dai_id(priv, rdai), + rsnd_dai_is_play(rdai, io)); + if (!mod) + return 0; + ssi_id = src_id = rsnd_mod_id(mod); + } + + ret = 0; + + /* SRC */ + if (src_id >= 0) { + mod = rsnd_src_mod_get(priv, src_id); + ret = rsnd_dai_connect(mod, io); + if (ret < 0) + return ret; + } + + /* SSI */ + if (ssi_id >= 0) { + mod = rsnd_ssi_mod_get(priv, ssi_id); + ret = rsnd_dai_connect(mod, io); + if (ret < 0) + return ret; + } + + return ret; +} + +static void rsnd_of_parse_dai(struct platform_device *pdev, + const struct rsnd_of_data *of_data, + struct rsnd_priv *priv) +{ + struct device_node *dai_node, *dai_np; + struct device_node *ssi_node, *ssi_np; + struct device_node *src_node, *src_np; + struct device_node *playback, *capture; + struct rsnd_dai_platform_info *dai_info; + struct rcar_snd_info *info = rsnd_priv_to_info(priv); + struct device *dev = &pdev->dev; + int nr, i; + int dai_i, ssi_i, src_i; + + if (!of_data) + return; + + dai_node = of_get_child_by_name(dev->of_node, "rcar_sound,dai"); + if (!dai_node) + return; + + nr = of_get_child_count(dai_node); + if (!nr) + return; + + dai_info = devm_kzalloc(dev, + sizeof(struct rsnd_dai_platform_info) * nr, + GFP_KERNEL); + if (!dai_info) { + dev_err(dev, "dai info allocation error\n"); + return; + } + + info->dai_info_nr = nr; + info->dai_info = dai_info; + + ssi_node = of_get_child_by_name(dev->of_node, "rcar_sound,ssi"); + src_node = of_get_child_by_name(dev->of_node, "rcar_sound,src"); + +#define mod_parse(name) \ +if (name##_node) { \ + struct rsnd_##name##_platform_info *name##_info; \ + \ + name##_i = 0; \ + for_each_child_of_node(name##_node, name##_np) { \ + name##_info = info->name##_info + name##_i; \ + \ + if (name##_np == playback) \ + dai_info->playback.name = name##_info; \ + if (name##_np == capture) \ + dai_info->capture.name = name##_info; \ + \ + name##_i++; \ + } \ +} + + /* + * parse all dai + */ + dai_i = 0; + for_each_child_of_node(dai_node, dai_np) { + dai_info = info->dai_info + dai_i; + + for (i = 0;; i++) { + + playback = of_parse_phandle(dai_np, "playback", i); + capture = of_parse_phandle(dai_np, "capture", i); + + if (!playback && !capture) + break; + + mod_parse(ssi); + mod_parse(src); + + if (playback) + of_node_put(playback); + if (capture) + of_node_put(capture); + } + + dai_i++; + } +} + static int rsnd_dai_probe(struct platform_device *pdev, - struct rcar_snd_info *info, + const struct rsnd_of_data *of_data, struct rsnd_priv *priv) { struct snd_soc_dai_driver *drv; + struct rcar_snd_info *info = rsnd_priv_to_info(priv); struct rsnd_dai *rdai; struct rsnd_mod *pmod, *cmod; struct device *dev = rsnd_priv_to_dev(priv); int dai_nr; int i; - /* get max dai nr */ - for (dai_nr = 0; dai_nr < 32; dai_nr++) { - pmod = rsnd_ssi_mod_get_frm_dai(priv, dai_nr, 1); - cmod = rsnd_ssi_mod_get_frm_dai(priv, dai_nr, 0); + rsnd_of_parse_dai(pdev, of_data, priv); - if (!pmod && !cmod) - break; + /* + * dai_nr should be set via dai_info_nr, + * but allow it to keeping compatible + */ + dai_nr = info->dai_info_nr; + if (!dai_nr) { + /* get max dai nr */ + for (dai_nr = 0; dai_nr < 32; dai_nr++) { + pmod = rsnd_ssi_mod_get_frm_dai(priv, dai_nr, 1); + cmod = rsnd_ssi_mod_get_frm_dai(priv, dai_nr, 0); + + if (!pmod && !cmod) + break; + } } if (!dai_nr) { @@ -572,7 +761,13 @@ static int rsnd_dai_probe(struct platform_device *pdev, return -ENOMEM; } + priv->rdai_nr = dai_nr; + priv->daidrv = drv; + priv->rdai = rdai; + for (i = 0; i < dai_nr; i++) { + if (info->dai_info) + rdai[i].info = &info->dai_info[i]; pmod = rsnd_ssi_mod_get_frm_dai(priv, i, 1); cmod = rsnd_ssi_mod_get_frm_dai(priv, i, 0); @@ -580,9 +775,6 @@ static int rsnd_dai_probe(struct platform_device *pdev, /* * init rsnd_dai */ - INIT_LIST_HEAD(&rdai[i].playback.head); - INIT_LIST_HEAD(&rdai[i].capture.head); - snprintf(rdai[i].name, RSND_DAI_NAME_SIZE, "rsnd-dai.%d", i); /* @@ -595,12 +787,20 @@ static int rsnd_dai_probe(struct platform_device *pdev, drv[i].playback.formats = RSND_FMTS; drv[i].playback.channels_min = 2; drv[i].playback.channels_max = 2; + + if (info->dai_info) + rdai[i].playback.info = &info->dai_info[i].playback; + rsnd_path_init(priv, &rdai[i], &rdai[i].playback); } if (cmod) { drv[i].capture.rates = RSND_RATES; drv[i].capture.formats = RSND_FMTS; drv[i].capture.channels_min = 2; drv[i].capture.channels_max = 2; + + if (info->dai_info) + rdai[i].capture.info = &info->dai_info[i].capture; + rsnd_path_init(priv, &rdai[i], &rdai[i].capture); } dev_dbg(dev, "%s (%s/%s)\n", rdai[i].name, @@ -608,18 +808,9 @@ static int rsnd_dai_probe(struct platform_device *pdev, cmod ? "capture" : " -- "); } - priv->dai_nr = dai_nr; - priv->daidrv = drv; - priv->rdai = rdai; - return 0; } -static void rsnd_dai_remove(struct platform_device *pdev, - struct rsnd_priv *priv) -{ -} - /* * pcm ops */ @@ -713,9 +904,30 @@ static int rsnd_probe(struct platform_device *pdev) struct rcar_snd_info *info; struct rsnd_priv *priv; struct device *dev = &pdev->dev; - int ret; + struct rsnd_dai *rdai; + const struct of_device_id *of_id = of_match_device(rsnd_of_match, dev); + const struct rsnd_of_data *of_data; + int (*probe_func[])(struct platform_device *pdev, + const struct rsnd_of_data *of_data, + struct rsnd_priv *priv) = { + rsnd_gen_probe, + rsnd_ssi_probe, + rsnd_src_probe, + rsnd_adg_probe, + rsnd_dai_probe, + }; + int ret, i; + + info = NULL; + of_data = NULL; + if (of_id) { + info = devm_kzalloc(&pdev->dev, + sizeof(struct rcar_snd_info), GFP_KERNEL); + of_data = of_id->data; + } else { + info = pdev->dev.platform_data; + } - info = pdev->dev.platform_data; if (!info) { dev_err(dev, "driver needs R-Car sound information\n"); return -ENODEV; @@ -737,25 +949,21 @@ static int rsnd_probe(struct platform_device *pdev) /* * init each module */ - ret = rsnd_gen_probe(pdev, info, priv); - if (ret < 0) - return ret; - - ret = rsnd_scu_probe(pdev, info, priv); - if (ret < 0) - return ret; + for (i = 0; i < ARRAY_SIZE(probe_func); i++) { + ret = probe_func[i](pdev, of_data, priv); + if (ret) + return ret; + } - ret = rsnd_adg_probe(pdev, info, priv); - if (ret < 0) - return ret; + for_each_rsnd_dai(rdai, priv, i) { + ret = rsnd_dai_call(rdai, &rdai->playback, probe); + if (ret) + return ret; - ret = rsnd_ssi_probe(pdev, info, priv); - if (ret < 0) - return ret; - - ret = rsnd_dai_probe(pdev, info, priv); - if (ret < 0) - return ret; + ret = rsnd_dai_call(rdai, &rdai->capture, probe); + if (ret) + return ret; + } /* * asoc register @@ -767,7 +975,7 @@ static int rsnd_probe(struct platform_device *pdev) } ret = snd_soc_register_component(dev, &rsnd_soc_component, - priv->daidrv, rsnd_dai_nr(priv)); + priv->daidrv, rsnd_rdai_nr(priv)); if (ret < 0) { dev_err(dev, "cannot snd dai register\n"); goto exit_snd_soc; @@ -789,17 +997,20 @@ exit_snd_soc: static int rsnd_remove(struct platform_device *pdev) { struct rsnd_priv *priv = dev_get_drvdata(&pdev->dev); + struct rsnd_dai *rdai; + int ret, i; pm_runtime_disable(&pdev->dev); - /* - * remove each module - */ - rsnd_ssi_remove(pdev, priv); - rsnd_adg_remove(pdev, priv); - rsnd_scu_remove(pdev, priv); - rsnd_dai_remove(pdev, priv); - rsnd_gen_remove(pdev, priv); + for_each_rsnd_dai(rdai, priv, i) { + ret = rsnd_dai_call(rdai, &rdai->playback, remove); + if (ret) + return ret; + + ret = rsnd_dai_call(rdai, &rdai->capture, remove); + if (ret) + return ret; + } return 0; } @@ -807,6 +1018,7 @@ static int rsnd_remove(struct platform_device *pdev) static struct platform_driver rsnd_driver = { .driver = { .name = "rcar_sound", + .of_match_table = rsnd_of_match, }, .probe = rsnd_probe, .remove = rsnd_remove, diff --git a/sound/soc/sh/rcar/gen.c b/sound/soc/sh/rcar/gen.c index add088bd4b2..50a1ef3eb1c 100644 --- a/sound/soc/sh/rcar/gen.c +++ b/sound/soc/sh/rcar/gen.c @@ -155,62 +155,6 @@ static int rsnd_gen_regmap_init(struct rsnd_priv *priv, return 0; } -int rsnd_gen_path_init(struct rsnd_priv *priv, - struct rsnd_dai *rdai, - struct rsnd_dai_stream *io) -{ - struct rsnd_mod *mod; - int ret; - int id; - - /* - * Gen1 is created by SRU/SSI, and this SRU is base module of - * Gen2's SCU/SSIU/SSI. (Gen2 SCU/SSIU came from SRU) - * - * Easy image is.. - * Gen1 SRU = Gen2 SCU + SSIU + etc - * - * Gen2 SCU path is very flexible, but, Gen1 SRU (SCU parts) is - * using fixed path. - * - * Then, SSI id = SCU id here - */ - - /* get SSI's ID */ - mod = rsnd_ssi_mod_get_frm_dai(priv, - rsnd_dai_id(priv, rdai), - rsnd_dai_is_play(rdai, io)); - id = rsnd_mod_id(mod); - - /* SSI */ - mod = rsnd_ssi_mod_get(priv, id); - ret = rsnd_dai_connect(rdai, mod, io); - if (ret < 0) - return ret; - - /* SCU */ - mod = rsnd_scu_mod_get(priv, id); - ret = rsnd_dai_connect(rdai, mod, io); - - return ret; -} - -int rsnd_gen_path_exit(struct rsnd_priv *priv, - struct rsnd_dai *rdai, - struct rsnd_dai_stream *io) -{ - struct rsnd_mod *mod, *n; - int ret = 0; - - /* - * remove all mod from rdai - */ - for_each_rsnd_mod(mod, n, io) - ret |= rsnd_dai_disconnect(mod); - - return ret; -} - /* * Gen2 */ @@ -229,14 +173,40 @@ static int rsnd_gen2_regmap_init(struct rsnd_priv *priv, struct rsnd_gen *gen) RSND_GEN2_S_REG(gen, SSIU, SSI_MODE0, 0x800), RSND_GEN2_S_REG(gen, SSIU, SSI_MODE1, 0x804), /* FIXME: it needs SSI_MODE2/3 in the future */ + RSND_GEN2_M_REG(gen, SSIU, SSI_BUSIF_MODE, 0x0, 0x80), + RSND_GEN2_M_REG(gen, SSIU, SSI_BUSIF_ADINR,0x4, 0x80), + RSND_GEN2_M_REG(gen, SSIU, SSI_CTRL, 0x10, 0x80), RSND_GEN2_M_REG(gen, SSIU, INT_ENABLE, 0x18, 0x80), + RSND_GEN2_M_REG(gen, SCU, SRC_BUSIF_MODE, 0x0, 0x20), + RSND_GEN2_M_REG(gen, SCU, SRC_ROUTE_MODE0,0xc, 0x20), + RSND_GEN2_M_REG(gen, SCU, SRC_CTRL, 0x10, 0x20), + RSND_GEN2_M_REG(gen, SCU, SRC_SWRSR, 0x200, 0x40), + RSND_GEN2_M_REG(gen, SCU, SRC_SRCIR, 0x204, 0x40), + RSND_GEN2_M_REG(gen, SCU, SRC_ADINR, 0x214, 0x40), + RSND_GEN2_M_REG(gen, SCU, SRC_IFSCR, 0x21c, 0x40), + RSND_GEN2_M_REG(gen, SCU, SRC_IFSVR, 0x220, 0x40), + RSND_GEN2_M_REG(gen, SCU, SRC_SRCCR, 0x224, 0x40), + RSND_GEN2_M_REG(gen, SCU, SRC_BSDSR, 0x22c, 0x40), + RSND_GEN2_M_REG(gen, SCU, SRC_BSISR, 0x238, 0x40), + RSND_GEN2_S_REG(gen, ADG, BRRA, 0x00), RSND_GEN2_S_REG(gen, ADG, BRRB, 0x04), RSND_GEN2_S_REG(gen, ADG, SSICKR, 0x08), RSND_GEN2_S_REG(gen, ADG, AUDIO_CLK_SEL0, 0x0c), RSND_GEN2_S_REG(gen, ADG, AUDIO_CLK_SEL1, 0x10), RSND_GEN2_S_REG(gen, ADG, AUDIO_CLK_SEL2, 0x14), + RSND_GEN2_S_REG(gen, ADG, DIV_EN, 0x30), + RSND_GEN2_S_REG(gen, ADG, SRCIN_TIMSEL0, 0x34), + RSND_GEN2_S_REG(gen, ADG, SRCIN_TIMSEL1, 0x38), + RSND_GEN2_S_REG(gen, ADG, SRCIN_TIMSEL2, 0x3c), + RSND_GEN2_S_REG(gen, ADG, SRCIN_TIMSEL3, 0x40), + RSND_GEN2_S_REG(gen, ADG, SRCIN_TIMSEL4, 0x44), + RSND_GEN2_S_REG(gen, ADG, SRCOUT_TIMSEL0, 0x48), + RSND_GEN2_S_REG(gen, ADG, SRCOUT_TIMSEL1, 0x4c), + RSND_GEN2_S_REG(gen, ADG, SRCOUT_TIMSEL2, 0x50), + RSND_GEN2_S_REG(gen, ADG, SRCOUT_TIMSEL3, 0x54), + RSND_GEN2_S_REG(gen, ADG, SRCOUT_TIMSEL4, 0x58), RSND_GEN2_M_REG(gen, SSI, SSICR, 0x00, 0x40), RSND_GEN2_M_REG(gen, SSI, SSISR, 0x04, 0x40), @@ -249,7 +219,6 @@ static int rsnd_gen2_regmap_init(struct rsnd_priv *priv, struct rsnd_gen *gen) } static int rsnd_gen2_probe(struct platform_device *pdev, - struct rcar_snd_info *info, struct rsnd_priv *priv) { struct device *dev = rsnd_priv_to_dev(priv); @@ -283,7 +252,7 @@ static int rsnd_gen2_probe(struct platform_device *pdev, return ret; dev_dbg(dev, "Gen2 device probed\n"); - dev_dbg(dev, "SRU : %08x => %p\n", scu_res->start, + dev_dbg(dev, "SCU : %08x => %p\n", scu_res->start, gen->base[RSND_GEN2_SCU]); dev_dbg(dev, "ADG : %08x => %p\n", adg_res->start, gen->base[RSND_GEN2_ADG]); @@ -317,7 +286,7 @@ static int rsnd_gen1_regmap_init(struct rsnd_priv *priv, struct rsnd_gen *gen) RSND_GEN1_S_REG(gen, SRU, SRC_ROUTE_CTRL, 0xc0), RSND_GEN1_S_REG(gen, SRU, SSI_MODE0, 0xD0), RSND_GEN1_S_REG(gen, SRU, SSI_MODE1, 0xD4), - RSND_GEN1_M_REG(gen, SRU, BUSIF_MODE, 0x20, 0x4), + RSND_GEN1_M_REG(gen, SRU, SRC_BUSIF_MODE, 0x20, 0x4), RSND_GEN1_M_REG(gen, SRU, SRC_ROUTE_MODE0,0x50, 0x8), RSND_GEN1_M_REG(gen, SRU, SRC_SWRSR, 0x200, 0x40), RSND_GEN1_M_REG(gen, SRU, SRC_SRCIR, 0x204, 0x40), @@ -347,7 +316,6 @@ static int rsnd_gen1_regmap_init(struct rsnd_priv *priv, struct rsnd_gen *gen) } static int rsnd_gen1_probe(struct platform_device *pdev, - struct rcar_snd_info *info, struct rsnd_priv *priv) { struct device *dev = rsnd_priv_to_dev(priv); @@ -391,14 +359,28 @@ static int rsnd_gen1_probe(struct platform_device *pdev, /* * Gen */ +static void rsnd_of_parse_gen(struct platform_device *pdev, + const struct rsnd_of_data *of_data, + struct rsnd_priv *priv) +{ + struct rcar_snd_info *info = priv->info; + + if (!of_data) + return; + + info->flags = of_data->flags; +} + int rsnd_gen_probe(struct platform_device *pdev, - struct rcar_snd_info *info, + const struct rsnd_of_data *of_data, struct rsnd_priv *priv) { struct device *dev = rsnd_priv_to_dev(priv); struct rsnd_gen *gen; int ret; + rsnd_of_parse_gen(pdev, of_data, priv); + gen = devm_kzalloc(dev, sizeof(*gen), GFP_KERNEL); if (!gen) { dev_err(dev, "GEN allocate failed\n"); @@ -409,17 +391,12 @@ int rsnd_gen_probe(struct platform_device *pdev, ret = -ENODEV; if (rsnd_is_gen1(priv)) - ret = rsnd_gen1_probe(pdev, info, priv); + ret = rsnd_gen1_probe(pdev, priv); else if (rsnd_is_gen2(priv)) - ret = rsnd_gen2_probe(pdev, info, priv); + ret = rsnd_gen2_probe(pdev, priv); if (ret < 0) dev_err(dev, "unknown generation R-Car sound device\n"); return ret; } - -void rsnd_gen_remove(struct platform_device *pdev, - struct rsnd_priv *priv) -{ -} diff --git a/sound/soc/sh/rcar/rsnd.h b/sound/soc/sh/rcar/rsnd.h index 4ca66cd899c..619d198c7d2 100644 --- a/sound/soc/sh/rcar/rsnd.h +++ b/sound/soc/sh/rcar/rsnd.h @@ -17,6 +17,8 @@ #include <linux/io.h> #include <linux/list.h> #include <linux/module.h> +#include <linux/of_device.h> +#include <linux/of_irq.h> #include <linux/sh_dma.h> #include <linux/workqueue.h> #include <sound/rcar_snd.h> @@ -32,15 +34,9 @@ */ enum rsnd_reg { /* SRU/SCU/SSIU */ - RSND_REG_SRC_ROUTE_SEL, /* for Gen1 */ - RSND_REG_SRC_TMG_SEL0, /* for Gen1 */ - RSND_REG_SRC_TMG_SEL1, /* for Gen1 */ - RSND_REG_SRC_TMG_SEL2, /* for Gen1 */ - RSND_REG_SRC_ROUTE_CTRL, /* for Gen1 */ RSND_REG_SSI_MODE0, RSND_REG_SSI_MODE1, - RSND_REG_BUSIF_MODE, - RSND_REG_INT_ENABLE, /* for Gen2 */ + RSND_REG_SRC_BUSIF_MODE, RSND_REG_SRC_ROUTE_MODE0, RSND_REG_SRC_SWRSR, RSND_REG_SRC_SRCIR, @@ -48,7 +44,6 @@ enum rsnd_reg { RSND_REG_SRC_IFSCR, RSND_REG_SRC_IFSVR, RSND_REG_SRC_SRCCR, - RSND_REG_SRC_MNFSR, /* ADG */ RSND_REG_BRRA, @@ -56,10 +51,6 @@ enum rsnd_reg { RSND_REG_SSICKR, RSND_REG_AUDIO_CLK_SEL0, RSND_REG_AUDIO_CLK_SEL1, - RSND_REG_AUDIO_CLK_SEL2, - RSND_REG_AUDIO_CLK_SEL3, /* for Gen1 */ - RSND_REG_AUDIO_CLK_SEL4, /* for Gen1 */ - RSND_REG_AUDIO_CLK_SEL5, /* for Gen1 */ /* SSI */ RSND_REG_SSICR, @@ -68,9 +59,63 @@ enum rsnd_reg { RSND_REG_SSIRDR, RSND_REG_SSIWSR, + /* SHARE see below */ + RSND_REG_SHARE01, + RSND_REG_SHARE02, + RSND_REG_SHARE03, + RSND_REG_SHARE04, + RSND_REG_SHARE05, + RSND_REG_SHARE06, + RSND_REG_SHARE07, + RSND_REG_SHARE08, + RSND_REG_SHARE09, + RSND_REG_SHARE10, + RSND_REG_SHARE11, + RSND_REG_SHARE12, + RSND_REG_SHARE13, + RSND_REG_SHARE14, + RSND_REG_SHARE15, + RSND_REG_SHARE16, + RSND_REG_SHARE17, + RSND_REG_SHARE18, + RSND_REG_SHARE19, + RSND_REG_MAX, }; +/* Gen1 only */ +#define RSND_REG_SRC_ROUTE_SEL RSND_REG_SHARE01 +#define RSND_REG_SRC_TMG_SEL0 RSND_REG_SHARE02 +#define RSND_REG_SRC_TMG_SEL1 RSND_REG_SHARE03 +#define RSND_REG_SRC_TMG_SEL2 RSND_REG_SHARE04 +#define RSND_REG_SRC_ROUTE_CTRL RSND_REG_SHARE05 +#define RSND_REG_SRC_MNFSR RSND_REG_SHARE06 +#define RSND_REG_AUDIO_CLK_SEL3 RSND_REG_SHARE07 +#define RSND_REG_AUDIO_CLK_SEL4 RSND_REG_SHARE08 +#define RSND_REG_AUDIO_CLK_SEL5 RSND_REG_SHARE09 + +/* Gen2 only */ +#define RSND_REG_SRC_CTRL RSND_REG_SHARE01 +#define RSND_REG_SSI_CTRL RSND_REG_SHARE02 +#define RSND_REG_SSI_BUSIF_MODE RSND_REG_SHARE03 +#define RSND_REG_SSI_BUSIF_ADINR RSND_REG_SHARE04 +#define RSND_REG_INT_ENABLE RSND_REG_SHARE05 +#define RSND_REG_SRC_BSDSR RSND_REG_SHARE06 +#define RSND_REG_SRC_BSISR RSND_REG_SHARE07 +#define RSND_REG_DIV_EN RSND_REG_SHARE08 +#define RSND_REG_SRCIN_TIMSEL0 RSND_REG_SHARE09 +#define RSND_REG_SRCIN_TIMSEL1 RSND_REG_SHARE10 +#define RSND_REG_SRCIN_TIMSEL2 RSND_REG_SHARE11 +#define RSND_REG_SRCIN_TIMSEL3 RSND_REG_SHARE12 +#define RSND_REG_SRCIN_TIMSEL4 RSND_REG_SHARE13 +#define RSND_REG_SRCOUT_TIMSEL0 RSND_REG_SHARE14 +#define RSND_REG_SRCOUT_TIMSEL1 RSND_REG_SHARE15 +#define RSND_REG_SRCOUT_TIMSEL2 RSND_REG_SHARE16 +#define RSND_REG_SRCOUT_TIMSEL3 RSND_REG_SHARE17 +#define RSND_REG_SRCOUT_TIMSEL4 RSND_REG_SHARE18 +#define RSND_REG_AUDIO_CLK_SEL2 RSND_REG_SHARE19 + +struct rsnd_of_data; struct rsnd_priv; struct rsnd_mod; struct rsnd_dai; @@ -96,24 +141,20 @@ void rsnd_bset(struct rsnd_priv *priv, struct rsnd_mod *mod, enum rsnd_reg reg, * R-Car DMA */ struct rsnd_dma { - struct rsnd_priv *priv; struct sh_dmae_slave slave; struct work_struct work; struct dma_chan *chan; enum dma_data_direction dir; - int (*inquiry)(struct rsnd_dma *dma, dma_addr_t *buf, int *len); - int (*complete)(struct rsnd_dma *dma); int submit_loop; + int offset; /* it cares A/B plane */ }; void rsnd_dma_start(struct rsnd_dma *dma); void rsnd_dma_stop(struct rsnd_dma *dma); int rsnd_dma_available(struct rsnd_dma *dma); int rsnd_dma_init(struct rsnd_priv *priv, struct rsnd_dma *dma, - int is_play, int id, - int (*inquiry)(struct rsnd_dma *dma, dma_addr_t *buf, int *len), - int (*complete)(struct rsnd_dma *dma)); + int is_play, int id); void rsnd_dma_quit(struct rsnd_priv *priv, struct rsnd_dma *dma); @@ -121,9 +162,20 @@ void rsnd_dma_quit(struct rsnd_priv *priv, /* * R-Car sound mod */ +enum rsnd_mod_type { + RSND_MOD_SRC = 0, + RSND_MOD_SSI, + RSND_MOD_MAX, +}; struct rsnd_mod_ops { char *name; + int (*probe)(struct rsnd_mod *mod, + struct rsnd_dai *rdai, + struct rsnd_dai_stream *io); + int (*remove)(struct rsnd_mod *mod, + struct rsnd_dai *rdai, + struct rsnd_dai_stream *io); int (*init)(struct rsnd_mod *mod, struct rsnd_dai *rdai, struct rsnd_dai_stream *io); @@ -138,28 +190,26 @@ struct rsnd_mod_ops { struct rsnd_dai_stream *io); }; +struct rsnd_dai_stream; struct rsnd_mod { int id; + enum rsnd_mod_type type; struct rsnd_priv *priv; struct rsnd_mod_ops *ops; - struct list_head list; /* connect to rsnd_dai playback/capture */ struct rsnd_dma dma; + struct rsnd_dai_stream *io; }; #define rsnd_mod_to_priv(mod) ((mod)->priv) #define rsnd_mod_to_dma(mod) (&(mod)->dma) #define rsnd_dma_to_mod(_dma) container_of((_dma), struct rsnd_mod, dma) +#define rsnd_mod_to_io(mod) ((mod)->io) #define rsnd_mod_id(mod) ((mod)->id) -#define for_each_rsnd_mod(pos, n, io) \ - list_for_each_entry_safe(pos, n, &(io)->head, list) -#define rsnd_mod_call(mod, func, rdai, io) \ - (!(mod) ? -ENODEV : \ - !((mod)->ops->func) ? 0 : \ - (mod)->ops->func(mod, rdai, io)) void rsnd_mod_init(struct rsnd_priv *priv, struct rsnd_mod *mod, struct rsnd_mod_ops *ops, + enum rsnd_mod_type type, int id); char *rsnd_mod_name(struct rsnd_mod *mod); @@ -168,13 +218,16 @@ char *rsnd_mod_name(struct rsnd_mod *mod); */ #define RSND_DAI_NAME_SIZE 16 struct rsnd_dai_stream { - struct list_head head; /* head of rsnd_mod list */ struct snd_pcm_substream *substream; + struct rsnd_mod *mod[RSND_MOD_MAX]; + struct rsnd_dai_path_info *info; /* rcar_snd.h */ int byte_pos; int period_pos; int byte_per_period; int next_period_byte; }; +#define rsnd_io_to_mod_ssi(io) ((io)->mod[RSND_MOD_SSI]) +#define rsnd_io_to_mod_src(io) ((io)->mod[RSND_MOD_SRC]) struct rsnd_dai { char name[RSND_DAI_NAME_SIZE]; @@ -189,16 +242,14 @@ struct rsnd_dai { unsigned int data_alignment:1; }; -#define rsnd_dai_nr(priv) ((priv)->dai_nr) +#define rsnd_rdai_nr(priv) ((priv)->rdai_nr) #define for_each_rsnd_dai(rdai, priv, i) \ - for (i = 0, (rdai) = rsnd_dai_get(priv, i); \ - i < rsnd_dai_nr(priv); \ - i++, (rdai) = rsnd_dai_get(priv, i)) + for (i = 0; \ + (i < rsnd_rdai_nr(priv)) && \ + ((rdai) = rsnd_dai_get(priv, i)); \ + i++) struct rsnd_dai *rsnd_dai_get(struct rsnd_priv *priv, int id); -int rsnd_dai_disconnect(struct rsnd_mod *mod); -int rsnd_dai_connect(struct rsnd_dai *rdai, struct rsnd_mod *mod, - struct rsnd_dai_stream *io); int rsnd_dai_is_play(struct rsnd_dai *rdai, struct rsnd_dai_stream *io); int rsnd_dai_id(struct rsnd_priv *priv, struct rsnd_dai *rdai); #define rsnd_dai_get_platform_info(rdai) ((rdai)->info) @@ -206,21 +257,14 @@ int rsnd_dai_id(struct rsnd_priv *priv, struct rsnd_dai *rdai); void rsnd_dai_pointer_update(struct rsnd_dai_stream *io, int cnt); int rsnd_dai_pointer_offset(struct rsnd_dai_stream *io, int additional); +#define rsnd_dai_is_clk_master(rdai) ((rdai)->clk_master) /* * R-Car Gen1/Gen2 */ int rsnd_gen_probe(struct platform_device *pdev, - struct rcar_snd_info *info, + const struct rsnd_of_data *of_data, struct rsnd_priv *priv); -void rsnd_gen_remove(struct platform_device *pdev, - struct rsnd_priv *priv); -int rsnd_gen_path_init(struct rsnd_priv *priv, - struct rsnd_dai *rdai, - struct rsnd_dai_stream *io); -int rsnd_gen_path_exit(struct rsnd_priv *priv, - struct rsnd_dai *rdai, - struct rsnd_dai_stream *io); void __iomem *rsnd_gen_reg_get(struct rsnd_priv *priv, struct rsnd_mod *mod, enum rsnd_reg reg); @@ -233,18 +277,28 @@ void __iomem *rsnd_gen_reg_get(struct rsnd_priv *priv, int rsnd_adg_ssi_clk_stop(struct rsnd_mod *mod); int rsnd_adg_ssi_clk_try_start(struct rsnd_mod *mod, unsigned int rate); int rsnd_adg_probe(struct platform_device *pdev, - struct rcar_snd_info *info, + const struct rsnd_of_data *of_data, struct rsnd_priv *priv); -void rsnd_adg_remove(struct platform_device *pdev, - struct rsnd_priv *priv); -int rsnd_adg_set_convert_clk(struct rsnd_priv *priv, - struct rsnd_mod *mod, - unsigned int src_rate, - unsigned int dst_rate); +int rsnd_adg_set_convert_clk_gen1(struct rsnd_priv *priv, + struct rsnd_mod *mod, + unsigned int src_rate, + unsigned int dst_rate); +int rsnd_adg_set_convert_clk_gen2(struct rsnd_mod *mod, + struct rsnd_dai *rdai, + struct rsnd_dai_stream *io, + unsigned int src_rate, + unsigned int dst_rate); +int rsnd_adg_set_convert_timing_gen2(struct rsnd_mod *mod, + struct rsnd_dai *rdai, + struct rsnd_dai_stream *io); /* * R-Car sound priv */ +struct rsnd_of_data { + u32 flags; +}; + struct rsnd_priv { struct device *dev; @@ -257,10 +311,10 @@ struct rsnd_priv { void *gen; /* - * below value will be filled on rsnd_scu_probe() + * below value will be filled on rsnd_src_probe() */ - void *scu; - int scu_nr; + void *src; + int src_nr; /* * below value will be filled on rsnd_adg_probe() @@ -270,46 +324,64 @@ struct rsnd_priv { /* * below value will be filled on rsnd_ssi_probe() */ - void *ssiu; + void *ssi; + int ssi_nr; /* * below value will be filled on rsnd_dai_probe() */ struct snd_soc_dai_driver *daidrv; struct rsnd_dai *rdai; - int dai_nr; + int rdai_nr; }; #define rsnd_priv_to_dev(priv) ((priv)->dev) +#define rsnd_priv_to_info(priv) ((priv)->info) #define rsnd_lock(priv, flags) spin_lock_irqsave(&priv->lock, flags) #define rsnd_unlock(priv, flags) spin_unlock_irqrestore(&priv->lock, flags) +#define rsnd_info_is_playback(priv, type) \ +({ \ + struct rcar_snd_info *info = rsnd_priv_to_info(priv); \ + int i, is_play = 0; \ + for (i = 0; i < info->dai_info_nr; i++) { \ + if (info->dai_info[i].playback.type == (type)->info) { \ + is_play = 1; \ + break; \ + } \ + } \ + is_play; \ +}) + /* - * R-Car SCU + * R-Car SRC */ -int rsnd_scu_probe(struct platform_device *pdev, - struct rcar_snd_info *info, +int rsnd_src_probe(struct platform_device *pdev, + const struct rsnd_of_data *of_data, struct rsnd_priv *priv); -void rsnd_scu_remove(struct platform_device *pdev, - struct rsnd_priv *priv); -struct rsnd_mod *rsnd_scu_mod_get(struct rsnd_priv *priv, int id); -bool rsnd_scu_hpbif_is_enable(struct rsnd_mod *mod); -unsigned int rsnd_scu_get_ssi_rate(struct rsnd_priv *priv, - struct rsnd_mod *ssi_mod, +struct rsnd_mod *rsnd_src_mod_get(struct rsnd_priv *priv, int id); +unsigned int rsnd_src_get_ssi_rate(struct rsnd_priv *priv, + struct rsnd_dai_stream *io, struct snd_pcm_runtime *runtime); +int rsnd_src_ssi_mode_init(struct rsnd_mod *ssi_mod, + struct rsnd_dai *rdai, + struct rsnd_dai_stream *io); +int rsnd_src_enable_ssi_irq(struct rsnd_mod *ssi_mod, + struct rsnd_dai *rdai, + struct rsnd_dai_stream *io); -#define rsnd_scu_nr(priv) ((priv)->scu_nr) +#define rsnd_src_nr(priv) ((priv)->src_nr) /* * R-Car SSI */ int rsnd_ssi_probe(struct platform_device *pdev, - struct rcar_snd_info *info, - struct rsnd_priv *priv); -void rsnd_ssi_remove(struct platform_device *pdev, + const struct rsnd_of_data *of_data, struct rsnd_priv *priv); struct rsnd_mod *rsnd_ssi_mod_get(struct rsnd_priv *priv, int id); struct rsnd_mod *rsnd_ssi_mod_get_frm_dai(struct rsnd_priv *priv, int dai_id, int is_play); +int rsnd_ssi_is_pin_sharing(struct rsnd_mod *mod); +int rsnd_ssi_is_play(struct rsnd_mod *mod); #endif diff --git a/sound/soc/sh/rcar/scu.c b/sound/soc/sh/rcar/scu.c deleted file mode 100644 index 9bb08bb1d45..00000000000 --- a/sound/soc/sh/rcar/scu.c +++ /dev/null @@ -1,384 +0,0 @@ -/* - * Renesas R-Car SCU support - * - * Copyright (C) 2013 Renesas Solutions Corp. - * Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ -#include "rsnd.h" - -struct rsnd_scu { - struct rsnd_scu_platform_info *info; /* rcar_snd.h */ - struct rsnd_mod mod; - struct clk *clk; -}; - -#define rsnd_scu_mode_flags(p) ((p)->info->flags) -#define rsnd_scu_convert_rate(p) ((p)->info->convert_rate) - -#define RSND_SCU_NAME_SIZE 16 - -/* - * ADINR - */ -#define OTBL_24 (0 << 16) -#define OTBL_22 (2 << 16) -#define OTBL_20 (4 << 16) -#define OTBL_18 (6 << 16) -#define OTBL_16 (8 << 16) - -/* - * image of SRC (Sampling Rate Converter) - * - * 96kHz <-> +-----+ 48kHz +-----+ 48kHz +-------+ - * 48kHz <-> | SRC | <------> | SSI | <-----> | codec | - * 44.1kHz <-> +-----+ +-----+ +-------+ - * ... - * - */ - -#define rsnd_mod_to_scu(_mod) \ - container_of((_mod), struct rsnd_scu, mod) - -#define for_each_rsnd_scu(pos, priv, i) \ - for ((i) = 0; \ - ((i) < rsnd_scu_nr(priv)) && \ - ((pos) = (struct rsnd_scu *)(priv)->scu + i); \ - i++) - -/* Gen1 only */ -static int rsnd_src_set_route_if_gen1(struct rsnd_priv *priv, - struct rsnd_mod *mod, - struct rsnd_dai *rdai, - struct rsnd_dai_stream *io) -{ - struct scu_route_config { - u32 mask; - int shift; - } routes[] = { - { 0xF, 0, }, /* 0 */ - { 0xF, 4, }, /* 1 */ - { 0xF, 8, }, /* 2 */ - { 0x7, 12, }, /* 3 */ - { 0x7, 16, }, /* 4 */ - { 0x7, 20, }, /* 5 */ - { 0x7, 24, }, /* 6 */ - { 0x3, 28, }, /* 7 */ - { 0x3, 30, }, /* 8 */ - }; - struct rsnd_scu *scu = rsnd_mod_to_scu(mod); - u32 mask; - u32 val; - int shift; - int id; - - /* - * Gen1 only - */ - if (!rsnd_is_gen1(priv)) - return 0; - - id = rsnd_mod_id(mod); - if (id < 0 || id >= ARRAY_SIZE(routes)) - return -EIO; - - /* - * SRC_ROUTE_SELECT - */ - val = rsnd_dai_is_play(rdai, io) ? 0x1 : 0x2; - val = val << routes[id].shift; - mask = routes[id].mask << routes[id].shift; - - rsnd_mod_bset(mod, SRC_ROUTE_SEL, mask, val); - - /* - * SRC_TIMING_SELECT - */ - shift = (id % 4) * 8; - mask = 0x1F << shift; - - /* - * ADG is used as source clock if SRC was used, - * then, SSI WS is used as destination clock. - * SSI WS is used as source clock if SRC is not used - * (when playback, source/destination become reverse when capture) - */ - if (rsnd_scu_convert_rate(scu)) /* use ADG */ - val = 0; - else if (8 == id) /* use SSI WS, but SRU8 is special */ - val = id << shift; - else /* use SSI WS */ - val = (id + 1) << shift; - - switch (id / 4) { - case 0: - rsnd_mod_bset(mod, SRC_TMG_SEL0, mask, val); - break; - case 1: - rsnd_mod_bset(mod, SRC_TMG_SEL1, mask, val); - break; - case 2: - rsnd_mod_bset(mod, SRC_TMG_SEL2, mask, val); - break; - } - - return 0; -} - -unsigned int rsnd_scu_get_ssi_rate(struct rsnd_priv *priv, - struct rsnd_mod *ssi_mod, - struct snd_pcm_runtime *runtime) -{ - struct rsnd_scu *scu; - unsigned int rate; - - /* this function is assuming SSI id = SCU id here */ - scu = rsnd_mod_to_scu(rsnd_scu_mod_get(priv, rsnd_mod_id(ssi_mod))); - - /* - * return convert rate if SRC is used, - * otherwise, return runtime->rate as usual - */ - rate = rsnd_scu_convert_rate(scu); - if (!rate) - rate = runtime->rate; - - return rate; -} - -static int rsnd_scu_convert_rate_ctrl(struct rsnd_priv *priv, - struct rsnd_mod *mod, - struct rsnd_dai *rdai, - struct rsnd_dai_stream *io) -{ - struct snd_pcm_runtime *runtime = rsnd_io_to_runtime(io); - struct rsnd_scu *scu = rsnd_mod_to_scu(mod); - u32 convert_rate = rsnd_scu_convert_rate(scu); - u32 adinr = runtime->channels; - - /* set/clear soft reset */ - rsnd_mod_write(mod, SRC_SWRSR, 0); - rsnd_mod_write(mod, SRC_SWRSR, 1); - - /* Initialize the operation of the SRC internal circuits */ - rsnd_mod_write(mod, SRC_SRCIR, 1); - - /* Set channel number and output bit length */ - switch (runtime->sample_bits) { - case 16: - adinr |= OTBL_16; - break; - case 32: - adinr |= OTBL_24; - break; - default: - return -EIO; - } - rsnd_mod_write(mod, SRC_ADINR, adinr); - - if (convert_rate) { - u32 fsrate = 0x0400000 / convert_rate * runtime->rate; - int ret; - - /* Enable the initial value of IFS */ - rsnd_mod_write(mod, SRC_IFSCR, 1); - - /* Set initial value of IFS */ - rsnd_mod_write(mod, SRC_IFSVR, fsrate); - - /* Select SRC mode (fixed value) */ - rsnd_mod_write(mod, SRC_SRCCR, 0x00010110); - - /* Set the restriction value of the FS ratio (98%) */ - rsnd_mod_write(mod, SRC_MNFSR, fsrate / 100 * 98); - - if (rsnd_is_gen1(priv)) { - /* no SRC_BFSSR settings, since SRC_SRCCR::BUFMD is 0 */ - } - - /* set convert clock */ - ret = rsnd_adg_set_convert_clk(priv, mod, - runtime->rate, - convert_rate); - if (ret < 0) - return ret; - } - - /* Cancel the initialization and operate the SRC function */ - rsnd_mod_write(mod, SRC_SRCIR, 0); - - /* use DMA transfer */ - rsnd_mod_write(mod, BUSIF_MODE, 1); - - return 0; -} - -static int rsnd_scu_transfer_start(struct rsnd_priv *priv, - struct rsnd_mod *mod, - struct rsnd_dai *rdai, - struct rsnd_dai_stream *io) -{ - struct rsnd_scu *scu = rsnd_mod_to_scu(mod); - int id = rsnd_mod_id(mod); - u32 val; - - if (rsnd_is_gen1(priv)) { - val = (1 << id); - rsnd_mod_bset(mod, SRC_ROUTE_CTRL, val, val); - } - - if (rsnd_scu_convert_rate(scu)) - rsnd_mod_write(mod, SRC_ROUTE_MODE0, 1); - - return 0; -} - -static int rsnd_scu_transfer_stop(struct rsnd_priv *priv, - struct rsnd_mod *mod, - struct rsnd_dai *rdai, - struct rsnd_dai_stream *io) -{ - struct rsnd_scu *scu = rsnd_mod_to_scu(mod); - int id = rsnd_mod_id(mod); - u32 mask; - - if (rsnd_is_gen1(priv)) { - mask = (1 << id); - rsnd_mod_bset(mod, SRC_ROUTE_CTRL, mask, 0); - } - - if (rsnd_scu_convert_rate(scu)) - rsnd_mod_write(mod, SRC_ROUTE_MODE0, 0); - - return 0; -} - -bool rsnd_scu_hpbif_is_enable(struct rsnd_mod *mod) -{ - struct rsnd_scu *scu = rsnd_mod_to_scu(mod); - u32 flags = rsnd_scu_mode_flags(scu); - - return !!(flags & RSND_SCU_USE_HPBIF); -} - -static int rsnd_scu_start(struct rsnd_mod *mod, - struct rsnd_dai *rdai, - struct rsnd_dai_stream *io) -{ - struct rsnd_priv *priv = rsnd_mod_to_priv(mod); - struct rsnd_scu *scu = rsnd_mod_to_scu(mod); - struct device *dev = rsnd_priv_to_dev(priv); - int ret; - - /* - * SCU will be used if it has RSND_SCU_USE_HPBIF flags - */ - if (!rsnd_scu_hpbif_is_enable(mod)) { - /* it use PIO transter */ - dev_dbg(dev, "%s%d is not used\n", - rsnd_mod_name(mod), rsnd_mod_id(mod)); - - return 0; - } - - clk_enable(scu->clk); - - /* it use DMA transter */ - - ret = rsnd_src_set_route_if_gen1(priv, mod, rdai, io); - if (ret < 0) - return ret; - - ret = rsnd_scu_convert_rate_ctrl(priv, mod, rdai, io); - if (ret < 0) - return ret; - - ret = rsnd_scu_transfer_start(priv, mod, rdai, io); - if (ret < 0) - return ret; - - dev_dbg(dev, "%s%d start\n", rsnd_mod_name(mod), rsnd_mod_id(mod)); - - return 0; -} - -static int rsnd_scu_stop(struct rsnd_mod *mod, - struct rsnd_dai *rdai, - struct rsnd_dai_stream *io) -{ - struct rsnd_priv *priv = rsnd_mod_to_priv(mod); - struct rsnd_scu *scu = rsnd_mod_to_scu(mod); - - if (!rsnd_scu_hpbif_is_enable(mod)) - return 0; - - rsnd_scu_transfer_stop(priv, mod, rdai, io); - - clk_disable(scu->clk); - - return 0; -} - -static struct rsnd_mod_ops rsnd_scu_ops = { - .name = "scu", - .start = rsnd_scu_start, - .stop = rsnd_scu_stop, -}; - -struct rsnd_mod *rsnd_scu_mod_get(struct rsnd_priv *priv, int id) -{ - if (WARN_ON(id < 0 || id >= rsnd_scu_nr(priv))) - id = 0; - - return &((struct rsnd_scu *)(priv->scu) + id)->mod; -} - -int rsnd_scu_probe(struct platform_device *pdev, - struct rcar_snd_info *info, - struct rsnd_priv *priv) -{ - struct device *dev = rsnd_priv_to_dev(priv); - struct rsnd_scu *scu; - struct clk *clk; - char name[RSND_SCU_NAME_SIZE]; - int i, nr; - - /* - * init SCU - */ - nr = info->scu_info_nr; - scu = devm_kzalloc(dev, sizeof(*scu) * nr, GFP_KERNEL); - if (!scu) { - dev_err(dev, "SCU allocate failed\n"); - return -ENOMEM; - } - - priv->scu_nr = nr; - priv->scu = scu; - - for_each_rsnd_scu(scu, priv, i) { - snprintf(name, RSND_SCU_NAME_SIZE, "scu.%d", i); - - clk = devm_clk_get(dev, name); - if (IS_ERR(clk)) - return PTR_ERR(clk); - - rsnd_mod_init(priv, &scu->mod, - &rsnd_scu_ops, i); - scu->info = &info->scu_info[i]; - scu->clk = clk; - - dev_dbg(dev, "SCU%d probed\n", i); - } - dev_dbg(dev, "scu probed\n"); - - return 0; -} - -void rsnd_scu_remove(struct platform_device *pdev, - struct rsnd_priv *priv) -{ -} diff --git a/sound/soc/sh/rcar/src.c b/sound/soc/sh/rcar/src.c new file mode 100644 index 00000000000..6232b7d307a --- /dev/null +++ b/sound/soc/sh/rcar/src.c @@ -0,0 +1,727 @@ +/* + * Renesas R-Car SRC support + * + * Copyright (C) 2013 Renesas Solutions Corp. + * Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ +#include "rsnd.h" + +struct rsnd_src { + struct rsnd_src_platform_info *info; /* rcar_snd.h */ + struct rsnd_mod mod; + struct clk *clk; +}; + +#define RSND_SRC_NAME_SIZE 16 + +/* + * ADINR + */ +#define OTBL_24 (0 << 16) +#define OTBL_22 (2 << 16) +#define OTBL_20 (4 << 16) +#define OTBL_18 (6 << 16) +#define OTBL_16 (8 << 16) + +#define rsnd_src_mode_flags(p) ((p)->info->flags) +#define rsnd_src_convert_rate(p) ((p)->info->convert_rate) +#define rsnd_mod_to_src(_mod) \ + container_of((_mod), struct rsnd_src, mod) +#define rsnd_src_hpbif_is_enable(src) \ + (rsnd_src_mode_flags(src) & RSND_SCU_USE_HPBIF) +#define rsnd_src_dma_available(src) \ + rsnd_dma_available(rsnd_mod_to_dma(&(src)->mod)) + +#define for_each_rsnd_src(pos, priv, i) \ + for ((i) = 0; \ + ((i) < rsnd_src_nr(priv)) && \ + ((pos) = (struct rsnd_src *)(priv)->src + i); \ + i++) + + +/* + * image of SRC (Sampling Rate Converter) + * + * 96kHz <-> +-----+ 48kHz +-----+ 48kHz +-------+ + * 48kHz <-> | SRC | <------> | SSI | <-----> | codec | + * 44.1kHz <-> +-----+ +-----+ +-------+ + * ... + * + */ + +/* + * src.c is caring... + * + * Gen1 + * + * [mem] -> [SRU] -> [SSI] + * |--------| + * + * Gen2 + * + * [mem] -> [SRC] -> [SSIU] -> [SSI] + * |-----------------| + */ + +/* + * How to use SRC bypass mode for debugging + * + * SRC has bypass mode, and it is useful for debugging. + * In Gen2 case, + * SRCm_MODE controls whether SRC is used or not + * SSI_MODE0 controls whether SSIU which receives SRC data + * is used or not. + * Both SRCm_MODE/SSI_MODE0 settings are needed if you use SRC, + * but SRC bypass mode needs SSI_MODE0 only. + * + * This driver request + * struct rsnd_src_platform_info { + * u32 flags; + * u32 convert_rate; + * } + * + * rsnd_src_hpbif_is_enable() will be true + * if flags had RSND_SRC_USE_HPBIF, + * and it controls whether SSIU is used or not. + * + * rsnd_src_convert_rate() indicates + * above convert_rate, and it controls + * whether SRC is used or not. + * + * ex) doesn't use SRC + * struct rsnd_src_platform_info info = { + * .flags = 0, + * .convert_rate = 0, + * }; + * + * ex) uses SRC + * struct rsnd_src_platform_info info = { + * .flags = RSND_SRC_USE_HPBIF, + * .convert_rate = 48000, + * }; + * + * ex) uses SRC bypass mode + * struct rsnd_src_platform_info info = { + * .flags = RSND_SRC_USE_HPBIF, + * .convert_rate = 0, + * }; + * + */ + +/* + * Gen1/Gen2 common functions + */ +int rsnd_src_ssi_mode_init(struct rsnd_mod *ssi_mod, + struct rsnd_dai *rdai, + struct rsnd_dai_stream *io) +{ + struct rsnd_priv *priv = rsnd_mod_to_priv(ssi_mod); + struct rsnd_mod *src_mod = rsnd_io_to_mod_src(io); + struct rcar_snd_info *info = rsnd_priv_to_info(priv); + int ssi_id = rsnd_mod_id(ssi_mod); + int has_src = 0; + + /* + * SSI_MODE0 + */ + if (info->dai_info) { + has_src = !!src_mod; + } else { + struct rsnd_src *src = rsnd_mod_to_src(src_mod); + has_src = rsnd_src_hpbif_is_enable(src); + } + + rsnd_mod_bset(ssi_mod, SSI_MODE0, (1 << ssi_id), + has_src ? 0 : (1 << ssi_id)); + + /* + * SSI_MODE1 + */ + if (rsnd_ssi_is_pin_sharing(ssi_mod)) { + int shift = -1; + switch (ssi_id) { + case 1: + shift = 0; + break; + case 2: + shift = 2; + break; + case 4: + shift = 16; + break; + } + + if (shift >= 0) + rsnd_mod_bset(ssi_mod, SSI_MODE1, + 0x3 << shift, + rsnd_dai_is_clk_master(rdai) ? + 0x2 << shift : 0x1 << shift); + } + + return 0; +} + +int rsnd_src_enable_ssi_irq(struct rsnd_mod *ssi_mod, + struct rsnd_dai *rdai, + struct rsnd_dai_stream *io) +{ + struct rsnd_priv *priv = rsnd_mod_to_priv(ssi_mod); + + /* enable PIO interrupt if Gen2 */ + if (rsnd_is_gen2(priv)) + rsnd_mod_write(ssi_mod, INT_ENABLE, 0x0f000000); + + return 0; +} + +unsigned int rsnd_src_get_ssi_rate(struct rsnd_priv *priv, + struct rsnd_dai_stream *io, + struct snd_pcm_runtime *runtime) +{ + struct rsnd_mod *src_mod = rsnd_io_to_mod_src(io); + struct rsnd_src *src; + unsigned int rate = 0; + + if (src_mod) { + src = rsnd_mod_to_src(src_mod); + + /* + * return convert rate if SRC is used, + * otherwise, return runtime->rate as usual + */ + rate = rsnd_src_convert_rate(src); + } + + if (!rate) + rate = runtime->rate; + + return rate; +} + +static int rsnd_src_set_convert_rate(struct rsnd_mod *mod, + struct rsnd_dai *rdai, + struct rsnd_dai_stream *io) +{ + struct snd_pcm_runtime *runtime = rsnd_io_to_runtime(io); + struct rsnd_src *src = rsnd_mod_to_src(mod); + u32 convert_rate = rsnd_src_convert_rate(src); + u32 adinr = runtime->channels; + u32 fsrate = 0; + + if (convert_rate) + fsrate = 0x0400000 / convert_rate * runtime->rate; + + /* set/clear soft reset */ + rsnd_mod_write(mod, SRC_SWRSR, 0); + rsnd_mod_write(mod, SRC_SWRSR, 1); + + /* + * Initialize the operation of the SRC internal circuits + * see rsnd_src_start() + */ + rsnd_mod_write(mod, SRC_SRCIR, 1); + + /* Set channel number and output bit length */ + switch (runtime->sample_bits) { + case 16: + adinr |= OTBL_16; + break; + case 32: + adinr |= OTBL_24; + break; + default: + return -EIO; + } + rsnd_mod_write(mod, SRC_ADINR, adinr); + + /* Enable the initial value of IFS */ + if (fsrate) { + rsnd_mod_write(mod, SRC_IFSCR, 1); + + /* Set initial value of IFS */ + rsnd_mod_write(mod, SRC_IFSVR, fsrate); + } + + /* use DMA transfer */ + rsnd_mod_write(mod, SRC_BUSIF_MODE, 1); + + return 0; +} + +static int rsnd_src_init(struct rsnd_mod *mod, + struct rsnd_dai *rdai, + struct rsnd_dai_stream *io) +{ + struct rsnd_src *src = rsnd_mod_to_src(mod); + + clk_enable(src->clk); + + return 0; +} + +static int rsnd_src_quit(struct rsnd_mod *mod, + struct rsnd_dai *rdai, + struct rsnd_dai_stream *io) +{ + struct rsnd_src *src = rsnd_mod_to_src(mod); + + clk_disable(src->clk); + + return 0; +} + +static int rsnd_src_start(struct rsnd_mod *mod, + struct rsnd_dai *rdai, + struct rsnd_dai_stream *io) +{ + struct rsnd_src *src = rsnd_mod_to_src(mod); + + /* + * Cancel the initialization and operate the SRC function + * see rsnd_src_set_convert_rate() + */ + rsnd_mod_write(mod, SRC_SRCIR, 0); + + if (rsnd_src_convert_rate(src)) + rsnd_mod_write(mod, SRC_ROUTE_MODE0, 1); + + return 0; +} + + +static int rsnd_src_stop(struct rsnd_mod *mod, + struct rsnd_dai *rdai, + struct rsnd_dai_stream *io) +{ + struct rsnd_src *src = rsnd_mod_to_src(mod); + + if (rsnd_src_convert_rate(src)) + rsnd_mod_write(mod, SRC_ROUTE_MODE0, 0); + + return 0; +} + +static struct rsnd_mod_ops rsnd_src_non_ops = { + .name = "src (non)", +}; + +/* + * Gen1 functions + */ +static int rsnd_src_set_route_gen1(struct rsnd_mod *mod, + struct rsnd_dai *rdai, + struct rsnd_dai_stream *io) +{ + struct src_route_config { + u32 mask; + int shift; + } routes[] = { + { 0xF, 0, }, /* 0 */ + { 0xF, 4, }, /* 1 */ + { 0xF, 8, }, /* 2 */ + { 0x7, 12, }, /* 3 */ + { 0x7, 16, }, /* 4 */ + { 0x7, 20, }, /* 5 */ + { 0x7, 24, }, /* 6 */ + { 0x3, 28, }, /* 7 */ + { 0x3, 30, }, /* 8 */ + }; + u32 mask; + u32 val; + int id; + + id = rsnd_mod_id(mod); + if (id < 0 || id >= ARRAY_SIZE(routes)) + return -EIO; + + /* + * SRC_ROUTE_SELECT + */ + val = rsnd_dai_is_play(rdai, io) ? 0x1 : 0x2; + val = val << routes[id].shift; + mask = routes[id].mask << routes[id].shift; + + rsnd_mod_bset(mod, SRC_ROUTE_SEL, mask, val); + + return 0; +} + +static int rsnd_src_set_convert_timing_gen1(struct rsnd_mod *mod, + struct rsnd_dai *rdai, + struct rsnd_dai_stream *io) +{ + struct rsnd_priv *priv = rsnd_mod_to_priv(mod); + struct rsnd_src *src = rsnd_mod_to_src(mod); + struct snd_pcm_runtime *runtime = rsnd_io_to_runtime(io); + u32 convert_rate = rsnd_src_convert_rate(src); + u32 mask; + u32 val; + int shift; + int id = rsnd_mod_id(mod); + int ret; + + /* + * SRC_TIMING_SELECT + */ + shift = (id % 4) * 8; + mask = 0x1F << shift; + + /* + * ADG is used as source clock if SRC was used, + * then, SSI WS is used as destination clock. + * SSI WS is used as source clock if SRC is not used + * (when playback, source/destination become reverse when capture) + */ + ret = 0; + if (convert_rate) { + /* use ADG */ + val = 0; + ret = rsnd_adg_set_convert_clk_gen1(priv, mod, + runtime->rate, + convert_rate); + } else if (8 == id) { + /* use SSI WS, but SRU8 is special */ + val = id << shift; + } else { + /* use SSI WS */ + val = (id + 1) << shift; + } + + if (ret < 0) + return ret; + + switch (id / 4) { + case 0: + rsnd_mod_bset(mod, SRC_TMG_SEL0, mask, val); + break; + case 1: + rsnd_mod_bset(mod, SRC_TMG_SEL1, mask, val); + break; + case 2: + rsnd_mod_bset(mod, SRC_TMG_SEL2, mask, val); + break; + } + + return 0; +} + +static int rsnd_src_set_convert_rate_gen1(struct rsnd_mod *mod, + struct rsnd_dai *rdai, + struct rsnd_dai_stream *io) +{ + int ret; + + ret = rsnd_src_set_convert_rate(mod, rdai, io); + if (ret < 0) + return ret; + + /* Select SRC mode (fixed value) */ + rsnd_mod_write(mod, SRC_SRCCR, 0x00010110); + + /* Set the restriction value of the FS ratio (98%) */ + rsnd_mod_write(mod, SRC_MNFSR, + rsnd_mod_read(mod, SRC_IFSVR) / 100 * 98); + + /* no SRC_BFSSR settings, since SRC_SRCCR::BUFMD is 0 */ + + return 0; +} + +static int rsnd_src_init_gen1(struct rsnd_mod *mod, + struct rsnd_dai *rdai, + struct rsnd_dai_stream *io) +{ + int ret; + + ret = rsnd_src_init(mod, rdai, io); + if (ret < 0) + return ret; + + ret = rsnd_src_set_route_gen1(mod, rdai, io); + if (ret < 0) + return ret; + + ret = rsnd_src_set_convert_rate_gen1(mod, rdai, io); + if (ret < 0) + return ret; + + ret = rsnd_src_set_convert_timing_gen1(mod, rdai, io); + if (ret < 0) + return ret; + + return 0; +} + +static int rsnd_src_start_gen1(struct rsnd_mod *mod, + struct rsnd_dai *rdai, + struct rsnd_dai_stream *io) +{ + int id = rsnd_mod_id(mod); + + rsnd_mod_bset(mod, SRC_ROUTE_CTRL, (1 << id), (1 << id)); + + return rsnd_src_start(mod, rdai, io); +} + +static int rsnd_src_stop_gen1(struct rsnd_mod *mod, + struct rsnd_dai *rdai, + struct rsnd_dai_stream *io) +{ + int id = rsnd_mod_id(mod); + + rsnd_mod_bset(mod, SRC_ROUTE_CTRL, (1 << id), 0); + + return rsnd_src_stop(mod, rdai, io); +} + +static struct rsnd_mod_ops rsnd_src_gen1_ops = { + .name = "sru (gen1)", + .init = rsnd_src_init_gen1, + .quit = rsnd_src_quit, + .start = rsnd_src_start_gen1, + .stop = rsnd_src_stop_gen1, +}; + +/* + * Gen2 functions + */ +static int rsnd_src_set_convert_rate_gen2(struct rsnd_mod *mod, + struct rsnd_dai *rdai, + struct rsnd_dai_stream *io) +{ + int ret; + + ret = rsnd_src_set_convert_rate(mod, rdai, io); + if (ret < 0) + return ret; + + rsnd_mod_write(mod, SSI_BUSIF_ADINR, rsnd_mod_read(mod, SRC_ADINR)); + rsnd_mod_write(mod, SSI_BUSIF_MODE, rsnd_mod_read(mod, SRC_BUSIF_MODE)); + + rsnd_mod_write(mod, SRC_SRCCR, 0x00011110); + + rsnd_mod_write(mod, SRC_BSDSR, 0x01800000); + rsnd_mod_write(mod, SRC_BSISR, 0x00100060); + + return 0; +} + +static int rsnd_src_set_convert_timing_gen2(struct rsnd_mod *mod, + struct rsnd_dai *rdai, + struct rsnd_dai_stream *io) +{ + struct snd_pcm_runtime *runtime = rsnd_io_to_runtime(io); + struct rsnd_src *src = rsnd_mod_to_src(mod); + u32 convert_rate = rsnd_src_convert_rate(src); + int ret; + + if (convert_rate) + ret = rsnd_adg_set_convert_clk_gen2(mod, rdai, io, + runtime->rate, + convert_rate); + else + ret = rsnd_adg_set_convert_timing_gen2(mod, rdai, io); + + return ret; +} + +static int rsnd_src_probe_gen2(struct rsnd_mod *mod, + struct rsnd_dai *rdai, + struct rsnd_dai_stream *io) +{ + struct rsnd_priv *priv = rsnd_mod_to_priv(mod); + struct rcar_snd_info *info = rsnd_priv_to_info(priv); + struct rsnd_src *src = rsnd_mod_to_src(mod); + struct rsnd_mod *ssi = rsnd_ssi_mod_get(priv, rsnd_mod_id(mod)); + struct device *dev = rsnd_priv_to_dev(priv); + int ret; + int is_play; + + if (info->dai_info) + is_play = rsnd_info_is_playback(priv, src); + else + is_play = rsnd_ssi_is_play(ssi); + + ret = rsnd_dma_init(priv, + rsnd_mod_to_dma(mod), + is_play, + src->info->dma_id); + if (ret < 0) + dev_err(dev, "SRC DMA failed\n"); + + return ret; +} + +static int rsnd_src_remove_gen2(struct rsnd_mod *mod, + struct rsnd_dai *rdai, + struct rsnd_dai_stream *io) +{ + rsnd_dma_quit(rsnd_mod_to_priv(mod), rsnd_mod_to_dma(mod)); + + return 0; +} + +static int rsnd_src_init_gen2(struct rsnd_mod *mod, + struct rsnd_dai *rdai, + struct rsnd_dai_stream *io) +{ + int ret; + + ret = rsnd_src_init(mod, rdai, io); + if (ret < 0) + return ret; + + ret = rsnd_src_set_convert_rate_gen2(mod, rdai, io); + if (ret < 0) + return ret; + + ret = rsnd_src_set_convert_timing_gen2(mod, rdai, io); + if (ret < 0) + return ret; + + return 0; +} + +static int rsnd_src_start_gen2(struct rsnd_mod *mod, + struct rsnd_dai *rdai, + struct rsnd_dai_stream *io) +{ + struct rsnd_src *src = rsnd_mod_to_src(mod); + + rsnd_dma_start(rsnd_mod_to_dma(&src->mod)); + + rsnd_mod_write(mod, SSI_CTRL, 0x1); + rsnd_mod_write(mod, SRC_CTRL, 0x11); + + return rsnd_src_start(mod, rdai, io); +} + +static int rsnd_src_stop_gen2(struct rsnd_mod *mod, + struct rsnd_dai *rdai, + struct rsnd_dai_stream *io) +{ + struct rsnd_src *src = rsnd_mod_to_src(mod); + + rsnd_mod_write(mod, SSI_CTRL, 0); + rsnd_mod_write(mod, SRC_CTRL, 0); + + rsnd_dma_stop(rsnd_mod_to_dma(&src->mod)); + + return rsnd_src_stop(mod, rdai, io); +} + +static struct rsnd_mod_ops rsnd_src_gen2_ops = { + .name = "src (gen2)", + .probe = rsnd_src_probe_gen2, + .remove = rsnd_src_remove_gen2, + .init = rsnd_src_init_gen2, + .quit = rsnd_src_quit, + .start = rsnd_src_start_gen2, + .stop = rsnd_src_stop_gen2, +}; + +struct rsnd_mod *rsnd_src_mod_get(struct rsnd_priv *priv, int id) +{ + if (WARN_ON(id < 0 || id >= rsnd_src_nr(priv))) + id = 0; + + return &((struct rsnd_src *)(priv->src) + id)->mod; +} + +static void rsnd_of_parse_src(struct platform_device *pdev, + const struct rsnd_of_data *of_data, + struct rsnd_priv *priv) +{ + struct device_node *src_node; + struct rcar_snd_info *info = rsnd_priv_to_info(priv); + struct rsnd_src_platform_info *src_info; + struct device *dev = &pdev->dev; + int nr; + + if (!of_data) + return; + + src_node = of_get_child_by_name(dev->of_node, "rcar_sound,src"); + if (!src_node) + return; + + nr = of_get_child_count(src_node); + if (!nr) + return; + + src_info = devm_kzalloc(dev, + sizeof(struct rsnd_src_platform_info) * nr, + GFP_KERNEL); + if (!src_info) { + dev_err(dev, "src info allocation error\n"); + return; + } + + info->src_info = src_info; + info->src_info_nr = nr; +} + +int rsnd_src_probe(struct platform_device *pdev, + const struct rsnd_of_data *of_data, + struct rsnd_priv *priv) +{ + struct rcar_snd_info *info = rsnd_priv_to_info(priv); + struct device *dev = rsnd_priv_to_dev(priv); + struct rsnd_src *src; + struct rsnd_mod_ops *ops; + struct clk *clk; + char name[RSND_SRC_NAME_SIZE]; + int i, nr; + + rsnd_of_parse_src(pdev, of_data, priv); + + /* + * init SRC + */ + nr = info->src_info_nr; + if (!nr) + return 0; + + src = devm_kzalloc(dev, sizeof(*src) * nr, GFP_KERNEL); + if (!src) { + dev_err(dev, "SRC allocate failed\n"); + return -ENOMEM; + } + + priv->src_nr = nr; + priv->src = src; + + for_each_rsnd_src(src, priv, i) { + snprintf(name, RSND_SRC_NAME_SIZE, "src.%d", i); + + clk = devm_clk_get(dev, name); + if (IS_ERR(clk)) { + snprintf(name, RSND_SRC_NAME_SIZE, "scu.%d", i); + clk = devm_clk_get(dev, name); + } + + if (IS_ERR(clk)) + return PTR_ERR(clk); + + src->info = &info->src_info[i]; + src->clk = clk; + + ops = &rsnd_src_non_ops; + if (rsnd_src_hpbif_is_enable(src)) { + if (rsnd_is_gen1(priv)) + ops = &rsnd_src_gen1_ops; + if (rsnd_is_gen2(priv)) + ops = &rsnd_src_gen2_ops; + } + + rsnd_mod_init(priv, &src->mod, ops, RSND_MOD_SRC, i); + + dev_dbg(dev, "SRC%d probed\n", i); + } + + return 0; +} diff --git a/sound/soc/sh/rcar/ssi.c b/sound/soc/sh/rcar/ssi.c index 4b8cf7ca9d1..4b7e20603dd 100644 --- a/sound/soc/sh/rcar/ssi.c +++ b/sound/soc/sh/rcar/ssi.c @@ -64,108 +64,29 @@ struct rsnd_ssi { struct rsnd_mod mod; struct rsnd_dai *rdai; - struct rsnd_dai_stream *io; u32 cr_own; u32 cr_clk; u32 cr_etc; int err; - int dma_offset; unsigned int usrcnt; unsigned int rate; }; -struct rsnd_ssiu { - u32 ssi_mode0; - u32 ssi_mode1; - - int ssi_nr; - struct rsnd_ssi *ssi; -}; - #define for_each_rsnd_ssi(pos, priv, i) \ for (i = 0; \ (i < rsnd_ssi_nr(priv)) && \ - ((pos) = ((struct rsnd_ssiu *)((priv)->ssiu))->ssi + i); \ + ((pos) = ((struct rsnd_ssi *)(priv)->ssi + i)); \ i++) -#define rsnd_ssi_nr(priv) (((struct rsnd_ssiu *)((priv)->ssiu))->ssi_nr) +#define rsnd_ssi_nr(priv) ((priv)->ssi_nr) #define rsnd_mod_to_ssi(_mod) container_of((_mod), struct rsnd_ssi, mod) #define rsnd_dma_to_ssi(dma) rsnd_mod_to_ssi(rsnd_dma_to_mod(dma)) #define rsnd_ssi_pio_available(ssi) ((ssi)->info->pio_irq > 0) #define rsnd_ssi_dma_available(ssi) \ rsnd_dma_available(rsnd_mod_to_dma(&(ssi)->mod)) #define rsnd_ssi_clk_from_parent(ssi) ((ssi)->parent) -#define rsnd_rdai_is_clk_master(rdai) ((rdai)->clk_master) #define rsnd_ssi_mode_flags(p) ((p)->info->flags) #define rsnd_ssi_dai_id(ssi) ((ssi)->info->dai_id) -#define rsnd_ssi_to_ssiu(ssi)\ - (((struct rsnd_ssiu *)((ssi) - rsnd_mod_id(&(ssi)->mod))) - 1) - -static void rsnd_ssi_mode_set(struct rsnd_priv *priv, - struct rsnd_dai *rdai, - struct rsnd_ssi *ssi) -{ - struct device *dev = rsnd_priv_to_dev(priv); - struct rsnd_mod *scu; - struct rsnd_ssiu *ssiu = rsnd_ssi_to_ssiu(ssi); - int id = rsnd_mod_id(&ssi->mod); - u32 flags; - u32 val; - - scu = rsnd_scu_mod_get(priv, rsnd_mod_id(&ssi->mod)); - - /* - * SSI_MODE0 - */ - - /* see also BUSIF_MODE */ - if (rsnd_scu_hpbif_is_enable(scu)) { - ssiu->ssi_mode0 &= ~(1 << id); - dev_dbg(dev, "SSI%d uses DEPENDENT mode\n", id); - } else { - ssiu->ssi_mode0 |= (1 << id); - dev_dbg(dev, "SSI%d uses INDEPENDENT mode\n", id); - } - - /* - * SSI_MODE1 - */ -#define ssi_parent_set(p, sync, adg, ext) \ - do { \ - ssi->parent = ssiu->ssi + p; \ - if (rsnd_rdai_is_clk_master(rdai)) \ - val = adg; \ - else \ - val = ext; \ - if (flags & RSND_SSI_SYNC) \ - val |= sync; \ - } while (0) - - flags = rsnd_ssi_mode_flags(ssi); - if (flags & RSND_SSI_CLK_PIN_SHARE) { - - val = 0; - switch (id) { - case 1: - ssi_parent_set(0, (1 << 4), (0x2 << 0), (0x1 << 0)); - break; - case 2: - ssi_parent_set(0, (1 << 4), (0x2 << 2), (0x1 << 2)); - break; - case 4: - ssi_parent_set(3, (1 << 20), (0x2 << 16), (0x1 << 16)); - break; - case 8: - ssi_parent_set(7, 0, 0, 0); - break; - } - - ssiu->ssi_mode1 |= val; - } - - rsnd_mod_write(&ssi->mod, SSI_MODE0, ssiu->ssi_mode0); - rsnd_mod_write(&ssi->mod, SSI_MODE1, ssiu->ssi_mode1); -} static void rsnd_ssi_status_check(struct rsnd_mod *mod, u32 bit) @@ -200,7 +121,7 @@ static int rsnd_ssi_master_clk_start(struct rsnd_ssi *ssi, 1, 2, 4, 8, 16, 6, 12, }; unsigned int main_rate; - unsigned int rate = rsnd_scu_get_ssi_rate(priv, &ssi->mod, runtime); + unsigned int rate = rsnd_src_get_ssi_rate(priv, io, runtime); /* * Find best clock, and try to start ADG @@ -252,7 +173,7 @@ static void rsnd_ssi_hw_start(struct rsnd_ssi *ssi, if (0 == ssi->usrcnt) { clk_enable(ssi->clk); - if (rsnd_rdai_is_clk_master(rdai)) { + if (rsnd_dai_is_clk_master(rdai)) { if (rsnd_ssi_clk_from_parent(ssi)) rsnd_ssi_hw_start(ssi->parent, rdai, io); else @@ -302,7 +223,7 @@ static void rsnd_ssi_hw_stop(struct rsnd_ssi *ssi, rsnd_mod_write(&ssi->mod, SSICR, cr); /* disabled all */ rsnd_ssi_status_check(&ssi->mod, IIRQ); - if (rsnd_rdai_is_clk_master(rdai)) { + if (rsnd_dai_is_clk_master(rdai)) { if (rsnd_ssi_clk_from_parent(ssi)) rsnd_ssi_hw_stop(ssi->parent, rdai); else @@ -323,8 +244,6 @@ static int rsnd_ssi_init(struct rsnd_mod *mod, struct rsnd_dai_stream *io) { struct rsnd_ssi *ssi = rsnd_mod_to_ssi(mod); - struct rsnd_priv *priv = rsnd_mod_to_priv(mod); - struct device *dev = rsnd_priv_to_dev(priv); struct snd_pcm_runtime *runtime = rsnd_io_to_runtime(io); u32 cr; @@ -365,13 +284,10 @@ static int rsnd_ssi_init(struct rsnd_mod *mod, * set ssi parameter */ ssi->rdai = rdai; - ssi->io = io; ssi->cr_own = cr; ssi->err = -1; /* ignore 1st error */ - rsnd_ssi_mode_set(priv, rdai, ssi); - - dev_dbg(dev, "%s.%d init\n", rsnd_mod_name(mod), rsnd_mod_id(mod)); + rsnd_src_ssi_mode_init(mod, rdai, io); return 0; } @@ -384,13 +300,10 @@ static int rsnd_ssi_quit(struct rsnd_mod *mod, struct rsnd_priv *priv = rsnd_mod_to_priv(mod); struct device *dev = rsnd_priv_to_dev(priv); - dev_dbg(dev, "%s.%d quit\n", rsnd_mod_name(mod), rsnd_mod_id(mod)); - if (ssi->err > 0) dev_warn(dev, "ssi under/over flow err = %d\n", ssi->err); ssi->rdai = NULL; - ssi->io = NULL; ssi->cr_own = 0; ssi->err = 0; @@ -414,8 +327,9 @@ static void rsnd_ssi_record_error(struct rsnd_ssi *ssi, u32 status) static irqreturn_t rsnd_ssi_pio_interrupt(int irq, void *data) { struct rsnd_ssi *ssi = data; - struct rsnd_dai_stream *io = ssi->io; - u32 status = rsnd_mod_read(&ssi->mod, SSISR); + struct rsnd_mod *mod = &ssi->mod; + struct rsnd_dai_stream *io = rsnd_mod_to_io(mod); + u32 status = rsnd_mod_read(mod, SSISR); irqreturn_t ret = IRQ_NONE; if (io && (status & DIRQ)) { @@ -432,9 +346,9 @@ static irqreturn_t rsnd_ssi_pio_interrupt(int irq, void *data) * see rsnd_ssi_init() */ if (rsnd_dai_is_play(rdai, io)) - rsnd_mod_write(&ssi->mod, SSITDR, *buf); + rsnd_mod_write(mod, SSITDR, *buf); else - *buf = rsnd_mod_read(&ssi->mod, SSIRDR); + *buf = rsnd_mod_read(mod, SSIRDR); rsnd_dai_pointer_update(io, sizeof(*buf)); @@ -444,25 +358,39 @@ static irqreturn_t rsnd_ssi_pio_interrupt(int irq, void *data) return ret; } -static int rsnd_ssi_pio_start(struct rsnd_mod *mod, +static int rsnd_ssi_pio_probe(struct rsnd_mod *mod, struct rsnd_dai *rdai, struct rsnd_dai_stream *io) { struct rsnd_priv *priv = rsnd_mod_to_priv(mod); - struct rsnd_ssi *ssi = rsnd_mod_to_ssi(mod); struct device *dev = rsnd_priv_to_dev(priv); + struct rsnd_ssi *ssi = rsnd_mod_to_ssi(mod); + int irq = ssi->info->pio_irq; + int ret; + + ret = devm_request_irq(dev, irq, + rsnd_ssi_pio_interrupt, + IRQF_SHARED, + dev_name(dev), ssi); + if (ret) + dev_err(dev, "SSI request interrupt failed\n"); + + return ret; +} + +static int rsnd_ssi_pio_start(struct rsnd_mod *mod, + struct rsnd_dai *rdai, + struct rsnd_dai_stream *io) +{ + struct rsnd_ssi *ssi = rsnd_mod_to_ssi(mod); /* enable PIO IRQ */ ssi->cr_etc = UIEN | OIEN | DIEN; - /* enable PIO interrupt if gen2 */ - if (rsnd_is_gen2(priv)) - rsnd_mod_write(&ssi->mod, INT_ENABLE, 0x0f000000); + rsnd_src_enable_ssi_irq(mod, rdai, io); rsnd_ssi_hw_start(ssi, rdai, io); - dev_dbg(dev, "%s.%d start\n", rsnd_mod_name(mod), rsnd_mod_id(mod)); - return 0; } @@ -470,12 +398,8 @@ static int rsnd_ssi_pio_stop(struct rsnd_mod *mod, struct rsnd_dai *rdai, struct rsnd_dai_stream *io) { - struct rsnd_priv *priv = rsnd_mod_to_priv(mod); - struct device *dev = rsnd_priv_to_dev(priv); struct rsnd_ssi *ssi = rsnd_mod_to_ssi(mod); - dev_dbg(dev, "%s.%d stop\n", rsnd_mod_name(mod), rsnd_mod_id(mod)); - ssi->cr_etc = 0; rsnd_ssi_hw_stop(ssi, rdai); @@ -485,35 +409,46 @@ static int rsnd_ssi_pio_stop(struct rsnd_mod *mod, static struct rsnd_mod_ops rsnd_ssi_pio_ops = { .name = "ssi (pio)", + .probe = rsnd_ssi_pio_probe, .init = rsnd_ssi_init, .quit = rsnd_ssi_quit, .start = rsnd_ssi_pio_start, .stop = rsnd_ssi_pio_stop, }; -static int rsnd_ssi_dma_inquiry(struct rsnd_dma *dma, dma_addr_t *buf, int *len) +static int rsnd_ssi_dma_probe(struct rsnd_mod *mod, + struct rsnd_dai *rdai, + struct rsnd_dai_stream *io) { - struct rsnd_ssi *ssi = rsnd_dma_to_ssi(dma); - struct rsnd_dai_stream *io = ssi->io; - struct snd_pcm_runtime *runtime = rsnd_io_to_runtime(io); + struct rsnd_priv *priv = rsnd_mod_to_priv(mod); + struct rsnd_ssi *ssi = rsnd_mod_to_ssi(mod); + struct rcar_snd_info *info = rsnd_priv_to_info(priv); + struct device *dev = rsnd_priv_to_dev(priv); + int dma_id = ssi->info->dma_id; + int is_play; + int ret; - *len = io->byte_per_period; - *buf = runtime->dma_addr + - rsnd_dai_pointer_offset(io, ssi->dma_offset + *len); - ssi->dma_offset = *len; /* it cares A/B plane */ + if (info->dai_info) + is_play = rsnd_info_is_playback(priv, ssi); + else + is_play = rsnd_ssi_is_play(&ssi->mod); - return 0; -} + ret = rsnd_dma_init( + priv, rsnd_mod_to_dma(mod), + is_play, + dma_id); -static int rsnd_ssi_dma_complete(struct rsnd_dma *dma) -{ - struct rsnd_ssi *ssi = rsnd_dma_to_ssi(dma); - struct rsnd_dai_stream *io = ssi->io; - u32 status = rsnd_mod_read(&ssi->mod, SSISR); + if (ret < 0) + dev_err(dev, "SSI DMA failed\n"); - rsnd_ssi_record_error(ssi, status); + return ret; +} - rsnd_dai_pointer_update(ssi->io, io->byte_per_period); +static int rsnd_ssi_dma_remove(struct rsnd_mod *mod, + struct rsnd_dai *rdai, + struct rsnd_dai_stream *io) +{ + rsnd_dma_quit(rsnd_mod_to_priv(mod), rsnd_mod_to_dma(mod)); return 0; } @@ -527,14 +462,13 @@ static int rsnd_ssi_dma_start(struct rsnd_mod *mod, /* enable DMA transfer */ ssi->cr_etc = DMEN; - ssi->dma_offset = 0; rsnd_dma_start(dma); rsnd_ssi_hw_start(ssi, ssi->rdai, io); /* enable WS continue */ - if (rsnd_rdai_is_clk_master(rdai)) + if (rsnd_dai_is_clk_master(rdai)) rsnd_mod_write(&ssi->mod, SSIWSR, CONT); return 0; @@ -549,6 +483,8 @@ static int rsnd_ssi_dma_stop(struct rsnd_mod *mod, ssi->cr_etc = 0; + rsnd_ssi_record_error(ssi, rsnd_mod_read(mod, SSISR)); + rsnd_ssi_hw_stop(ssi, rdai); rsnd_dma_stop(dma); @@ -558,6 +494,8 @@ static int rsnd_ssi_dma_stop(struct rsnd_mod *mod, static struct rsnd_mod_ops rsnd_ssi_dma_ops = { .name = "ssi (dma)", + .probe = rsnd_ssi_dma_probe, + .remove = rsnd_ssi_dma_remove, .init = rsnd_ssi_init, .quit = rsnd_ssi_quit, .start = rsnd_ssi_dma_start, @@ -567,24 +505,8 @@ static struct rsnd_mod_ops rsnd_ssi_dma_ops = { /* * Non SSI */ -static int rsnd_ssi_non(struct rsnd_mod *mod, - struct rsnd_dai *rdai, - struct rsnd_dai_stream *io) -{ - struct rsnd_priv *priv = rsnd_mod_to_priv(mod); - struct device *dev = rsnd_priv_to_dev(priv); - - dev_dbg(dev, "%s\n", __func__); - - return 0; -} - static struct rsnd_mod_ops rsnd_ssi_non_ops = { .name = "ssi (non)", - .init = rsnd_ssi_non, - .quit = rsnd_ssi_non, - .start = rsnd_ssi_non, - .stop = rsnd_ssi_non, }; /* @@ -593,16 +515,30 @@ static struct rsnd_mod_ops rsnd_ssi_non_ops = { struct rsnd_mod *rsnd_ssi_mod_get_frm_dai(struct rsnd_priv *priv, int dai_id, int is_play) { + struct rsnd_dai_platform_info *dai_info = NULL; + struct rsnd_dai_path_info *path_info = NULL; + struct rsnd_ssi_platform_info *target_info = NULL; struct rsnd_ssi *ssi; int i, has_play; + if (priv->rdai) + dai_info = priv->rdai[dai_id].info; + if (dai_info) + path_info = (is_play) ? &dai_info->playback : &dai_info->capture; + if (path_info) + target_info = path_info->ssi; + is_play = !!is_play; for_each_rsnd_ssi(ssi, priv, i) { + if (target_info == ssi->info) + return &ssi->mod; + + /* for compatible */ if (rsnd_ssi_dai_id(ssi) != dai_id) continue; - has_play = !!(rsnd_ssi_mode_flags(ssi) & RSND_SSI_PLAY); + has_play = rsnd_ssi_is_play(&ssi->mod); if (is_play == has_play) return &ssi->mod; @@ -616,36 +552,122 @@ struct rsnd_mod *rsnd_ssi_mod_get(struct rsnd_priv *priv, int id) if (WARN_ON(id < 0 || id >= rsnd_ssi_nr(priv))) id = 0; - return &(((struct rsnd_ssiu *)(priv->ssiu))->ssi + id)->mod; + return &((struct rsnd_ssi *)(priv->ssi) + id)->mod; +} + +int rsnd_ssi_is_pin_sharing(struct rsnd_mod *mod) +{ + struct rsnd_ssi *ssi = rsnd_mod_to_ssi(mod); + + return !!(rsnd_ssi_mode_flags(ssi) & RSND_SSI_CLK_PIN_SHARE); +} + +int rsnd_ssi_is_play(struct rsnd_mod *mod) +{ + struct rsnd_ssi *ssi = rsnd_mod_to_ssi(mod); + + return !!(rsnd_ssi_mode_flags(ssi) & RSND_SSI_PLAY); +} + +static void rsnd_ssi_parent_clk_setup(struct rsnd_priv *priv, struct rsnd_ssi *ssi) +{ + if (!rsnd_ssi_is_pin_sharing(&ssi->mod)) + return; + + switch (rsnd_mod_id(&ssi->mod)) { + case 1: + case 2: + ssi->parent = rsnd_mod_to_ssi(rsnd_ssi_mod_get(priv, 0)); + break; + case 4: + ssi->parent = rsnd_mod_to_ssi(rsnd_ssi_mod_get(priv, 3)); + break; + case 8: + ssi->parent = rsnd_mod_to_ssi(rsnd_ssi_mod_get(priv, 7)); + break; + } +} + + +static void rsnd_of_parse_ssi(struct platform_device *pdev, + const struct rsnd_of_data *of_data, + struct rsnd_priv *priv) +{ + struct device_node *node; + struct device_node *np; + struct rsnd_ssi_platform_info *ssi_info; + struct rcar_snd_info *info = rsnd_priv_to_info(priv); + struct device *dev = &pdev->dev; + int nr, i; + + if (!of_data) + return; + + node = of_get_child_by_name(dev->of_node, "rcar_sound,ssi"); + if (!node) + return; + + nr = of_get_child_count(node); + if (!nr) + return; + + ssi_info = devm_kzalloc(dev, + sizeof(struct rsnd_ssi_platform_info) * nr, + GFP_KERNEL); + if (!ssi_info) { + dev_err(dev, "ssi info allocation error\n"); + return; + } + + info->ssi_info = ssi_info; + info->ssi_info_nr = nr; + + i = -1; + for_each_child_of_node(node, np) { + i++; + + ssi_info = info->ssi_info + i; + + /* + * pin settings + */ + if (of_get_property(np, "shared-pin", NULL)) + ssi_info->flags |= RSND_SSI_CLK_PIN_SHARE; + + /* + * irq + */ + ssi_info->pio_irq = irq_of_parse_and_map(np, 0); + } } int rsnd_ssi_probe(struct platform_device *pdev, - struct rcar_snd_info *info, + const struct rsnd_of_data *of_data, struct rsnd_priv *priv) { + struct rcar_snd_info *info = rsnd_priv_to_info(priv); struct rsnd_ssi_platform_info *pinfo; struct device *dev = rsnd_priv_to_dev(priv); struct rsnd_mod_ops *ops; struct clk *clk; - struct rsnd_ssiu *ssiu; struct rsnd_ssi *ssi; char name[RSND_SSI_NAME_SIZE]; - int i, nr, ret; + int i, nr; + + rsnd_of_parse_ssi(pdev, of_data, priv); /* * init SSI */ nr = info->ssi_info_nr; - ssiu = devm_kzalloc(dev, sizeof(*ssiu) + (sizeof(*ssi) * nr), - GFP_KERNEL); - if (!ssiu) { + ssi = devm_kzalloc(dev, sizeof(*ssi) * nr, GFP_KERNEL); + if (!ssi) { dev_err(dev, "SSI allocate failed\n"); return -ENOMEM; } - priv->ssiu = ssiu; - ssiu->ssi = (struct rsnd_ssi *)(ssiu + 1); - ssiu->ssi_nr = nr; + priv->ssi = ssi; + priv->ssi_nr = nr; for_each_rsnd_ssi(ssi, priv, i) { pinfo = &info->ssi_info[i]; @@ -660,61 +682,15 @@ int rsnd_ssi_probe(struct platform_device *pdev, ssi->clk = clk; ops = &rsnd_ssi_non_ops; + if (pinfo->dma_id > 0) + ops = &rsnd_ssi_dma_ops; + else if (rsnd_ssi_pio_available(ssi)) + ops = &rsnd_ssi_pio_ops; - /* - * SSI DMA case - */ - if (pinfo->dma_id > 0) { - ret = rsnd_dma_init( - priv, rsnd_mod_to_dma(&ssi->mod), - (rsnd_ssi_mode_flags(ssi) & RSND_SSI_PLAY), - pinfo->dma_id, - rsnd_ssi_dma_inquiry, - rsnd_ssi_dma_complete); - if (ret < 0) - dev_info(dev, "SSI DMA failed. try PIO transter\n"); - else - ops = &rsnd_ssi_dma_ops; - - dev_dbg(dev, "SSI%d use DMA transfer\n", i); - } - - /* - * SSI PIO case - */ - if (!rsnd_ssi_dma_available(ssi) && - rsnd_ssi_pio_available(ssi)) { - ret = devm_request_irq(dev, pinfo->pio_irq, - &rsnd_ssi_pio_interrupt, - IRQF_SHARED, - dev_name(dev), ssi); - if (ret) { - dev_err(dev, "SSI request interrupt failed\n"); - return ret; - } - - ops = &rsnd_ssi_pio_ops; - - dev_dbg(dev, "SSI%d use PIO transfer\n", i); - } + rsnd_mod_init(priv, &ssi->mod, ops, RSND_MOD_SSI, i); - rsnd_mod_init(priv, &ssi->mod, ops, i); + rsnd_ssi_parent_clk_setup(priv, ssi); } - dev_dbg(dev, "ssi probed\n"); - return 0; } - -void rsnd_ssi_remove(struct platform_device *pdev, - struct rsnd_priv *priv) -{ - struct rsnd_ssi *ssi; - int i; - - for_each_rsnd_ssi(ssi, priv, i) { - if (rsnd_ssi_dma_available(ssi)) - rsnd_dma_quit(priv, rsnd_mod_to_dma(&ssi->mod)); - } - -} diff --git a/sound/soc/sirf/Kconfig b/sound/soc/sirf/Kconfig new file mode 100644 index 00000000000..89e89429b04 --- /dev/null +++ b/sound/soc/sirf/Kconfig @@ -0,0 +1,14 @@ +config SND_SOC_SIRF + tristate "SoC Audio for the SiRF SoC chips" + depends on ARCH_SIRF || COMPILE_TEST + select SND_SOC_GENERIC_DMAENGINE_PCM + +config SND_SOC_SIRF_AUDIO + tristate "SoC Audio support for SiRF internal audio codec" + depends on SND_SOC_SIRF + select SND_SOC_SIRF_AUDIO_CODEC + select SND_SOC_SIRF_AUDIO_PORT + +config SND_SOC_SIRF_AUDIO_PORT + select REGMAP_MMIO + tristate diff --git a/sound/soc/sirf/Makefile b/sound/soc/sirf/Makefile new file mode 100644 index 00000000000..913b93231d4 --- /dev/null +++ b/sound/soc/sirf/Makefile @@ -0,0 +1,5 @@ +snd-soc-sirf-audio-objs := sirf-audio.o +snd-soc-sirf-audio-port-objs := sirf-audio-port.o + +obj-$(CONFIG_SND_SOC_SIRF_AUDIO) += snd-soc-sirf-audio.o +obj-$(CONFIG_SND_SOC_SIRF_AUDIO_PORT) += snd-soc-sirf-audio-port.o diff --git a/sound/soc/sirf/sirf-audio-port.c b/sound/soc/sirf/sirf-audio-port.c new file mode 100644 index 00000000000..b04a53f2b4f --- /dev/null +++ b/sound/soc/sirf/sirf-audio-port.c @@ -0,0 +1,194 @@ +/* + * SiRF Audio port driver + * + * Copyright (c) 2011 Cambridge Silicon Radio Limited, a CSR plc group company. + * + * Licensed under GPLv2 or later. + */ +#include <linux/module.h> +#include <linux/io.h> +#include <linux/regmap.h> +#include <sound/soc.h> +#include <sound/dmaengine_pcm.h> + +#include "sirf-audio-port.h" + +struct sirf_audio_port { + struct regmap *regmap; + struct snd_dmaengine_dai_dma_data playback_dma_data; + struct snd_dmaengine_dai_dma_data capture_dma_data; +}; + +static void sirf_audio_port_tx_enable(struct sirf_audio_port *port) +{ + regmap_update_bits(port->regmap, AUDIO_PORT_IC_TXFIFO_OP, + AUDIO_FIFO_RESET, AUDIO_FIFO_RESET); + regmap_write(port->regmap, AUDIO_PORT_IC_TXFIFO_INT_MSK, 0); + regmap_write(port->regmap, AUDIO_PORT_IC_TXFIFO_OP, 0); + regmap_update_bits(port->regmap, AUDIO_PORT_IC_TXFIFO_OP, + AUDIO_FIFO_START, AUDIO_FIFO_START); + regmap_update_bits(port->regmap, AUDIO_PORT_IC_CODEC_TX_CTRL, + IC_TX_ENABLE, IC_TX_ENABLE); +} + +static void sirf_audio_port_tx_disable(struct sirf_audio_port *port) +{ + regmap_write(port->regmap, AUDIO_PORT_IC_TXFIFO_OP, 0); + regmap_update_bits(port->regmap, AUDIO_PORT_IC_CODEC_TX_CTRL, + IC_TX_ENABLE, ~IC_TX_ENABLE); +} + +static void sirf_audio_port_rx_enable(struct sirf_audio_port *port, + int channels) +{ + regmap_update_bits(port->regmap, AUDIO_PORT_IC_RXFIFO_OP, + AUDIO_FIFO_RESET, AUDIO_FIFO_RESET); + regmap_write(port->regmap, AUDIO_PORT_IC_RXFIFO_INT_MSK, 0); + regmap_write(port->regmap, AUDIO_PORT_IC_RXFIFO_OP, 0); + regmap_update_bits(port->regmap, AUDIO_PORT_IC_RXFIFO_OP, + AUDIO_FIFO_START, AUDIO_FIFO_START); + if (channels == 1) + regmap_update_bits(port->regmap, AUDIO_PORT_IC_CODEC_RX_CTRL, + IC_RX_ENABLE_MONO, IC_RX_ENABLE_MONO); + else + regmap_update_bits(port->regmap, AUDIO_PORT_IC_CODEC_RX_CTRL, + IC_RX_ENABLE_STEREO, IC_RX_ENABLE_STEREO); +} + +static void sirf_audio_port_rx_disable(struct sirf_audio_port *port) +{ + regmap_update_bits(port->regmap, AUDIO_PORT_IC_CODEC_RX_CTRL, + IC_RX_ENABLE_STEREO, ~IC_RX_ENABLE_STEREO); +} + +static int sirf_audio_port_dai_probe(struct snd_soc_dai *dai) +{ + struct sirf_audio_port *port = snd_soc_dai_get_drvdata(dai); + snd_soc_dai_init_dma_data(dai, &port->playback_dma_data, + &port->capture_dma_data); + return 0; +} + +static int sirf_audio_port_trigger(struct snd_pcm_substream *substream, int cmd, + struct snd_soc_dai *dai) +{ + struct sirf_audio_port *port = snd_soc_dai_get_drvdata(dai); + int playback = substream->stream == SNDRV_PCM_STREAM_PLAYBACK; + + switch (cmd) { + case SNDRV_PCM_TRIGGER_STOP: + case SNDRV_PCM_TRIGGER_SUSPEND: + case SNDRV_PCM_TRIGGER_PAUSE_PUSH: + if (playback) + sirf_audio_port_tx_disable(port); + else + sirf_audio_port_rx_disable(port); + break; + case SNDRV_PCM_TRIGGER_START: + case SNDRV_PCM_TRIGGER_RESUME: + case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: + if (playback) + sirf_audio_port_tx_enable(port); + else + sirf_audio_port_rx_enable(port, + substream->runtime->channels); + break; + default: + return -EINVAL; + } + + return 0; +} + +static const struct snd_soc_dai_ops sirf_audio_port_dai_ops = { + .trigger = sirf_audio_port_trigger, +}; + +static struct snd_soc_dai_driver sirf_audio_port_dai = { + .probe = sirf_audio_port_dai_probe, + .name = "sirf-audio-port", + .id = 0, + .playback = { + .channels_min = 2, + .channels_max = 2, + .rates = SNDRV_PCM_RATE_48000, + .formats = SNDRV_PCM_FMTBIT_S16_LE, + }, + .capture = { + .channels_min = 1, + .channels_max = 2, + .rates = SNDRV_PCM_RATE_48000, + .formats = SNDRV_PCM_FMTBIT_S16_LE, + }, + .ops = &sirf_audio_port_dai_ops, +}; + +static const struct snd_soc_component_driver sirf_audio_port_component = { + .name = "sirf-audio-port", +}; + +static const struct regmap_config sirf_audio_port_regmap_config = { + .reg_bits = 32, + .reg_stride = 4, + .val_bits = 32, + .max_register = AUDIO_PORT_IC_RXFIFO_INT_MSK, + .cache_type = REGCACHE_NONE, +}; + +static int sirf_audio_port_probe(struct platform_device *pdev) +{ + int ret; + struct sirf_audio_port *port; + void __iomem *base; + struct resource *mem_res; + + port = devm_kzalloc(&pdev->dev, + sizeof(struct sirf_audio_port), GFP_KERNEL); + if (!port) + return -ENOMEM; + + mem_res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!mem_res) { + dev_err(&pdev->dev, "no mem resource?\n"); + return -ENODEV; + } + + base = devm_ioremap(&pdev->dev, mem_res->start, + resource_size(mem_res)); + if (base == NULL) + return -ENOMEM; + + port->regmap = devm_regmap_init_mmio(&pdev->dev, base, + &sirf_audio_port_regmap_config); + if (IS_ERR(port->regmap)) + return PTR_ERR(port->regmap); + + ret = devm_snd_soc_register_component(&pdev->dev, + &sirf_audio_port_component, &sirf_audio_port_dai, 1); + if (ret) + return ret; + + platform_set_drvdata(pdev, port); + return devm_snd_dmaengine_pcm_register(&pdev->dev, NULL, 0); +} + +static const struct of_device_id sirf_audio_port_of_match[] = { + { .compatible = "sirf,audio-port", }, + {} +}; +MODULE_DEVICE_TABLE(of, sirf_audio_port_of_match); + +static struct platform_driver sirf_audio_port_driver = { + .driver = { + .name = "sirf-audio-port", + .owner = THIS_MODULE, + .of_match_table = sirf_audio_port_of_match, + }, + .probe = sirf_audio_port_probe, +}; + +module_platform_driver(sirf_audio_port_driver); + +MODULE_DESCRIPTION("SiRF Audio Port driver"); +MODULE_AUTHOR("RongJun Ying <Rongjun.Ying@csr.com>"); +MODULE_LICENSE("GPL v2"); diff --git a/sound/soc/sirf/sirf-audio-port.h b/sound/soc/sirf/sirf-audio-port.h new file mode 100644 index 00000000000..f32dc54f449 --- /dev/null +++ b/sound/soc/sirf/sirf-audio-port.h @@ -0,0 +1,62 @@ +/* + * SiRF Audio port controllers define + * + * Copyright (c) 2011 Cambridge Silicon Radio Limited, a CSR plc group company. + * + * Licensed under GPLv2 or later. + */ + +#ifndef _SIRF_AUDIO_PORT_H +#define _SIRF_AUDIO_PORT_H + +#define AUDIO_PORT_TX_FIFO_LEVEL_CHECK_MASK 0x3F +#define AUDIO_PORT_TX_FIFO_SC_OFFSET 0 +#define AUDIO_PORT_TX_FIFO_LC_OFFSET 10 +#define AUDIO_PORT_TX_FIFO_HC_OFFSET 20 + +#define TX_FIFO_SC(x) (((x) & AUDIO_PORT_TX_FIFO_LEVEL_CHECK_MASK) \ + << AUDIO_PORT_TX_FIFO_SC_OFFSET) +#define TX_FIFO_LC(x) (((x) & AUDIO_PORT_TX_FIFO_LEVEL_CHECK_MASK) \ + << AUDIO_PORT_TX_FIFO_LC_OFFSET) +#define TX_FIFO_HC(x) (((x) & AUDIO_PORT_TX_FIFO_LEVEL_CHECK_MASK) \ + << AUDIO_PORT_TX_FIFO_HC_OFFSET) + +#define AUDIO_PORT_RX_FIFO_LEVEL_CHECK_MASK 0x0F +#define AUDIO_PORT_RX_FIFO_SC_OFFSET 0 +#define AUDIO_PORT_RX_FIFO_LC_OFFSET 10 +#define AUDIO_PORT_RX_FIFO_HC_OFFSET 20 + +#define RX_FIFO_SC(x) (((x) & AUDIO_PORT_RX_FIFO_LEVEL_CHECK_MASK) \ + << AUDIO_PORT_RX_FIFO_SC_OFFSET) +#define RX_FIFO_LC(x) (((x) & AUDIO_PORT_RX_FIFO_LEVEL_CHECK_MASK) \ + << AUDIO_PORT_RX_FIFO_LC_OFFSET) +#define RX_FIFO_HC(x) (((x) & AUDIO_PORT_RX_FIFO_LEVEL_CHECK_MASK) \ + << AUDIO_PORT_RX_FIFO_HC_OFFSET) +#define AUDIO_PORT_IC_CODEC_TX_CTRL (0x00F4) +#define AUDIO_PORT_IC_CODEC_RX_CTRL (0x00F8) + +#define AUDIO_PORT_IC_TXFIFO_OP (0x00FC) +#define AUDIO_PORT_IC_TXFIFO_LEV_CHK (0x0100) +#define AUDIO_PORT_IC_TXFIFO_STS (0x0104) +#define AUDIO_PORT_IC_TXFIFO_INT (0x0108) +#define AUDIO_PORT_IC_TXFIFO_INT_MSK (0x010C) + +#define AUDIO_PORT_IC_RXFIFO_OP (0x0110) +#define AUDIO_PORT_IC_RXFIFO_LEV_CHK (0x0114) +#define AUDIO_PORT_IC_RXFIFO_STS (0x0118) +#define AUDIO_PORT_IC_RXFIFO_INT (0x011C) +#define AUDIO_PORT_IC_RXFIFO_INT_MSK (0x0120) + +#define AUDIO_FIFO_START (1 << 0) +#define AUDIO_FIFO_RESET (1 << 1) + +#define AUDIO_FIFO_FULL (1 << 0) +#define AUDIO_FIFO_EMPTY (1 << 1) +#define AUDIO_FIFO_OFLOW (1 << 2) +#define AUDIO_FIFO_UFLOW (1 << 3) + +#define IC_TX_ENABLE (0x03) +#define IC_RX_ENABLE_MONO (0x01) +#define IC_RX_ENABLE_STEREO (0x03) + +#endif /*__SIRF_AUDIO_PORT_H*/ diff --git a/sound/soc/sirf/sirf-audio.c b/sound/soc/sirf/sirf-audio.c new file mode 100644 index 00000000000..ecef5102165 --- /dev/null +++ b/sound/soc/sirf/sirf-audio.c @@ -0,0 +1,156 @@ +/* + * SiRF audio card driver + * + * Copyright (c) 2011 Cambridge Silicon Radio Limited, a CSR plc group company. + * + * Licensed under GPLv2 or later. + */ + +#include <linux/platform_device.h> +#include <linux/module.h> +#include <linux/of.h> +#include <linux/gpio.h> +#include <linux/of_gpio.h> +#include <sound/core.h> +#include <sound/pcm.h> +#include <sound/soc.h> + +struct sirf_audio_card { + unsigned int gpio_hp_pa; + unsigned int gpio_spk_pa; +}; + +static int sirf_audio_hp_event(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *ctrl, int event) +{ + struct snd_soc_dapm_context *dapm = w->dapm; + struct snd_soc_card *card = dapm->card; + struct sirf_audio_card *sirf_audio_card = snd_soc_card_get_drvdata(card); + int on = !SND_SOC_DAPM_EVENT_OFF(event); + if (gpio_is_valid(sirf_audio_card->gpio_hp_pa)) + gpio_set_value(sirf_audio_card->gpio_hp_pa, on); + return 0; +} + +static int sirf_audio_spk_event(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *ctrl, int event) +{ + struct snd_soc_dapm_context *dapm = w->dapm; + struct snd_soc_card *card = dapm->card; + struct sirf_audio_card *sirf_audio_card = snd_soc_card_get_drvdata(card); + int on = !SND_SOC_DAPM_EVENT_OFF(event); + + if (gpio_is_valid(sirf_audio_card->gpio_spk_pa)) + gpio_set_value(sirf_audio_card->gpio_spk_pa, on); + + return 0; +} +static const struct snd_soc_dapm_widget sirf_audio_dapm_widgets[] = { + SND_SOC_DAPM_HP("Hp", sirf_audio_hp_event), + SND_SOC_DAPM_SPK("Ext Spk", sirf_audio_spk_event), + SND_SOC_DAPM_MIC("Ext Mic", NULL), +}; + +static const struct snd_soc_dapm_route intercon[] = { + {"Hp", NULL, "HPOUTL"}, + {"Hp", NULL, "HPOUTR"}, + {"Ext Spk", NULL, "SPKOUT"}, + {"MICIN1", NULL, "Mic Bias"}, + {"Mic Bias", NULL, "Ext Mic"}, +}; + +/* Digital audio interface glue - connects codec <--> CPU */ +static struct snd_soc_dai_link sirf_audio_dai_link[] = { + { + .name = "SiRF audio card", + .stream_name = "SiRF audio HiFi", + .codec_dai_name = "sirf-audio-codec", + }, +}; + +/* Audio machine driver */ +static struct snd_soc_card snd_soc_sirf_audio_card = { + .name = "SiRF audio card", + .owner = THIS_MODULE, + .dai_link = sirf_audio_dai_link, + .num_links = ARRAY_SIZE(sirf_audio_dai_link), + .dapm_widgets = sirf_audio_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(sirf_audio_dapm_widgets), + .dapm_routes = intercon, + .num_dapm_routes = ARRAY_SIZE(intercon), +}; + +static int sirf_audio_probe(struct platform_device *pdev) +{ + struct snd_soc_card *card = &snd_soc_sirf_audio_card; + struct sirf_audio_card *sirf_audio_card; + int ret; + + sirf_audio_card = devm_kzalloc(&pdev->dev, sizeof(struct sirf_audio_card), + GFP_KERNEL); + if (sirf_audio_card == NULL) + return -ENOMEM; + + sirf_audio_dai_link[0].cpu_of_node = + of_parse_phandle(pdev->dev.of_node, "sirf,audio-platform", 0); + sirf_audio_dai_link[0].platform_of_node = + of_parse_phandle(pdev->dev.of_node, "sirf,audio-platform", 0); + sirf_audio_dai_link[0].codec_of_node = + of_parse_phandle(pdev->dev.of_node, "sirf,audio-codec", 0); + sirf_audio_card->gpio_spk_pa = of_get_named_gpio(pdev->dev.of_node, + "spk-pa-gpios", 0); + sirf_audio_card->gpio_hp_pa = of_get_named_gpio(pdev->dev.of_node, + "hp-pa-gpios", 0); + if (gpio_is_valid(sirf_audio_card->gpio_spk_pa)) { + ret = devm_gpio_request_one(&pdev->dev, + sirf_audio_card->gpio_spk_pa, + GPIOF_OUT_INIT_LOW, "SPA_PA_SD"); + if (ret) { + dev_err(&pdev->dev, + "Failed to request GPIO_%d for reset: %d\n", + sirf_audio_card->gpio_spk_pa, ret); + return ret; + } + } + if (gpio_is_valid(sirf_audio_card->gpio_hp_pa)) { + ret = devm_gpio_request_one(&pdev->dev, + sirf_audio_card->gpio_hp_pa, + GPIOF_OUT_INIT_LOW, "HP_PA_SD"); + if (ret) { + dev_err(&pdev->dev, + "Failed to request GPIO_%d for reset: %d\n", + sirf_audio_card->gpio_hp_pa, ret); + return ret; + } + } + + card->dev = &pdev->dev; + snd_soc_card_set_drvdata(card, sirf_audio_card); + + ret = devm_snd_soc_register_card(&pdev->dev, card); + if (ret) + dev_err(&pdev->dev, "snd_soc_register_card() failed:%d\n", ret); + + return ret; +} + +static const struct of_device_id sirf_audio_of_match[] = { + {.compatible = "sirf,sirf-audio-card", }, + { }, +}; +MODULE_DEVICE_TABLE(of, sirf_audio_of_match); + +static struct platform_driver sirf_audio_driver = { + .driver = { + .name = "sirf-audio-card", + .owner = THIS_MODULE, + .pm = &snd_soc_pm_ops, + .of_match_table = sirf_audio_of_match, + }, + .probe = sirf_audio_probe, +}; +module_platform_driver(sirf_audio_driver); + +MODULE_AUTHOR("RongJun Ying <RongJun.Ying@csr.com>"); +MODULE_DESCRIPTION("ALSA SoC SIRF audio card driver"); +MODULE_LICENSE("GPL v2"); diff --git a/sound/soc/soc-cache.c b/sound/soc/soc-cache.c index 375dc6dfba4..bfed3e4c45f 100644 --- a/sound/soc/soc-cache.c +++ b/sound/soc/soc-cache.c @@ -96,8 +96,7 @@ int snd_soc_cache_exit(struct snd_soc_codec *codec) { dev_dbg(codec->dev, "ASoC: Destroying cache for %s codec\n", codec->name); - if (!codec->reg_cache) - return 0; + kfree(codec->reg_cache); codec->reg_cache = NULL; return 0; @@ -117,8 +116,9 @@ int snd_soc_cache_read(struct snd_soc_codec *codec, return -EINVAL; mutex_lock(&codec->cache_rw_mutex); - *value = snd_soc_get_cache_val(codec->reg_cache, reg, - codec->driver->reg_word_size); + if (!ZERO_OR_NULL_PTR(codec->reg_cache)) + *value = snd_soc_get_cache_val(codec->reg_cache, reg, + codec->driver->reg_word_size); mutex_unlock(&codec->cache_rw_mutex); return 0; @@ -136,8 +136,9 @@ int snd_soc_cache_write(struct snd_soc_codec *codec, unsigned int reg, unsigned int value) { mutex_lock(&codec->cache_rw_mutex); - snd_soc_set_cache_val(codec->reg_cache, reg, value, - codec->driver->reg_word_size); + if (!ZERO_OR_NULL_PTR(codec->reg_cache)) + snd_soc_set_cache_val(codec->reg_cache, reg, value, + codec->driver->reg_word_size); mutex_unlock(&codec->cache_rw_mutex); return 0; diff --git a/sound/soc/soc-compress.c b/sound/soc/soc-compress.c index 5e9690c85d8..91083e6a6b3 100644 --- a/sound/soc/soc-compress.c +++ b/sound/soc/soc-compress.c @@ -30,8 +30,6 @@ static int soc_compr_open(struct snd_compr_stream *cstream) { struct snd_soc_pcm_runtime *rtd = cstream->private_data; struct snd_soc_platform *platform = rtd->platform; - struct snd_soc_dai *cpu_dai = rtd->cpu_dai; - struct snd_soc_dai *codec_dai = rtd->codec_dai; int ret = 0; mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass); @@ -52,17 +50,7 @@ static int soc_compr_open(struct snd_compr_stream *cstream) } } - if (cstream->direction == SND_COMPRESS_PLAYBACK) { - cpu_dai->playback_active++; - codec_dai->playback_active++; - } else { - cpu_dai->capture_active++; - codec_dai->capture_active++; - } - - cpu_dai->active++; - codec_dai->active++; - rtd->codec->active++; + snd_soc_runtime_activate(rtd, cstream->direction); mutex_unlock(&rtd->pcm_mutex); @@ -81,8 +69,6 @@ static int soc_compr_open_fe(struct snd_compr_stream *cstream) struct snd_soc_pcm_runtime *fe = cstream->private_data; struct snd_pcm_substream *fe_substream = fe->pcm->streams[0].substream; struct snd_soc_platform *platform = fe->platform; - struct snd_soc_dai *cpu_dai = fe->cpu_dai; - struct snd_soc_dai *codec_dai = fe->codec_dai; struct snd_soc_dpcm *dpcm; struct snd_soc_dapm_widget_list *list; int stream; @@ -140,17 +126,7 @@ static int soc_compr_open_fe(struct snd_compr_stream *cstream) fe->dpcm[stream].state = SND_SOC_DPCM_STATE_OPEN; fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_NO; - if (cstream->direction == SND_COMPRESS_PLAYBACK) { - cpu_dai->playback_active++; - codec_dai->playback_active++; - } else { - cpu_dai->capture_active++; - codec_dai->capture_active++; - } - - cpu_dai->active++; - codec_dai->active++; - fe->codec->active++; + snd_soc_runtime_activate(fe, stream); mutex_unlock(&fe->card->mutex); @@ -202,23 +178,18 @@ static int soc_compr_free(struct snd_compr_stream *cstream) struct snd_soc_platform *platform = rtd->platform; struct snd_soc_dai *cpu_dai = rtd->cpu_dai; struct snd_soc_dai *codec_dai = rtd->codec_dai; - struct snd_soc_codec *codec = rtd->codec; + int stream; mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass); - if (cstream->direction == SND_COMPRESS_PLAYBACK) { - cpu_dai->playback_active--; - codec_dai->playback_active--; - } else { - cpu_dai->capture_active--; - codec_dai->capture_active--; - } + if (cstream->direction == SND_COMPRESS_PLAYBACK) + stream = SNDRV_PCM_STREAM_PLAYBACK; + else + stream = SNDRV_PCM_STREAM_CAPTURE; - snd_soc_dai_digital_mute(codec_dai, 1, cstream->direction); + snd_soc_runtime_deactivate(rtd, stream); - cpu_dai->active--; - codec_dai->active--; - codec->active--; + snd_soc_dai_digital_mute(codec_dai, 1, cstream->direction); if (!cpu_dai->active) cpu_dai->rate = 0; @@ -235,8 +206,7 @@ static int soc_compr_free(struct snd_compr_stream *cstream) cpu_dai->runtime = NULL; if (cstream->direction == SND_COMPRESS_PLAYBACK) { - if (!rtd->pmdown_time || codec->ignore_pmdown_time || - rtd->dai_link->ignore_pmdown_time) { + if (snd_soc_runtime_ignore_pmdown_time(rtd)) { snd_soc_dapm_stream_event(rtd, SNDRV_PCM_STREAM_PLAYBACK, SND_SOC_DAPM_STREAM_STOP); @@ -261,26 +231,17 @@ static int soc_compr_free_fe(struct snd_compr_stream *cstream) { struct snd_soc_pcm_runtime *fe = cstream->private_data; struct snd_soc_platform *platform = fe->platform; - struct snd_soc_dai *cpu_dai = fe->cpu_dai; - struct snd_soc_dai *codec_dai = fe->codec_dai; struct snd_soc_dpcm *dpcm; int stream, ret; mutex_lock_nested(&fe->card->mutex, SND_SOC_CARD_CLASS_RUNTIME); - if (cstream->direction == SND_COMPRESS_PLAYBACK) { + if (cstream->direction == SND_COMPRESS_PLAYBACK) stream = SNDRV_PCM_STREAM_PLAYBACK; - cpu_dai->playback_active--; - codec_dai->playback_active--; - } else { + else stream = SNDRV_PCM_STREAM_CAPTURE; - cpu_dai->capture_active--; - codec_dai->capture_active--; - } - cpu_dai->active--; - codec_dai->active--; - fe->codec->active--; + snd_soc_runtime_deactivate(fe, stream); fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_FE; diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index fe1df50805a..051c006281f 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c @@ -56,7 +56,6 @@ EXPORT_SYMBOL_GPL(snd_soc_debugfs_root); #endif static DEFINE_MUTEX(client_mutex); -static LIST_HEAD(dai_list); static LIST_HEAD(platform_list); static LIST_HEAD(codec_list); static LIST_HEAD(component_list); @@ -370,18 +369,22 @@ static ssize_t dai_list_read_file(struct file *file, char __user *user_buf, { char *buf = kmalloc(PAGE_SIZE, GFP_KERNEL); ssize_t len, ret = 0; + struct snd_soc_component *component; struct snd_soc_dai *dai; if (!buf) return -ENOMEM; - list_for_each_entry(dai, &dai_list, list) { - len = snprintf(buf + ret, PAGE_SIZE - ret, "%s\n", dai->name); - if (len >= 0) - ret += len; - if (ret > PAGE_SIZE) { - ret = PAGE_SIZE; - break; + list_for_each_entry(component, &component_list, list) { + list_for_each_entry(dai, &component->dai_list, list) { + len = snprintf(buf + ret, PAGE_SIZE - ret, "%s\n", + dai->name); + if (len >= 0) + ret += len; + if (ret > PAGE_SIZE) { + ret = PAGE_SIZE; + break; + } } } @@ -855,6 +858,7 @@ static int soc_bind_dai_link(struct snd_soc_card *card, int num) { struct snd_soc_dai_link *dai_link = &card->dai_link[num]; struct snd_soc_pcm_runtime *rtd = &card->rtd[num]; + struct snd_soc_component *component; struct snd_soc_codec *codec; struct snd_soc_platform *platform; struct snd_soc_dai *codec_dai, *cpu_dai; @@ -863,18 +867,20 @@ static int soc_bind_dai_link(struct snd_soc_card *card, int num) dev_dbg(card->dev, "ASoC: binding %s at idx %d\n", dai_link->name, num); /* Find CPU DAI from registered DAIs*/ - list_for_each_entry(cpu_dai, &dai_list, list) { + list_for_each_entry(component, &component_list, list) { if (dai_link->cpu_of_node && - (cpu_dai->dev->of_node != dai_link->cpu_of_node)) + component->dev->of_node != dai_link->cpu_of_node) continue; if (dai_link->cpu_name && - strcmp(dev_name(cpu_dai->dev), dai_link->cpu_name)) - continue; - if (dai_link->cpu_dai_name && - strcmp(cpu_dai->name, dai_link->cpu_dai_name)) + strcmp(dev_name(component->dev), dai_link->cpu_name)) continue; + list_for_each_entry(cpu_dai, &component->dai_list, list) { + if (dai_link->cpu_dai_name && + strcmp(cpu_dai->name, dai_link->cpu_dai_name)) + continue; - rtd->cpu_dai = cpu_dai; + rtd->cpu_dai = cpu_dai; + } } if (!rtd->cpu_dai) { @@ -899,12 +905,10 @@ static int soc_bind_dai_link(struct snd_soc_card *card, int num) * CODEC found, so find CODEC DAI from registered DAIs from * this CODEC */ - list_for_each_entry(codec_dai, &dai_list, list) { - if (codec->dev == codec_dai->dev && - !strcmp(codec_dai->name, - dai_link->codec_dai_name)) { - + list_for_each_entry(codec_dai, &codec->component.dai_list, list) { + if (!strcmp(codec_dai->name, dai_link->codec_dai_name)) { rtd->codec_dai = codec_dai; + break; } } @@ -1128,15 +1132,21 @@ static int soc_probe_codec(struct snd_soc_card *card, driver->num_dapm_widgets); /* Create DAPM widgets for each DAI stream */ - list_for_each_entry(dai, &dai_list, list) { - if (dai->dev != codec->dev) - continue; - + list_for_each_entry(dai, &codec->component.dai_list, list) snd_soc_dapm_new_dai_widgets(&codec->dapm, dai); - } codec->dapm.idle_bias_off = driver->idle_bias_off; + if (!codec->write && dev_get_regmap(codec->dev, NULL)) { + /* Set the default I/O up try regmap */ + ret = snd_soc_codec_set_cache_io(codec, NULL); + if (ret < 0) { + dev_err(codec->dev, + "Failed to set cache I/O: %d\n", ret); + goto err_probe; + } + } + if (driver->probe) { ret = driver->probe(codec); if (ret < 0) { @@ -1150,10 +1160,6 @@ static int soc_probe_codec(struct snd_soc_card *card, codec->name); } - /* If the driver didn't set I/O up try regmap */ - if (!codec->write && dev_get_regmap(codec->dev, NULL)) - snd_soc_codec_set_cache_io(codec, 0, 0, SND_SOC_REGMAP); - if (driver->controls) snd_soc_add_codec_controls(codec, driver->controls, driver->num_controls); @@ -1180,6 +1186,7 @@ static int soc_probe_platform(struct snd_soc_card *card, { int ret = 0; const struct snd_soc_platform_driver *driver = platform->driver; + struct snd_soc_component *component; struct snd_soc_dai *dai; platform->card = card; @@ -1195,11 +1202,11 @@ static int soc_probe_platform(struct snd_soc_card *card, driver->dapm_widgets, driver->num_dapm_widgets); /* Create DAPM widgets for each DAI stream */ - list_for_each_entry(dai, &dai_list, list) { - if (dai->dev != platform->dev) + list_for_each_entry(component, &component_list, list) { + if (component->dev != platform->dev) continue; - - snd_soc_dapm_new_dai_widgets(&platform->dapm, dai); + list_for_each_entry(dai, &component->dai_list, list) + snd_soc_dapm_new_dai_widgets(&platform->dapm, dai); } platform->dapm.idle_bias_off = 1; @@ -1246,7 +1253,7 @@ static int soc_post_component_init(struct snd_soc_card *card, struct snd_soc_dai_link *dai_link = NULL; struct snd_soc_aux_dev *aux_dev = NULL; struct snd_soc_pcm_runtime *rtd; - const char *temp, *name; + const char *name; int ret = 0; if (!dailess) { @@ -1260,10 +1267,6 @@ static int soc_post_component_init(struct snd_soc_card *card, } rtd->card = card; - /* machine controls, routes and widgets are not prefixed */ - temp = codec->name_prefix; - codec->name_prefix = NULL; - /* do machine specific initialization */ if (!dailess && dai_link->init) ret = dai_link->init(rtd); @@ -1273,7 +1276,6 @@ static int soc_post_component_init(struct snd_soc_card *card, dev_err(card->dev, "ASoC: failed to init %s: %d\n", name, ret); return ret; } - codec->name_prefix = temp; /* register the rtd device */ rtd->codec = codec; @@ -1654,7 +1656,7 @@ static int snd_soc_instantiate_card(struct snd_soc_card *card) } /* card bind complete so register a sound card */ - ret = snd_card_create(SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1, + ret = snd_card_new(card->dev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1, card->owner, 0, &card->snd_card); if (ret < 0) { dev_err(card->dev, @@ -1662,7 +1664,6 @@ static int snd_soc_instantiate_card(struct snd_soc_card *card) card->name, ret); goto base_error; } - card->snd_card->dev = card->dev; card->dapm.bias_level = SND_SOC_BIAS_OFF; card->dapm.dev = card->dev; @@ -2571,10 +2572,10 @@ int snd_soc_info_enum_double(struct snd_kcontrol *kcontrol, uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; uinfo->count = e->shift_l == e->shift_r ? 1 : 2; - uinfo->value.enumerated.items = e->max; + uinfo->value.enumerated.items = e->items; - if (uinfo->value.enumerated.item > e->max - 1) - uinfo->value.enumerated.item = e->max - 1; + if (uinfo->value.enumerated.item >= e->items) + uinfo->value.enumerated.item = e->items - 1; strlcpy(uinfo->value.enumerated.name, e->texts[uinfo->value.enumerated.item], sizeof(uinfo->value.enumerated.name)); @@ -2596,14 +2597,18 @@ int snd_soc_get_enum_double(struct snd_kcontrol *kcontrol, { struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; - unsigned int val; + unsigned int val, item; + unsigned int reg_val; - val = snd_soc_read(codec, e->reg); - ucontrol->value.enumerated.item[0] - = (val >> e->shift_l) & e->mask; - if (e->shift_l != e->shift_r) - ucontrol->value.enumerated.item[1] = - (val >> e->shift_r) & e->mask; + reg_val = snd_soc_read(codec, e->reg); + val = (reg_val >> e->shift_l) & e->mask; + item = snd_soc_enum_val_to_item(e, val); + ucontrol->value.enumerated.item[0] = item; + if (e->shift_l != e->shift_r) { + val = (reg_val >> e->shift_l) & e->mask; + item = snd_soc_enum_val_to_item(e, val); + ucontrol->value.enumerated.item[1] = item; + } return 0; } @@ -2623,17 +2628,18 @@ int snd_soc_put_enum_double(struct snd_kcontrol *kcontrol, { struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; + unsigned int *item = ucontrol->value.enumerated.item; unsigned int val; unsigned int mask; - if (ucontrol->value.enumerated.item[0] > e->max - 1) + if (item[0] >= e->items) return -EINVAL; - val = ucontrol->value.enumerated.item[0] << e->shift_l; + val = snd_soc_enum_item_to_val(e, item[0]) << e->shift_l; mask = e->mask << e->shift_l; if (e->shift_l != e->shift_r) { - if (ucontrol->value.enumerated.item[1] > e->max - 1) + if (item[1] >= e->items) return -EINVAL; - val |= ucontrol->value.enumerated.item[1] << e->shift_r; + val |= snd_soc_enum_item_to_val(e, item[1]) << e->shift_r; mask |= e->mask << e->shift_r; } @@ -2642,78 +2648,46 @@ int snd_soc_put_enum_double(struct snd_kcontrol *kcontrol, EXPORT_SYMBOL_GPL(snd_soc_put_enum_double); /** - * snd_soc_get_value_enum_double - semi enumerated double mixer get callback - * @kcontrol: mixer control - * @ucontrol: control element information - * - * Callback to get the value of a double semi enumerated mixer. + * snd_soc_read_signed - Read a codec register and interprete as signed value + * @codec: codec + * @reg: Register to read + * @mask: Mask to use after shifting the register value + * @shift: Right shift of register value + * @sign_bit: Bit that describes if a number is negative or not. * - * Semi enumerated mixer: the enumerated items are referred as values. Can be - * used for handling bitfield coded enumeration for example. + * This functions reads a codec register. The register value is shifted right + * by 'shift' bits and masked with the given 'mask'. Afterwards it translates + * the given registervalue into a signed integer if sign_bit is non-zero. * - * Returns 0 for success. + * Returns the register value as signed int. */ -int snd_soc_get_value_enum_double(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) +static int snd_soc_read_signed(struct snd_soc_codec *codec, unsigned int reg, + unsigned int mask, unsigned int shift, unsigned int sign_bit) { - struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); - struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; - unsigned int reg_val, val, mux; + int ret; + unsigned int val; - reg_val = snd_soc_read(codec, e->reg); - val = (reg_val >> e->shift_l) & e->mask; - for (mux = 0; mux < e->max; mux++) { - if (val == e->values[mux]) - break; - } - ucontrol->value.enumerated.item[0] = mux; - if (e->shift_l != e->shift_r) { - val = (reg_val >> e->shift_r) & e->mask; - for (mux = 0; mux < e->max; mux++) { - if (val == e->values[mux]) - break; - } - ucontrol->value.enumerated.item[1] = mux; - } + val = (snd_soc_read(codec, reg) >> shift) & mask; - return 0; -} -EXPORT_SYMBOL_GPL(snd_soc_get_value_enum_double); + if (!sign_bit) + return val; -/** - * snd_soc_put_value_enum_double - semi enumerated double mixer put callback - * @kcontrol: mixer control - * @ucontrol: control element information - * - * Callback to set the value of a double semi enumerated mixer. - * - * Semi enumerated mixer: the enumerated items are referred as values. Can be - * used for handling bitfield coded enumeration for example. - * - * Returns 0 for success. - */ -int snd_soc_put_value_enum_double(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); - struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; - unsigned int val; - unsigned int mask; + /* non-negative number */ + if (!(val & BIT(sign_bit))) + return val; - if (ucontrol->value.enumerated.item[0] > e->max - 1) - return -EINVAL; - val = e->values[ucontrol->value.enumerated.item[0]] << e->shift_l; - mask = e->mask << e->shift_l; - if (e->shift_l != e->shift_r) { - if (ucontrol->value.enumerated.item[1] > e->max - 1) - return -EINVAL; - val |= e->values[ucontrol->value.enumerated.item[1]] << e->shift_r; - mask |= e->mask << e->shift_r; - } + ret = val; - return snd_soc_update_bits_locked(codec, e->reg, mask, val); + /* + * The register most probably does not contain a full-sized int. + * Instead we have an arbitrary number of bits in a signed + * representation which has to be translated into a full-sized int. + * This is done by filling up all bits above the sign-bit. + */ + ret |= ~((int)(BIT(sign_bit) - 1)); + + return ret; } -EXPORT_SYMBOL_GPL(snd_soc_put_value_enum_double); /** * snd_soc_info_volsw - single mixer info callback @@ -2743,7 +2717,7 @@ int snd_soc_info_volsw(struct snd_kcontrol *kcontrol, uinfo->count = snd_soc_volsw_is_stereo(mc) ? 2 : 1; uinfo->value.integer.min = 0; - uinfo->value.integer.max = platform_max; + uinfo->value.integer.max = platform_max - mc->min; return 0; } EXPORT_SYMBOL_GPL(snd_soc_info_volsw); @@ -2769,11 +2743,16 @@ int snd_soc_get_volsw(struct snd_kcontrol *kcontrol, unsigned int shift = mc->shift; unsigned int rshift = mc->rshift; int max = mc->max; + int min = mc->min; + int sign_bit = mc->sign_bit; unsigned int mask = (1 << fls(max)) - 1; unsigned int invert = mc->invert; - ucontrol->value.integer.value[0] = - (snd_soc_read(codec, reg) >> shift) & mask; + if (sign_bit) + mask = BIT(sign_bit + 1) - 1; + + ucontrol->value.integer.value[0] = snd_soc_read_signed(codec, reg, mask, + shift, sign_bit) - min; if (invert) ucontrol->value.integer.value[0] = max - ucontrol->value.integer.value[0]; @@ -2781,10 +2760,12 @@ int snd_soc_get_volsw(struct snd_kcontrol *kcontrol, if (snd_soc_volsw_is_stereo(mc)) { if (reg == reg2) ucontrol->value.integer.value[1] = - (snd_soc_read(codec, reg) >> rshift) & mask; + snd_soc_read_signed(codec, reg, mask, rshift, + sign_bit) - min; else ucontrol->value.integer.value[1] = - (snd_soc_read(codec, reg2) >> shift) & mask; + snd_soc_read_signed(codec, reg2, mask, shift, + sign_bit) - min; if (invert) ucontrol->value.integer.value[1] = max - ucontrol->value.integer.value[1]; @@ -2815,20 +2796,25 @@ int snd_soc_put_volsw(struct snd_kcontrol *kcontrol, unsigned int shift = mc->shift; unsigned int rshift = mc->rshift; int max = mc->max; + int min = mc->min; + unsigned int sign_bit = mc->sign_bit; unsigned int mask = (1 << fls(max)) - 1; unsigned int invert = mc->invert; int err; - bool type_2r = 0; + bool type_2r = false; unsigned int val2 = 0; unsigned int val, val_mask; - val = (ucontrol->value.integer.value[0] & mask); + if (sign_bit) + mask = BIT(sign_bit + 1) - 1; + + val = ((ucontrol->value.integer.value[0] + min) & mask); if (invert) val = max - val; val_mask = mask << shift; val = val << shift; if (snd_soc_volsw_is_stereo(mc)) { - val2 = (ucontrol->value.integer.value[1] & mask); + val2 = ((ucontrol->value.integer.value[1] + min) & mask); if (invert) val2 = max - val2; if (reg == reg2) { @@ -2836,7 +2822,7 @@ int snd_soc_put_volsw(struct snd_kcontrol *kcontrol, val |= val2 << rshift; } else { val2 = val2 << shift; - type_2r = 1; + type_2r = true; } } err = snd_soc_update_bits_locked(codec, reg, val_mask, val); @@ -3234,7 +3220,7 @@ int snd_soc_bytes_put(struct snd_kcontrol *kcontrol, struct soc_bytes *params = (void *)kcontrol->private_value; struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); int ret, len; - unsigned int val; + unsigned int val, mask; void *data; if (!codec->using_regmap) @@ -3264,12 +3250,36 @@ int snd_soc_bytes_put(struct snd_kcontrol *kcontrol, ((u8 *)data)[0] |= val; break; case 2: - ((u16 *)data)[0] &= cpu_to_be16(~params->mask); - ((u16 *)data)[0] |= cpu_to_be16(val); + mask = ~params->mask; + ret = regmap_parse_val(codec->control_data, + &mask, &mask); + if (ret != 0) + goto out; + + ((u16 *)data)[0] &= mask; + + ret = regmap_parse_val(codec->control_data, + &val, &val); + if (ret != 0) + goto out; + + ((u16 *)data)[0] |= val; break; case 4: - ((u32 *)data)[0] &= cpu_to_be32(~params->mask); - ((u32 *)data)[0] |= cpu_to_be32(val); + mask = ~params->mask; + ret = regmap_parse_val(codec->control_data, + &mask, &mask); + if (ret != 0) + goto out; + + ((u32 *)data)[0] &= mask; + + ret = regmap_parse_val(codec->control_data, + &val, &val); + if (ret != 0) + goto out; + + ((u32 *)data)[0] |= val; break; default: ret = -EINVAL; @@ -3609,6 +3619,30 @@ int snd_soc_dai_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) EXPORT_SYMBOL_GPL(snd_soc_dai_set_fmt); /** + * snd_soc_xlate_tdm_slot - generate tx/rx slot mask. + * @slots: Number of slots in use. + * @tx_mask: bitmask representing active TX slots. + * @rx_mask: bitmask representing active RX slots. + * + * Generates the TDM tx and rx slot default masks for DAI. + */ +static int snd_soc_xlate_tdm_slot_mask(unsigned int slots, + unsigned int *tx_mask, + unsigned int *rx_mask) +{ + if (*tx_mask || *rx_mask) + return 0; + + if (!slots) + return -EINVAL; + + *tx_mask = (1 << slots) - 1; + *rx_mask = (1 << slots) - 1; + + return 0; +} + +/** * snd_soc_dai_set_tdm_slot - configure DAI TDM. * @dai: DAI * @tx_mask: bitmask representing active TX slots. @@ -3622,11 +3656,17 @@ EXPORT_SYMBOL_GPL(snd_soc_dai_set_fmt); int snd_soc_dai_set_tdm_slot(struct snd_soc_dai *dai, unsigned int tx_mask, unsigned int rx_mask, int slots, int slot_width) { + if (dai->driver && dai->driver->ops->xlate_tdm_slot_mask) + dai->driver->ops->xlate_tdm_slot_mask(slots, + &tx_mask, &rx_mask); + else + snd_soc_xlate_tdm_slot_mask(slots, &tx_mask, &rx_mask); + if (dai->driver && dai->driver->ops->set_tdm_slot) return dai->driver->ops->set_tdm_slot(dai, tx_mask, rx_mask, slots, slot_width); else - return -EINVAL; + return -ENOTSUPP; } EXPORT_SYMBOL_GPL(snd_soc_dai_set_tdm_slot); @@ -3882,95 +3922,42 @@ static inline char *fmt_multiple_name(struct device *dev, } /** - * snd_soc_register_dai - Register a DAI with the ASoC core + * snd_soc_unregister_dai - Unregister DAIs from the ASoC core * - * @dai: DAI to register + * @component: The component for which the DAIs should be unregistered */ -static int snd_soc_register_dai(struct device *dev, - struct snd_soc_dai_driver *dai_drv) +static void snd_soc_unregister_dais(struct snd_soc_component *component) { - struct snd_soc_codec *codec; - struct snd_soc_dai *dai; + struct snd_soc_dai *dai, *_dai; - dev_dbg(dev, "ASoC: dai register %s\n", dev_name(dev)); - - dai = kzalloc(sizeof(struct snd_soc_dai), GFP_KERNEL); - if (dai == NULL) - return -ENOMEM; - - /* create DAI component name */ - dai->name = fmt_single_name(dev, &dai->id); - if (dai->name == NULL) { + list_for_each_entry_safe(dai, _dai, &component->dai_list, list) { + dev_dbg(component->dev, "ASoC: Unregistered DAI '%s'\n", + dai->name); + list_del(&dai->list); + kfree(dai->name); kfree(dai); - return -ENOMEM; - } - - dai->dev = dev; - dai->driver = dai_drv; - dai->dapm.dev = dev; - if (!dai->driver->ops) - dai->driver->ops = &null_dai_ops; - - mutex_lock(&client_mutex); - - list_for_each_entry(codec, &codec_list, list) { - if (codec->dev == dev) { - dev_dbg(dev, "ASoC: Mapped DAI %s to CODEC %s\n", - dai->name, codec->name); - dai->codec = codec; - break; - } - } - - if (!dai->codec) - dai->dapm.idle_bias_off = 1; - - list_add(&dai->list, &dai_list); - - mutex_unlock(&client_mutex); - - dev_dbg(dev, "ASoC: Registered DAI '%s'\n", dai->name); - - return 0; -} - -/** - * snd_soc_unregister_dai - Unregister a DAI from the ASoC core - * - * @dai: DAI to unregister - */ -static void snd_soc_unregister_dai(struct device *dev) -{ - struct snd_soc_dai *dai; - - list_for_each_entry(dai, &dai_list, list) { - if (dev == dai->dev) - goto found; } - return; - -found: - mutex_lock(&client_mutex); - list_del(&dai->list); - mutex_unlock(&client_mutex); - - dev_dbg(dev, "ASoC: Unregistered DAI '%s'\n", dai->name); - kfree(dai->name); - kfree(dai); } /** - * snd_soc_register_dais - Register multiple DAIs with the ASoC core + * snd_soc_register_dais - Register a DAI with the ASoC core * - * @dai: Array of DAIs to register + * @component: The component the DAIs are registered for + * @codec: The CODEC that the DAIs are registered for, NULL if the component is + * not a CODEC. + * @dai_drv: DAI driver to use for the DAIs * @count: Number of DAIs + * @legacy_dai_naming: Use the legacy naming scheme and let the DAI inherit the + * parent's name. */ -static int snd_soc_register_dais(struct device *dev, - struct snd_soc_dai_driver *dai_drv, size_t count) +static int snd_soc_register_dais(struct snd_soc_component *component, + struct snd_soc_codec *codec, struct snd_soc_dai_driver *dai_drv, + size_t count, bool legacy_dai_naming) { - struct snd_soc_codec *codec; + struct device *dev = component->dev; struct snd_soc_dai *dai; - int i, ret = 0; + unsigned int i; + int ret; dev_dbg(dev, "ASoC: dai register %s #%Zu\n", dev_name(dev), count); @@ -3982,70 +3969,54 @@ static int snd_soc_register_dais(struct device *dev, goto err; } - /* create DAI component name */ - dai->name = fmt_multiple_name(dev, &dai_drv[i]); + /* + * Back in the old days when we still had component-less DAIs, + * instead of having a static name, component-less DAIs would + * inherit the name of the parent device so it is possible to + * register multiple instances of the DAI. We still need to keep + * the same naming style even though those DAIs are not + * component-less anymore. + */ + if (count == 1 && legacy_dai_naming) { + dai->name = fmt_single_name(dev, &dai->id); + } else { + dai->name = fmt_multiple_name(dev, &dai_drv[i]); + if (dai_drv[i].id) + dai->id = dai_drv[i].id; + else + dai->id = i; + } if (dai->name == NULL) { kfree(dai); - ret = -EINVAL; + ret = -ENOMEM; goto err; } + dai->component = component; + dai->codec = codec; dai->dev = dev; dai->driver = &dai_drv[i]; - if (dai->driver->id) - dai->id = dai->driver->id; - else - dai->id = i; dai->dapm.dev = dev; if (!dai->driver->ops) dai->driver->ops = &null_dai_ops; - mutex_lock(&client_mutex); - - list_for_each_entry(codec, &codec_list, list) { - if (codec->dev == dev) { - dev_dbg(dev, - "ASoC: Mapped DAI %s to CODEC %s\n", - dai->name, codec->name); - dai->codec = codec; - break; - } - } - if (!dai->codec) dai->dapm.idle_bias_off = 1; - list_add(&dai->list, &dai_list); - - mutex_unlock(&client_mutex); + list_add(&dai->list, &component->dai_list); - dev_dbg(dai->dev, "ASoC: Registered DAI '%s'\n", dai->name); + dev_dbg(dev, "ASoC: Registered DAI '%s'\n", dai->name); } return 0; err: - for (i--; i >= 0; i--) - snd_soc_unregister_dai(dev); + snd_soc_unregister_dais(component); return ret; } /** - * snd_soc_unregister_dais - Unregister multiple DAIs from the ASoC core - * - * @dai: Array of DAIs to unregister - * @count: Number of DAIs - */ -static void snd_soc_unregister_dais(struct device *dev, size_t count) -{ - int i; - - for (i = 0; i < count; i++) - snd_soc_unregister_dai(dev); -} - -/** * snd_soc_register_component - Register a component with the ASoC core * */ @@ -4053,6 +4024,7 @@ static int __snd_soc_register_component(struct device *dev, struct snd_soc_component *cmpnt, const struct snd_soc_component_driver *cmpnt_drv, + struct snd_soc_codec *codec, struct snd_soc_dai_driver *dai_drv, int num_dai, bool allow_single_dai) { @@ -4075,20 +4047,10 @@ __snd_soc_register_component(struct device *dev, cmpnt->driver = cmpnt_drv; cmpnt->dai_drv = dai_drv; cmpnt->num_dai = num_dai; + INIT_LIST_HEAD(&cmpnt->dai_list); - /* - * snd_soc_register_dai() uses fmt_single_name(), and - * snd_soc_register_dais() uses fmt_multiple_name() - * for dai->name which is used for name based matching - * - * this function is used from cpu/codec. - * allow_single_dai flag can ignore "codec" driver reworking - * since it had been used snd_soc_register_dais(), - */ - if ((1 == num_dai) && allow_single_dai) - ret = snd_soc_register_dai(dev, dai_drv); - else - ret = snd_soc_register_dais(dev, dai_drv, num_dai); + ret = snd_soc_register_dais(cmpnt, codec, dai_drv, num_dai, + allow_single_dai); if (ret < 0) { dev_err(dev, "ASoC: Failed to regster DAIs: %d\n", ret); goto error_component_name; @@ -4121,7 +4083,9 @@ int snd_soc_register_component(struct device *dev, return -ENOMEM; } - return __snd_soc_register_component(dev, cmpnt, cmpnt_drv, + cmpnt->ignore_pmdown_time = true; + + return __snd_soc_register_component(dev, cmpnt, cmpnt_drv, NULL, dai_drv, num_dai, true); } EXPORT_SYMBOL_GPL(snd_soc_register_component); @@ -4141,7 +4105,7 @@ void snd_soc_unregister_component(struct device *dev) return; found: - snd_soc_unregister_dais(dev, cmpnt->num_dai); + snd_soc_unregister_dais(cmpnt); mutex_lock(&client_mutex); list_del(&cmpnt->list); @@ -4319,7 +4283,7 @@ int snd_soc_register_codec(struct device *dev, codec->volatile_register = codec_drv->volatile_register; codec->readable_register = codec_drv->readable_register; codec->writable_register = codec_drv->writable_register; - codec->ignore_pmdown_time = codec_drv->ignore_pmdown_time; + codec->component.ignore_pmdown_time = codec_drv->ignore_pmdown_time; codec->dapm.bias_level = SND_SOC_BIAS_OFF; codec->dapm.dev = dev; codec->dapm.codec = codec; @@ -4342,7 +4306,7 @@ int snd_soc_register_codec(struct device *dev, /* register component */ ret = __snd_soc_register_component(dev, &codec->component, &codec_drv->component_driver, - dai_drv, num_dai, false); + codec, dai_drv, num_dai, false); if (ret < 0) { dev_err(codec->dev, "ASoC: Failed to regster component: %d\n", ret); goto fail_codec_name; @@ -4417,6 +4381,122 @@ int snd_soc_of_parse_card_name(struct snd_soc_card *card, } EXPORT_SYMBOL_GPL(snd_soc_of_parse_card_name); +static const struct snd_soc_dapm_widget simple_widgets[] = { + SND_SOC_DAPM_MIC("Microphone", NULL), + SND_SOC_DAPM_LINE("Line", NULL), + SND_SOC_DAPM_HP("Headphone", NULL), + SND_SOC_DAPM_SPK("Speaker", NULL), +}; + +int snd_soc_of_parse_audio_simple_widgets(struct snd_soc_card *card, + const char *propname) +{ + struct device_node *np = card->dev->of_node; + struct snd_soc_dapm_widget *widgets; + const char *template, *wname; + int i, j, num_widgets, ret; + + num_widgets = of_property_count_strings(np, propname); + if (num_widgets < 0) { + dev_err(card->dev, + "ASoC: Property '%s' does not exist\n", propname); + return -EINVAL; + } + if (num_widgets & 1) { + dev_err(card->dev, + "ASoC: Property '%s' length is not even\n", propname); + return -EINVAL; + } + + num_widgets /= 2; + if (!num_widgets) { + dev_err(card->dev, "ASoC: Property '%s's length is zero\n", + propname); + return -EINVAL; + } + + widgets = devm_kcalloc(card->dev, num_widgets, sizeof(*widgets), + GFP_KERNEL); + if (!widgets) { + dev_err(card->dev, + "ASoC: Could not allocate memory for widgets\n"); + return -ENOMEM; + } + + for (i = 0; i < num_widgets; i++) { + ret = of_property_read_string_index(np, propname, + 2 * i, &template); + if (ret) { + dev_err(card->dev, + "ASoC: Property '%s' index %d read error:%d\n", + propname, 2 * i, ret); + return -EINVAL; + } + + for (j = 0; j < ARRAY_SIZE(simple_widgets); j++) { + if (!strncmp(template, simple_widgets[j].name, + strlen(simple_widgets[j].name))) { + widgets[i] = simple_widgets[j]; + break; + } + } + + if (j >= ARRAY_SIZE(simple_widgets)) { + dev_err(card->dev, + "ASoC: DAPM widget '%s' is not supported\n", + template); + return -EINVAL; + } + + ret = of_property_read_string_index(np, propname, + (2 * i) + 1, + &wname); + if (ret) { + dev_err(card->dev, + "ASoC: Property '%s' index %d read error:%d\n", + propname, (2 * i) + 1, ret); + return -EINVAL; + } + + widgets[i].name = wname; + } + + card->dapm_widgets = widgets; + card->num_dapm_widgets = num_widgets; + + return 0; +} +EXPORT_SYMBOL_GPL(snd_soc_of_parse_audio_simple_widgets); + +int snd_soc_of_parse_tdm_slot(struct device_node *np, + unsigned int *slots, + unsigned int *slot_width) +{ + u32 val; + int ret; + + if (of_property_read_bool(np, "dai-tdm-slot-num")) { + ret = of_property_read_u32(np, "dai-tdm-slot-num", &val); + if (ret) + return ret; + + if (slots) + *slots = val; + } + + if (of_property_read_bool(np, "dai-tdm-slot-width")) { + ret = of_property_read_u32(np, "dai-tdm-slot-width", &val); + if (ret) + return ret; + + if (slot_width) + *slot_width = val; + } + + return 0; +} +EXPORT_SYMBOL_GPL(snd_soc_of_parse_tdm_slot); + int snd_soc_of_parse_audio_routing(struct snd_soc_card *card, const char *propname) { diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c index b9dc6acbba8..c8a780d0d05 100644 --- a/sound/soc/soc-dapm.c +++ b/sound/soc/soc-dapm.c @@ -70,8 +70,6 @@ static int dapm_up_seq[] = { [snd_soc_dapm_aif_out] = 4, [snd_soc_dapm_mic] = 5, [snd_soc_dapm_mux] = 6, - [snd_soc_dapm_virt_mux] = 6, - [snd_soc_dapm_value_mux] = 6, [snd_soc_dapm_dac] = 7, [snd_soc_dapm_switch] = 8, [snd_soc_dapm_mixer] = 8, @@ -102,8 +100,6 @@ static int dapm_down_seq[] = { [snd_soc_dapm_mic] = 7, [snd_soc_dapm_micbias] = 8, [snd_soc_dapm_mux] = 9, - [snd_soc_dapm_virt_mux] = 9, - [snd_soc_dapm_value_mux] = 9, [snd_soc_dapm_aif_in] = 10, [snd_soc_dapm_aif_out] = 10, [snd_soc_dapm_dai_in] = 10, @@ -115,6 +111,12 @@ static int dapm_down_seq[] = { [snd_soc_dapm_post] = 14, }; +static void dapm_assert_locked(struct snd_soc_dapm_context *dapm) +{ + if (dapm->card && dapm->card->instantiated) + lockdep_assert_held(&dapm->card->dapm_mutex); +} + static void pop_wait(u32 pop_time) { if (pop_time) @@ -146,15 +148,16 @@ static bool dapm_dirty_widget(struct snd_soc_dapm_widget *w) return !list_empty(&w->dirty); } -void dapm_mark_dirty(struct snd_soc_dapm_widget *w, const char *reason) +static void dapm_mark_dirty(struct snd_soc_dapm_widget *w, const char *reason) { + dapm_assert_locked(w->dapm); + if (!dapm_dirty_widget(w)) { dev_vdbg(w->dapm->dev, "Marking %s dirty due to %s\n", w->name, reason); list_add_tail(&w->dirty, &w->dapm->card->dapm_dirty); } } -EXPORT_SYMBOL_GPL(dapm_mark_dirty); void dapm_mark_io_dirty(struct snd_soc_dapm_context *dapm) { @@ -361,6 +364,8 @@ static void dapm_reset(struct snd_soc_card *card) { struct snd_soc_dapm_widget *w; + lockdep_assert_held(&card->dapm_mutex); + memset(&card->dapm_stats, 0, sizeof(card->dapm_stats)); list_for_each_entry(w, &card->widgets, list) { @@ -386,7 +391,8 @@ static int soc_widget_read(struct snd_soc_dapm_widget *w, int reg, return -1; } -static int soc_widget_write(struct snd_soc_dapm_widget *w, int reg, int val) +static int soc_widget_write(struct snd_soc_dapm_widget *w, int reg, + unsigned int val) { if (w->codec) return snd_soc_write(w->codec, reg, val); @@ -498,131 +504,40 @@ out: return ret; } -/* set up initial codec paths */ -static void dapm_set_path_status(struct snd_soc_dapm_widget *w, - struct snd_soc_dapm_path *p, int i) +/* connect mux widget to its interconnecting audio paths */ +static int dapm_connect_mux(struct snd_soc_dapm_context *dapm, + struct snd_soc_dapm_widget *src, struct snd_soc_dapm_widget *dest, + struct snd_soc_dapm_path *path, const char *control_name, + const struct snd_kcontrol_new *kcontrol) { - switch (w->id) { - case snd_soc_dapm_switch: - case snd_soc_dapm_mixer: - case snd_soc_dapm_mixer_named_ctl: { - int val; - struct soc_mixer_control *mc = (struct soc_mixer_control *) - w->kcontrol_news[i].private_value; - int reg = mc->reg; - unsigned int shift = mc->shift; - int max = mc->max; - unsigned int mask = (1 << fls(max)) - 1; - unsigned int invert = mc->invert; - - if (reg != SND_SOC_NOPM) { - soc_widget_read(w, reg, &val); - val = (val >> shift) & mask; - if (invert) - val = max - val; - p->connect = !!val; - } else { - p->connect = 0; - } - - } - break; - case snd_soc_dapm_mux: { - struct soc_enum *e = (struct soc_enum *) - w->kcontrol_news[i].private_value; - int val, item; - - soc_widget_read(w, e->reg, &val); - item = (val >> e->shift_l) & e->mask; - - if (item < e->max && !strcmp(p->name, e->texts[item])) - p->connect = 1; - else - p->connect = 0; - } - break; - case snd_soc_dapm_virt_mux: { - struct soc_enum *e = (struct soc_enum *) - w->kcontrol_news[i].private_value; + struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; + unsigned int val, item; + int i; - p->connect = 0; + if (e->reg != SND_SOC_NOPM) { + soc_widget_read(dest, e->reg, &val); + val = (val >> e->shift_l) & e->mask; + item = snd_soc_enum_val_to_item(e, val); + } else { /* since a virtual mux has no backing registers to * decide which path to connect, it will try to match * with the first enumeration. This is to ensure * that the default mux choice (the first) will be * correctly powered up during initialization. */ - if (!strcmp(p->name, e->texts[0])) - p->connect = 1; + item = 0; } - break; - case snd_soc_dapm_value_mux: { - struct soc_enum *e = (struct soc_enum *) - w->kcontrol_news[i].private_value; - int val, item; - soc_widget_read(w, e->reg, &val); - val = (val >> e->shift_l) & e->mask; - for (item = 0; item < e->max; item++) { - if (val == e->values[item]) - break; - } - - if (item < e->max && !strcmp(p->name, e->texts[item])) - p->connect = 1; - else - p->connect = 0; - } - break; - /* does not affect routing - always connected */ - case snd_soc_dapm_pga: - case snd_soc_dapm_out_drv: - case snd_soc_dapm_output: - case snd_soc_dapm_adc: - case snd_soc_dapm_input: - case snd_soc_dapm_siggen: - case snd_soc_dapm_dac: - case snd_soc_dapm_micbias: - case snd_soc_dapm_vmid: - case snd_soc_dapm_supply: - case snd_soc_dapm_regulator_supply: - case snd_soc_dapm_clock_supply: - case snd_soc_dapm_aif_in: - case snd_soc_dapm_aif_out: - case snd_soc_dapm_dai_in: - case snd_soc_dapm_dai_out: - case snd_soc_dapm_hp: - case snd_soc_dapm_mic: - case snd_soc_dapm_spk: - case snd_soc_dapm_line: - case snd_soc_dapm_dai_link: - case snd_soc_dapm_kcontrol: - p->connect = 1; - break; - /* does affect routing - dynamically connected */ - case snd_soc_dapm_pre: - case snd_soc_dapm_post: - p->connect = 0; - break; - } -} - -/* connect mux widget to its interconnecting audio paths */ -static int dapm_connect_mux(struct snd_soc_dapm_context *dapm, - struct snd_soc_dapm_widget *src, struct snd_soc_dapm_widget *dest, - struct snd_soc_dapm_path *path, const char *control_name, - const struct snd_kcontrol_new *kcontrol) -{ - struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; - int i; - - for (i = 0; i < e->max; i++) { + for (i = 0; i < e->items; i++) { if (!(strcmp(control_name, e->texts[i]))) { list_add(&path->list, &dapm->card->paths); list_add(&path->list_sink, &dest->sources); list_add(&path->list_source, &src->sinks); path->name = (char*)e->texts[i]; - dapm_set_path_status(dest, path, 0); + if (i == item) + path->connect = 1; + else + path->connect = 0; return 0; } } @@ -630,6 +545,30 @@ static int dapm_connect_mux(struct snd_soc_dapm_context *dapm, return -ENODEV; } +/* set up initial codec paths */ +static void dapm_set_mixer_path_status(struct snd_soc_dapm_widget *w, + struct snd_soc_dapm_path *p, int i) +{ + struct soc_mixer_control *mc = (struct soc_mixer_control *) + w->kcontrol_news[i].private_value; + unsigned int reg = mc->reg; + unsigned int shift = mc->shift; + unsigned int max = mc->max; + unsigned int mask = (1 << fls(max)) - 1; + unsigned int invert = mc->invert; + unsigned int val; + + if (reg != SND_SOC_NOPM) { + soc_widget_read(w, reg, &val); + val = (val >> shift) & mask; + if (invert) + val = max - val; + p->connect = !!val; + } else { + p->connect = 0; + } +} + /* connect mixer widget to its interconnecting audio paths */ static int dapm_connect_mixer(struct snd_soc_dapm_context *dapm, struct snd_soc_dapm_widget *src, struct snd_soc_dapm_widget *dest, @@ -644,7 +583,7 @@ static int dapm_connect_mixer(struct snd_soc_dapm_context *dapm, list_add(&path->list_sink, &dest->sources); list_add(&path->list_source, &src->sinks); path->name = dest->kcontrol_news[i].name; - dapm_set_path_status(dest, path, i); + dapm_set_mixer_path_status(dest, path, i); return 0; } } @@ -723,8 +662,6 @@ static int dapm_create_or_share_mixmux_kcontrol(struct snd_soc_dapm_widget *w, kcname_in_long_name = true; break; case snd_soc_dapm_mux: - case snd_soc_dapm_virt_mux: - case snd_soc_dapm_value_mux: wname_in_long_name = true; kcname_in_long_name = false; break; @@ -1823,6 +1760,8 @@ static int dapm_power_widgets(struct snd_soc_card *card, int event) ASYNC_DOMAIN_EXCLUSIVE(async_domain); enum snd_soc_bias_level bias; + lockdep_assert_held(&card->dapm_mutex); + trace_snd_soc_dapm_start(card); list_for_each_entry(d, &card->dapm_list, list) { @@ -1897,10 +1836,14 @@ static int dapm_power_widgets(struct snd_soc_card *card, int event) trace_snd_soc_dapm_walk_done(card); - /* Run all the bias changes in parallel */ - list_for_each_entry(d, &card->dapm_list, list) - async_schedule_domain(dapm_pre_sequence_async, d, - &async_domain); + /* Run card bias changes at first */ + dapm_pre_sequence_async(&card->dapm, 0); + /* Run other bias changes in parallel */ + list_for_each_entry(d, &card->dapm_list, list) { + if (d != &card->dapm) + async_schedule_domain(dapm_pre_sequence_async, d, + &async_domain); + } async_synchronize_full_domain(&async_domain); list_for_each_entry(w, &down_list, power_list) { @@ -1920,10 +1863,14 @@ static int dapm_power_widgets(struct snd_soc_card *card, int event) dapm_seq_run(card, &up_list, event, true); /* Run all the bias changes in parallel */ - list_for_each_entry(d, &card->dapm_list, list) - async_schedule_domain(dapm_post_sequence_async, d, - &async_domain); + list_for_each_entry(d, &card->dapm_list, list) { + if (d != &card->dapm) + async_schedule_domain(dapm_post_sequence_async, d, + &async_domain); + } async_synchronize_full_domain(&async_domain); + /* Run card bias changes at last */ + dapm_post_sequence_async(&card->dapm, 0); /* do we need to notify any clients that DAPM event is complete */ list_for_each_entry(d, &card->dapm_list, list) { @@ -2110,6 +2057,8 @@ static int soc_dapm_mux_update_power(struct snd_soc_card *card, struct snd_soc_dapm_path *path; int found = 0; + lockdep_assert_held(&card->dapm_mutex); + /* find dapm widget path assoc with kcontrol */ dapm_kcontrol_for_each_path(path, kcontrol) { if (!path->name || !e->texts[mux]) @@ -2160,6 +2109,8 @@ static int soc_dapm_mixer_update_power(struct snd_soc_card *card, struct snd_soc_dapm_path *path; int found = 0; + lockdep_assert_held(&card->dapm_mutex); + /* find dapm widget path assoc with kcontrol */ dapm_kcontrol_for_each_path(path, kcontrol) { found = 1; @@ -2325,6 +2276,8 @@ static int snd_soc_dapm_set_pin(struct snd_soc_dapm_context *dapm, { struct snd_soc_dapm_widget *w = dapm_find_widget(dapm, pin, true); + dapm_assert_locked(dapm); + if (!w) { dev_err(dapm->dev, "ASoC: DAPM unknown pin %s\n", pin); return -EINVAL; @@ -2341,18 +2294,18 @@ static int snd_soc_dapm_set_pin(struct snd_soc_dapm_context *dapm, } /** - * snd_soc_dapm_sync - scan and power dapm paths + * snd_soc_dapm_sync_unlocked - scan and power dapm paths * @dapm: DAPM context * * Walks all dapm audio paths and powers widgets according to their * stream or path usage. * + * Requires external locking. + * * Returns 0 for success. */ -int snd_soc_dapm_sync(struct snd_soc_dapm_context *dapm) +int snd_soc_dapm_sync_unlocked(struct snd_soc_dapm_context *dapm) { - int ret; - /* * Suppress early reports (eg, jacks syncing their state) to avoid * silly DAPM runs during card startup. @@ -2360,8 +2313,25 @@ int snd_soc_dapm_sync(struct snd_soc_dapm_context *dapm) if (!dapm->card || !dapm->card->instantiated) return 0; + return dapm_power_widgets(dapm->card, SND_SOC_DAPM_STREAM_NOP); +} +EXPORT_SYMBOL_GPL(snd_soc_dapm_sync_unlocked); + +/** + * snd_soc_dapm_sync - scan and power dapm paths + * @dapm: DAPM context + * + * Walks all dapm audio paths and powers widgets according to their + * stream or path usage. + * + * Returns 0 for success. + */ +int snd_soc_dapm_sync(struct snd_soc_dapm_context *dapm) +{ + int ret; + mutex_lock_nested(&dapm->card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME); - ret = dapm_power_widgets(dapm->card, SND_SOC_DAPM_STREAM_NOP); + ret = snd_soc_dapm_sync_unlocked(dapm); mutex_unlock(&dapm->card->dapm_mutex); return ret; } @@ -2444,8 +2414,6 @@ static int snd_soc_dapm_add_path(struct snd_soc_dapm_context *dapm, path->connect = 1; return 0; case snd_soc_dapm_mux: - case snd_soc_dapm_virt_mux: - case snd_soc_dapm_value_mux: ret = dapm_connect_mux(dapm, wsource, wsink, path, control, &wsink->kcontrol_news[0]); if (ret != 0) @@ -2772,8 +2740,6 @@ int snd_soc_dapm_new_widgets(struct snd_soc_card *card) dapm_new_mixer(w); break; case snd_soc_dapm_mux: - case snd_soc_dapm_virt_mux: - case snd_soc_dapm_value_mux: dapm_new_mux(w); break; case snd_soc_dapm_pga: @@ -2935,213 +2901,75 @@ int snd_soc_dapm_get_enum_double(struct snd_kcontrol *kcontrol, { struct snd_soc_codec *codec = snd_soc_dapm_kcontrol_codec(kcontrol); struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; - unsigned int val; - - val = snd_soc_read(codec, e->reg); - ucontrol->value.enumerated.item[0] = (val >> e->shift_l) & e->mask; - if (e->shift_l != e->shift_r) - ucontrol->value.enumerated.item[1] = - (val >> e->shift_r) & e->mask; - - return 0; -} -EXPORT_SYMBOL_GPL(snd_soc_dapm_get_enum_double); - -/** - * snd_soc_dapm_put_enum_double - dapm enumerated double mixer set callback - * @kcontrol: mixer control - * @ucontrol: control element information - * - * Callback to set the value of a dapm enumerated double mixer control. - * - * Returns 0 for success. - */ -int snd_soc_dapm_put_enum_double(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_soc_codec *codec = snd_soc_dapm_kcontrol_codec(kcontrol); - struct snd_soc_card *card = codec->card; - struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; - unsigned int val, mux, change; - unsigned int mask; - struct snd_soc_dapm_update update; - int ret = 0; - - if (ucontrol->value.enumerated.item[0] > e->max - 1) - return -EINVAL; - mux = ucontrol->value.enumerated.item[0]; - val = mux << e->shift_l; - mask = e->mask << e->shift_l; - if (e->shift_l != e->shift_r) { - if (ucontrol->value.enumerated.item[1] > e->max - 1) - return -EINVAL; - val |= ucontrol->value.enumerated.item[1] << e->shift_r; - mask |= e->mask << e->shift_r; - } - - mutex_lock_nested(&card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME); - - change = snd_soc_test_bits(codec, e->reg, mask, val); - if (change) { - update.kcontrol = kcontrol; - update.reg = e->reg; - update.mask = mask; - update.val = val; - card->update = &update; - - ret = soc_dapm_mux_update_power(card, kcontrol, mux, e); - - card->update = NULL; - } - - mutex_unlock(&card->dapm_mutex); - - if (ret > 0) - soc_dpcm_runtime_update(card); - - return change; -} -EXPORT_SYMBOL_GPL(snd_soc_dapm_put_enum_double); - -/** - * snd_soc_dapm_get_enum_virt - Get virtual DAPM mux - * @kcontrol: mixer control - * @ucontrol: control element information - * - * Returns 0 for success. - */ -int snd_soc_dapm_get_enum_virt(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - ucontrol->value.enumerated.item[0] = dapm_kcontrol_get_value(kcontrol); - return 0; -} -EXPORT_SYMBOL_GPL(snd_soc_dapm_get_enum_virt); - -/** - * snd_soc_dapm_put_enum_virt - Set virtual DAPM mux - * @kcontrol: mixer control - * @ucontrol: control element information - * - * Returns 0 for success. - */ -int snd_soc_dapm_put_enum_virt(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_soc_codec *codec = snd_soc_dapm_kcontrol_codec(kcontrol); - struct snd_soc_card *card = codec->card; - unsigned int value; - struct soc_enum *e = - (struct soc_enum *)kcontrol->private_value; - int change; - int ret = 0; - - if (ucontrol->value.enumerated.item[0] >= e->max) - return -EINVAL; + unsigned int reg_val, val; - mutex_lock_nested(&card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME); - - value = ucontrol->value.enumerated.item[0]; - change = dapm_kcontrol_set_value(kcontrol, value); - if (change) - ret = soc_dapm_mux_update_power(card, kcontrol, value, e); - - mutex_unlock(&card->dapm_mutex); - - if (ret > 0) - soc_dpcm_runtime_update(card); - - return change; -} -EXPORT_SYMBOL_GPL(snd_soc_dapm_put_enum_virt); - -/** - * snd_soc_dapm_get_value_enum_double - dapm semi enumerated double mixer get - * callback - * @kcontrol: mixer control - * @ucontrol: control element information - * - * Callback to get the value of a dapm semi enumerated double mixer control. - * - * Semi enumerated mixer: the enumerated items are referred as values. Can be - * used for handling bitfield coded enumeration for example. - * - * Returns 0 for success. - */ -int snd_soc_dapm_get_value_enum_double(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_soc_codec *codec = snd_soc_dapm_kcontrol_codec(kcontrol); - struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; - unsigned int reg_val, val, mux; + if (e->reg != SND_SOC_NOPM) + reg_val = snd_soc_read(codec, e->reg); + else + reg_val = dapm_kcontrol_get_value(kcontrol); - reg_val = snd_soc_read(codec, e->reg); val = (reg_val >> e->shift_l) & e->mask; - for (mux = 0; mux < e->max; mux++) { - if (val == e->values[mux]) - break; - } - ucontrol->value.enumerated.item[0] = mux; + ucontrol->value.enumerated.item[0] = snd_soc_enum_val_to_item(e, val); if (e->shift_l != e->shift_r) { val = (reg_val >> e->shift_r) & e->mask; - for (mux = 0; mux < e->max; mux++) { - if (val == e->values[mux]) - break; - } - ucontrol->value.enumerated.item[1] = mux; + val = snd_soc_enum_val_to_item(e, val); + ucontrol->value.enumerated.item[1] = val; } return 0; } -EXPORT_SYMBOL_GPL(snd_soc_dapm_get_value_enum_double); +EXPORT_SYMBOL_GPL(snd_soc_dapm_get_enum_double); /** - * snd_soc_dapm_put_value_enum_double - dapm semi enumerated double mixer set - * callback + * snd_soc_dapm_put_enum_double - dapm enumerated double mixer set callback * @kcontrol: mixer control * @ucontrol: control element information * - * Callback to set the value of a dapm semi enumerated double mixer control. - * - * Semi enumerated mixer: the enumerated items are referred as values. Can be - * used for handling bitfield coded enumeration for example. + * Callback to set the value of a dapm enumerated double mixer control. * * Returns 0 for success. */ -int snd_soc_dapm_put_value_enum_double(struct snd_kcontrol *kcontrol, +int snd_soc_dapm_put_enum_double(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { struct snd_soc_codec *codec = snd_soc_dapm_kcontrol_codec(kcontrol); struct snd_soc_card *card = codec->card; struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; - unsigned int val, mux, change; + unsigned int *item = ucontrol->value.enumerated.item; + unsigned int val, change; unsigned int mask; struct snd_soc_dapm_update update; int ret = 0; - if (ucontrol->value.enumerated.item[0] > e->max - 1) + if (item[0] >= e->items) return -EINVAL; - mux = ucontrol->value.enumerated.item[0]; - val = e->values[ucontrol->value.enumerated.item[0]] << e->shift_l; + + val = snd_soc_enum_item_to_val(e, item[0]) << e->shift_l; mask = e->mask << e->shift_l; if (e->shift_l != e->shift_r) { - if (ucontrol->value.enumerated.item[1] > e->max - 1) + if (item[1] > e->items) return -EINVAL; - val |= e->values[ucontrol->value.enumerated.item[1]] << e->shift_r; + val |= snd_soc_enum_item_to_val(e, item[1]) << e->shift_l; mask |= e->mask << e->shift_r; } mutex_lock_nested(&card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME); - change = snd_soc_test_bits(codec, e->reg, mask, val); + if (e->reg != SND_SOC_NOPM) + change = snd_soc_test_bits(codec, e->reg, mask, val); + else + change = dapm_kcontrol_set_value(kcontrol, val); + if (change) { - update.kcontrol = kcontrol; - update.reg = e->reg; - update.mask = mask; - update.val = val; - card->update = &update; + if (e->reg != SND_SOC_NOPM) { + update.kcontrol = kcontrol; + update.reg = e->reg; + update.mask = mask; + update.val = val; + card->update = &update; + } - ret = soc_dapm_mux_update_power(card, kcontrol, mux, e); + ret = soc_dapm_mux_update_power(card, kcontrol, item[0], e); card->update = NULL; } @@ -3153,7 +2981,7 @@ int snd_soc_dapm_put_value_enum_double(struct snd_kcontrol *kcontrol, return change; } -EXPORT_SYMBOL_GPL(snd_soc_dapm_put_value_enum_double); +EXPORT_SYMBOL_GPL(snd_soc_dapm_put_enum_double); /** * snd_soc_dapm_info_pin_switch - Info for a pin switch @@ -3283,8 +3111,6 @@ snd_soc_dapm_new_control(struct snd_soc_dapm_context *dapm, w->power_check = dapm_generic_check_power; break; case snd_soc_dapm_mux: - case snd_soc_dapm_virt_mux: - case snd_soc_dapm_value_mux: w->power_check = dapm_generic_check_power; break; case snd_soc_dapm_dai_out: @@ -4098,7 +3924,7 @@ void snd_soc_dapm_free(struct snd_soc_dapm_context *dapm) } EXPORT_SYMBOL_GPL(snd_soc_dapm_free); -static void soc_dapm_shutdown_codec(struct snd_soc_dapm_context *dapm) +static void soc_dapm_shutdown_dapm(struct snd_soc_dapm_context *dapm) { struct snd_soc_card *card = dapm->card; struct snd_soc_dapm_widget *w; @@ -4138,14 +3964,21 @@ static void soc_dapm_shutdown_codec(struct snd_soc_dapm_context *dapm) */ void snd_soc_dapm_shutdown(struct snd_soc_card *card) { - struct snd_soc_codec *codec; + struct snd_soc_dapm_context *dapm; - list_for_each_entry(codec, &card->codec_dev_list, card_list) { - soc_dapm_shutdown_codec(&codec->dapm); - if (codec->dapm.bias_level == SND_SOC_BIAS_STANDBY) - snd_soc_dapm_set_bias_level(&codec->dapm, - SND_SOC_BIAS_OFF); + list_for_each_entry(dapm, &card->dapm_list, list) { + if (dapm != &card->dapm) { + soc_dapm_shutdown_dapm(dapm); + if (dapm->bias_level == SND_SOC_BIAS_STANDBY) + snd_soc_dapm_set_bias_level(dapm, + SND_SOC_BIAS_OFF); + } } + + soc_dapm_shutdown_dapm(&card->dapm); + if (card->dapm.bias_level == SND_SOC_BIAS_STANDBY) + snd_soc_dapm_set_bias_level(&card->dapm, + SND_SOC_BIAS_OFF); } /* Module information */ diff --git a/sound/soc/soc-io.c b/sound/soc/soc-io.c index aa886cca3ec..260efc8466f 100644 --- a/sound/soc/soc-io.c +++ b/sound/soc/soc-io.c @@ -23,21 +23,6 @@ static int hw_write(struct snd_soc_codec *codec, unsigned int reg, unsigned int value) { - int ret; - - if (!snd_soc_codec_volatile_register(codec, reg) && - reg < codec->driver->reg_cache_size && - !codec->cache_bypass) { - ret = snd_soc_cache_write(codec, reg, value); - if (ret < 0) - return -1; - } - - if (codec->cache_only) { - codec->cache_sync = 1; - return 0; - } - return regmap_write(codec->control_data, reg, value); } @@ -46,32 +31,18 @@ static unsigned int hw_read(struct snd_soc_codec *codec, unsigned int reg) int ret; unsigned int val; - if (reg >= codec->driver->reg_cache_size || - snd_soc_codec_volatile_register(codec, reg) || - codec->cache_bypass) { - if (codec->cache_only) - return -1; - - ret = regmap_read(codec->control_data, reg, &val); - if (ret == 0) - return val; - else - return -1; - } - - ret = snd_soc_cache_read(codec, reg, &val); - if (ret < 0) + ret = regmap_read(codec->control_data, reg, &val); + if (ret == 0) + return val; + else return -1; - return val; } /** * snd_soc_codec_set_cache_io: Set up standard I/O functions. * * @codec: CODEC to configure. - * @addr_bits: Number of bits of register address data. - * @data_bits: Number of bits of data per register. - * @control: Control bus used. + * @map: Register map to write to * * Register formats are frequently shared between many I2C and SPI * devices. In order to promote code reuse the ASoC core provides @@ -85,60 +56,36 @@ static unsigned int hw_read(struct snd_soc_codec *codec, unsigned int reg) * volatile registers. */ int snd_soc_codec_set_cache_io(struct snd_soc_codec *codec, - int addr_bits, int data_bits, - enum snd_soc_control_type control) + struct regmap *regmap) { - struct regmap_config config; int ret; - memset(&config, 0, sizeof(config)); - codec->write = hw_write; - codec->read = hw_read; - - config.reg_bits = addr_bits; - config.val_bits = data_bits; + /* Device has made its own regmap arrangements */ + if (!regmap) + codec->control_data = dev_get_regmap(codec->dev, NULL); + else + codec->control_data = regmap; - switch (control) { -#if IS_ENABLED(CONFIG_REGMAP_I2C) - case SND_SOC_I2C: - codec->control_data = regmap_init_i2c(to_i2c_client(codec->dev), - &config); - break; -#endif + if (IS_ERR(codec->control_data)) + return PTR_ERR(codec->control_data); -#if IS_ENABLED(CONFIG_REGMAP_SPI) - case SND_SOC_SPI: - codec->control_data = regmap_init_spi(to_spi_device(codec->dev), - &config); - break; -#endif - - case SND_SOC_REGMAP: - /* Device has made its own regmap arrangements */ - codec->using_regmap = true; - if (!codec->control_data) - codec->control_data = dev_get_regmap(codec->dev, NULL); + codec->write = hw_write; + codec->read = hw_read; - if (codec->control_data) { - ret = regmap_get_val_bytes(codec->control_data); - /* Errors are legitimate for non-integer byte - * multiples */ - if (ret > 0) - codec->val_bytes = ret; - } - break; + ret = regmap_get_val_bytes(codec->control_data); + /* Errors are legitimate for non-integer byte + * multiples */ + if (ret > 0) + codec->val_bytes = ret; - default: - return -EINVAL; - } + codec->using_regmap = true; - return PTR_ERR_OR_ZERO(codec->control_data); + return 0; } EXPORT_SYMBOL_GPL(snd_soc_codec_set_cache_io); #else int snd_soc_codec_set_cache_io(struct snd_soc_codec *codec, - int addr_bits, int data_bits, - enum snd_soc_control_type control) + struct regmap *regmap) { return -ENOTSUPP; } diff --git a/sound/soc/soc-jack.c b/sound/soc/soc-jack.c index 23d43dac91d..b903f822d1b 100644 --- a/sound/soc/soc-jack.c +++ b/sound/soc/soc-jack.c @@ -250,7 +250,7 @@ static void snd_soc_jack_gpio_detect(struct snd_soc_jack_gpio *gpio) report = 0; if (gpio->jack_status_check) - report = gpio->jack_status_check(); + report = gpio->jack_status_check(gpio->data); snd_soc_jack_report(jack, report, gpio->report); } @@ -342,7 +342,8 @@ int snd_soc_jack_add_gpios(struct snd_soc_jack *jack, int count, gpio_export(gpios[i].gpio, false); /* Update initial jack status */ - snd_soc_jack_gpio_detect(&gpios[i]); + schedule_delayed_work(&gpios[i].work, + msecs_to_jiffies(gpios[i].debounce_time)); } return 0; diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c index 28522bd03b8..2cedf09f6d9 100644 --- a/sound/soc/soc-pcm.c +++ b/sound/soc/soc-pcm.c @@ -35,6 +35,86 @@ #define DPCM_MAX_BE_USERS 8 /** + * snd_soc_runtime_activate() - Increment active count for PCM runtime components + * @rtd: ASoC PCM runtime that is activated + * @stream: Direction of the PCM stream + * + * Increments the active count for all the DAIs and components attached to a PCM + * runtime. Should typically be called when a stream is opened. + * + * Must be called with the rtd->pcm_mutex being held + */ +void snd_soc_runtime_activate(struct snd_soc_pcm_runtime *rtd, int stream) +{ + struct snd_soc_dai *cpu_dai = rtd->cpu_dai; + struct snd_soc_dai *codec_dai = rtd->codec_dai; + + lockdep_assert_held(&rtd->pcm_mutex); + + if (stream == SNDRV_PCM_STREAM_PLAYBACK) { + cpu_dai->playback_active++; + codec_dai->playback_active++; + } else { + cpu_dai->capture_active++; + codec_dai->capture_active++; + } + + cpu_dai->active++; + codec_dai->active++; + cpu_dai->component->active++; + codec_dai->component->active++; +} + +/** + * snd_soc_runtime_deactivate() - Decrement active count for PCM runtime components + * @rtd: ASoC PCM runtime that is deactivated + * @stream: Direction of the PCM stream + * + * Decrements the active count for all the DAIs and components attached to a PCM + * runtime. Should typically be called when a stream is closed. + * + * Must be called with the rtd->pcm_mutex being held + */ +void snd_soc_runtime_deactivate(struct snd_soc_pcm_runtime *rtd, int stream) +{ + struct snd_soc_dai *cpu_dai = rtd->cpu_dai; + struct snd_soc_dai *codec_dai = rtd->codec_dai; + + lockdep_assert_held(&rtd->pcm_mutex); + + if (stream == SNDRV_PCM_STREAM_PLAYBACK) { + cpu_dai->playback_active--; + codec_dai->playback_active--; + } else { + cpu_dai->capture_active--; + codec_dai->capture_active--; + } + + cpu_dai->active--; + codec_dai->active--; + cpu_dai->component->active--; + codec_dai->component->active--; +} + +/** + * snd_soc_runtime_ignore_pmdown_time() - Check whether to ignore the power down delay + * @rtd: The ASoC PCM runtime that should be checked. + * + * This function checks whether the power down delay should be ignored for a + * specific PCM runtime. Returns true if the delay is 0, if it the DAI link has + * been configured to ignore the delay, or if none of the components benefits + * from having the delay. + */ +bool snd_soc_runtime_ignore_pmdown_time(struct snd_soc_pcm_runtime *rtd) +{ + if (!rtd->pmdown_time || rtd->dai_link->ignore_pmdown_time) + return true; + + return rtd->cpu_dai->component->ignore_pmdown_time && + rtd->codec_dai->component->ignore_pmdown_time; +} + +/** * snd_soc_set_runtime_hwparams - set the runtime hardware parameters * @substream: the pcm substream * @hw: the hardware parameters @@ -378,16 +458,9 @@ static int soc_pcm_open(struct snd_pcm_substream *substream) runtime->hw.rate_max); dynamic: - if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { - cpu_dai->playback_active++; - codec_dai->playback_active++; - } else { - cpu_dai->capture_active++; - codec_dai->capture_active++; - } - cpu_dai->active++; - codec_dai->active++; - rtd->codec->active++; + + snd_soc_runtime_activate(rtd, substream->stream); + mutex_unlock(&rtd->pcm_mutex); return 0; @@ -459,21 +532,10 @@ static int soc_pcm_close(struct snd_pcm_substream *substream) struct snd_soc_platform *platform = rtd->platform; struct snd_soc_dai *cpu_dai = rtd->cpu_dai; struct snd_soc_dai *codec_dai = rtd->codec_dai; - struct snd_soc_codec *codec = rtd->codec; mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass); - if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { - cpu_dai->playback_active--; - codec_dai->playback_active--; - } else { - cpu_dai->capture_active--; - codec_dai->capture_active--; - } - - cpu_dai->active--; - codec_dai->active--; - codec->active--; + snd_soc_runtime_deactivate(rtd, substream->stream); /* clear the corresponding DAIs rate when inactive */ if (!cpu_dai->active) @@ -496,8 +558,7 @@ static int soc_pcm_close(struct snd_pcm_substream *substream) cpu_dai->runtime = NULL; if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { - if (!rtd->pmdown_time || codec->ignore_pmdown_time || - rtd->dai_link->ignore_pmdown_time) { + if (snd_soc_runtime_ignore_pmdown_time(rtd)) { /* powered down playback stream now */ snd_soc_dapm_stream_event(rtd, SNDRV_PCM_STREAM_PLAYBACK, @@ -1989,7 +2050,6 @@ int soc_dpcm_runtime_update(struct snd_soc_card *card) paths = dpcm_path_get(fe, SNDRV_PCM_STREAM_PLAYBACK, &list); if (paths < 0) { - dpcm_path_put(&list); dev_warn(fe->dev, "ASoC: %s no valid %s path\n", fe->dai_link->name, "playback"); mutex_unlock(&card->mutex); @@ -2019,7 +2079,6 @@ capture: paths = dpcm_path_get(fe, SNDRV_PCM_STREAM_CAPTURE, &list); if (paths < 0) { - dpcm_path_put(&list); dev_warn(fe->dev, "ASoC: %s no valid %s path\n", fe->dai_link->name, "capture"); mutex_unlock(&card->mutex); @@ -2084,7 +2143,6 @@ static int dpcm_fe_dai_open(struct snd_pcm_substream *fe_substream) fe->dpcm[stream].runtime = fe_substream->runtime; if (dpcm_path_get(fe, stream, &list) <= 0) { - dpcm_path_put(&list); dev_dbg(fe->dev, "ASoC: %s no valid %s route\n", fe->dai_link->name, stream ? "capture" : "playback"); } diff --git a/sound/soc/spear/spdif_out.c b/sound/soc/spear/spdif_out.c index fe99f461aff..19cca043e6e 100644 --- a/sound/soc/spear/spdif_out.c +++ b/sound/soc/spear/spdif_out.c @@ -213,10 +213,7 @@ static int spdif_digital_mute(struct snd_soc_dai *dai, int mute) static int spdif_mute_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { - struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); - struct snd_soc_card *card = codec->card; - struct snd_soc_pcm_runtime *rtd = card->rtd; - struct snd_soc_dai *cpu_dai = rtd->cpu_dai; + struct snd_soc_dai *cpu_dai = snd_kcontrol_chip(kcontrol); struct spdif_out_dev *host = snd_soc_dai_get_drvdata(cpu_dai); ucontrol->value.integer.value[0] = host->saved_params.mute; @@ -226,10 +223,7 @@ static int spdif_mute_get(struct snd_kcontrol *kcontrol, static int spdif_mute_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { - struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); - struct snd_soc_card *card = codec->card; - struct snd_soc_pcm_runtime *rtd = card->rtd; - struct snd_soc_dai *cpu_dai = rtd->cpu_dai; + struct snd_soc_dai *cpu_dai = snd_kcontrol_chip(kcontrol); struct spdif_out_dev *host = snd_soc_dai_get_drvdata(cpu_dai); if (host->saved_params.mute == ucontrol->value.integer.value[0]) diff --git a/sound/soc/tegra/Kconfig b/sound/soc/tegra/Kconfig index 9f9c1856f82..31198cf7f88 100644 --- a/sound/soc/tegra/Kconfig +++ b/sound/soc/tegra/Kconfig @@ -105,7 +105,7 @@ config SND_SOC_TEGRA_TRIMSLICE tristate "SoC Audio support for TrimSlice board" depends on SND_SOC_TEGRA && I2C select SND_SOC_TEGRA20_I2S if ARCH_TEGRA_2x_SOC - select SND_SOC_TLV320AIC23 + select SND_SOC_TLV320AIC23_I2C help Say Y or M here if you want to add support for SoC audio on the TrimSlice platform. diff --git a/sound/soc/tegra/tegra20_ac97.c b/sound/soc/tegra/tegra20_ac97.c index cf5e1cfe818..3b0fa12dbff 100644 --- a/sound/soc/tegra/tegra20_ac97.c +++ b/sound/soc/tegra/tegra20_ac97.c @@ -37,7 +37,6 @@ #include <sound/soc.h> #include <sound/dmaengine_pcm.h> -#include "tegra_asoc_utils.h" #include "tegra20_ac97.h" #define DRV_NAME "tegra20-ac97" @@ -306,7 +305,7 @@ static const struct regmap_config tegra20_ac97_regmap_config = { .readable_reg = tegra20_ac97_wr_rd_reg, .volatile_reg = tegra20_ac97_volatile_reg, .precious_reg = tegra20_ac97_precious_reg, - .cache_type = REGCACHE_RBTREE, + .cache_type = REGCACHE_FLAT, }; static int tegra20_ac97_platform_probe(struct platform_device *pdev) @@ -376,18 +375,10 @@ static int tegra20_ac97_platform_probe(struct platform_device *pdev) ac97->playback_dma_data.addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; ac97->playback_dma_data.maxburst = 4; - ret = tegra_asoc_utils_init(&ac97->util_data, &pdev->dev); - if (ret) - goto err_clk_put; - - ret = tegra_asoc_utils_set_ac97_rate(&ac97->util_data); - if (ret) - goto err_asoc_utils_fini; - ret = clk_prepare_enable(ac97->clk_ac97); if (ret) { dev_err(&pdev->dev, "clk_enable failed: %d\n", ret); - goto err_asoc_utils_fini; + goto err; } ret = snd_soc_set_ac97_ops(&tegra20_ac97_ops); @@ -419,8 +410,6 @@ err_unregister_component: snd_soc_unregister_component(&pdev->dev); err_clk_disable_unprepare: clk_disable_unprepare(ac97->clk_ac97); -err_asoc_utils_fini: - tegra_asoc_utils_fini(&ac97->util_data); err_clk_put: err: snd_soc_set_ac97_ops(NULL); @@ -434,8 +423,6 @@ static int tegra20_ac97_platform_remove(struct platform_device *pdev) tegra_pcm_platform_unregister(&pdev->dev); snd_soc_unregister_component(&pdev->dev); - tegra_asoc_utils_fini(&ac97->util_data); - clk_disable_unprepare(ac97->clk_ac97); snd_soc_set_ac97_ops(NULL); diff --git a/sound/soc/tegra/tegra20_ac97.h b/sound/soc/tegra/tegra20_ac97.h index 4acb3aaba29..0a39d823edc 100644 --- a/sound/soc/tegra/tegra20_ac97.h +++ b/sound/soc/tegra/tegra20_ac97.h @@ -90,6 +90,5 @@ struct tegra20_ac97 { struct regmap *regmap; int reset_gpio; int sync_gpio; - struct tegra_asoc_utils_data util_data; }; #endif /* __TEGRA20_AC97_H__ */ diff --git a/sound/soc/tegra/tegra20_das.c b/sound/soc/tegra/tegra20_das.c index e72392927bd..a634f13b3ff 100644 --- a/sound/soc/tegra/tegra20_das.c +++ b/sound/soc/tegra/tegra20_das.c @@ -128,7 +128,7 @@ static const struct regmap_config tegra20_das_regmap_config = { .max_register = LAST_REG(DAC_INPUT_DATA_CLK_SEL), .writeable_reg = tegra20_das_wr_rd_reg, .readable_reg = tegra20_das_wr_rd_reg, - .cache_type = REGCACHE_RBTREE, + .cache_type = REGCACHE_FLAT, }; static int tegra20_das_probe(struct platform_device *pdev) diff --git a/sound/soc/tegra/tegra20_i2s.c b/sound/soc/tegra/tegra20_i2s.c index 42c1f6bfaf2..79a9932ffe6 100644 --- a/sound/soc/tegra/tegra20_i2s.c +++ b/sound/soc/tegra/tegra20_i2s.c @@ -333,7 +333,7 @@ static const struct regmap_config tegra20_i2s_regmap_config = { .readable_reg = tegra20_i2s_wr_rd_reg, .volatile_reg = tegra20_i2s_volatile_reg, .precious_reg = tegra20_i2s_precious_reg, - .cache_type = REGCACHE_RBTREE, + .cache_type = REGCACHE_FLAT, }; static int tegra20_i2s_platform_probe(struct platform_device *pdev) diff --git a/sound/soc/tegra/tegra20_spdif.c b/sound/soc/tegra/tegra20_spdif.c index 8c7c1028e57..a0ce92400fa 100644 --- a/sound/soc/tegra/tegra20_spdif.c +++ b/sound/soc/tegra/tegra20_spdif.c @@ -259,7 +259,7 @@ static const struct regmap_config tegra20_spdif_regmap_config = { .readable_reg = tegra20_spdif_wr_rd_reg, .volatile_reg = tegra20_spdif_volatile_reg, .precious_reg = tegra20_spdif_precious_reg, - .cache_type = REGCACHE_RBTREE, + .cache_type = REGCACHE_FLAT, }; static int tegra20_spdif_platform_probe(struct platform_device *pdev) diff --git a/sound/soc/tegra/tegra30_ahub.c b/sound/soc/tegra/tegra30_ahub.c index d6f4c9940e0..0db68f49f4d 100644 --- a/sound/soc/tegra/tegra30_ahub.c +++ b/sound/soc/tegra/tegra30_ahub.c @@ -471,7 +471,7 @@ static const struct regmap_config tegra30_ahub_apbif_regmap_config = { .readable_reg = tegra30_ahub_apbif_wr_rd_reg, .volatile_reg = tegra30_ahub_apbif_volatile_reg, .precious_reg = tegra30_ahub_apbif_precious_reg, - .cache_type = REGCACHE_RBTREE, + .cache_type = REGCACHE_FLAT, }; static bool tegra30_ahub_ahub_wr_rd_reg(struct device *dev, unsigned int reg) @@ -490,7 +490,7 @@ static const struct regmap_config tegra30_ahub_ahub_regmap_config = { .max_register = LAST_REG(AUDIO_RX), .writeable_reg = tegra30_ahub_ahub_wr_rd_reg, .readable_reg = tegra30_ahub_ahub_wr_rd_reg, - .cache_type = REGCACHE_RBTREE, + .cache_type = REGCACHE_FLAT, }; static struct tegra30_ahub_soc_data soc_data_tegra30 = { diff --git a/sound/soc/tegra/tegra30_i2s.c b/sound/soc/tegra/tegra30_i2s.c index 49ad9366add..f146c41dd3e 100644 --- a/sound/soc/tegra/tegra30_i2s.c +++ b/sound/soc/tegra/tegra30_i2s.c @@ -357,7 +357,7 @@ static const struct regmap_config tegra30_i2s_regmap_config = { .writeable_reg = tegra30_i2s_wr_rd_reg, .readable_reg = tegra30_i2s_wr_rd_reg, .volatile_reg = tegra30_i2s_volatile_reg, - .cache_type = REGCACHE_RBTREE, + .cache_type = REGCACHE_FLAT, }; static const struct tegra30_i2s_soc_data tegra30_i2s_config = { diff --git a/sound/soc/tegra/tegra_wm9712.c b/sound/soc/tegra/tegra_wm9712.c index 45b57892b6a..25a7f8211ec 100644 --- a/sound/soc/tegra/tegra_wm9712.c +++ b/sound/soc/tegra/tegra_wm9712.c @@ -29,10 +29,13 @@ #include <sound/pcm_params.h> #include <sound/soc.h> +#include "tegra_asoc_utils.h" + #define DRV_NAME "tegra-snd-wm9712" struct tegra_wm9712 { struct platform_device *codec; + struct tegra_asoc_utils_data util_data; }; static const struct snd_soc_dapm_widget tegra_wm9712_dapm_widgets[] = { @@ -118,15 +121,25 @@ static int tegra_wm9712_driver_probe(struct platform_device *pdev) tegra_wm9712_dai.platform_of_node = tegra_wm9712_dai.cpu_of_node; + ret = tegra_asoc_utils_init(&machine->util_data, &pdev->dev); + if (ret) + goto codec_unregister; + + ret = tegra_asoc_utils_set_ac97_rate(&machine->util_data); + if (ret) + goto asoc_utils_fini; + ret = snd_soc_register_card(card); if (ret) { dev_err(&pdev->dev, "snd_soc_register_card failed (%d)\n", ret); - goto codec_unregister; + goto asoc_utils_fini; } return 0; +asoc_utils_fini: + tegra_asoc_utils_fini(&machine->util_data); codec_unregister: platform_device_del(machine->codec); codec_put: @@ -141,6 +154,8 @@ static int tegra_wm9712_driver_remove(struct platform_device *pdev) snd_soc_unregister_card(card); + tegra_asoc_utils_fini(&machine->util_data); + platform_device_unregister(machine->codec); return 0; diff --git a/sound/sparc/amd7930.c b/sound/sparc/amd7930.c index 174d21fb56e..4a85e143347 100644 --- a/sound/sparc/amd7930.c +++ b/sound/sparc/amd7930.c @@ -1019,8 +1019,8 @@ static int amd7930_sbus_probe(struct platform_device *op) return -ENOENT; } - err = snd_card_create(index[dev_num], id[dev_num], THIS_MODULE, 0, - &card); + err = snd_card_new(&op->dev, index[dev_num], id[dev_num], + THIS_MODULE, 0, &card); if (err < 0) return err; diff --git a/sound/sparc/cs4231.c b/sound/sparc/cs4231.c index dbb1b625eb2..4e91bcaa366 100644 --- a/sound/sparc/cs4231.c +++ b/sound/sparc/cs4231.c @@ -1565,7 +1565,8 @@ static int snd_cs4231_mixer(struct snd_card *card) static int dev; -static int cs4231_attach_begin(struct snd_card **rcard) +static int cs4231_attach_begin(struct platform_device *op, + struct snd_card **rcard) { struct snd_card *card; struct snd_cs4231 *chip; @@ -1581,8 +1582,8 @@ static int cs4231_attach_begin(struct snd_card **rcard) return -ENOENT; } - err = snd_card_create(index[dev], id[dev], THIS_MODULE, - sizeof(struct snd_cs4231), &card); + err = snd_card_new(&op->dev, index[dev], id[dev], THIS_MODULE, + sizeof(struct snd_cs4231), &card); if (err < 0) return err; @@ -1869,7 +1870,7 @@ static int cs4231_sbus_probe(struct platform_device *op) struct snd_card *card; int err; - err = cs4231_attach_begin(&card); + err = cs4231_attach_begin(op, &card); if (err) return err; @@ -2060,7 +2061,7 @@ static int cs4231_ebus_probe(struct platform_device *op) struct snd_card *card; int err; - err = cs4231_attach_begin(&card); + err = cs4231_attach_begin(op, &card); if (err) return err; diff --git a/sound/sparc/dbri.c b/sound/sparc/dbri.c index eee7afcae37..be1b1aa96b7 100644 --- a/sound/sparc/dbri.c +++ b/sound/sparc/dbri.c @@ -2615,8 +2615,8 @@ static int dbri_probe(struct platform_device *op) return -ENODEV; } - err = snd_card_create(index[dev], id[dev], THIS_MODULE, - sizeof(struct snd_dbri), &card); + err = snd_card_new(&op->dev, index[dev], id[dev], THIS_MODULE, + sizeof(struct snd_dbri), &card); if (err < 0) return err; diff --git a/sound/spi/at73c213.c b/sound/spi/at73c213.c index 25c38afaee4..39522367897 100644 --- a/sound/spi/at73c213.c +++ b/sound/spi/at73c213.c @@ -927,8 +927,6 @@ static int snd_at73c213_dev_init(struct snd_card *card, if (retval) goto out_snd_dev; - snd_card_set_dev(card, &spi->dev); - goto out; out_snd_dev: @@ -966,8 +964,8 @@ static int snd_at73c213_probe(struct spi_device *spi) /* Allocate "card" using some unused identifiers. */ snprintf(id, sizeof id, "at73c213_%d", board->ssc_id); - retval = snd_card_create(-1, id, THIS_MODULE, - sizeof(struct snd_at73c213), &card); + retval = snd_card_new(&spi->dev, -1, id, THIS_MODULE, + sizeof(struct snd_at73c213), &card); if (retval < 0) goto out; diff --git a/sound/usb/6fire/chip.c b/sound/usb/6fire/chip.c index 66edc4a7917..dcddfc354ba 100644 --- a/sound/usb/6fire/chip.c +++ b/sound/usb/6fire/chip.c @@ -106,7 +106,7 @@ static int usb6fire_chip_probe(struct usb_interface *intf, } if (regidx < 0) { mutex_unlock(®ister_mutex); - snd_printk(KERN_ERR PREFIX "too many cards registered.\n"); + dev_err(&intf->dev, "too many cards registered.\n"); return -ENODEV; } devices[regidx] = device; @@ -121,20 +121,19 @@ static int usb6fire_chip_probe(struct usb_interface *intf, /* if we are here, card can be registered in alsa. */ if (usb_set_interface(device, 0, 0) != 0) { - snd_printk(KERN_ERR PREFIX "can't set first interface.\n"); + dev_err(&intf->dev, "can't set first interface.\n"); return -EIO; } - ret = snd_card_create(index[regidx], id[regidx], THIS_MODULE, - sizeof(struct sfire_chip), &card); + ret = snd_card_new(&intf->dev, index[regidx], id[regidx], + THIS_MODULE, sizeof(struct sfire_chip), &card); if (ret < 0) { - snd_printk(KERN_ERR PREFIX "cannot create alsa card.\n"); + dev_err(&intf->dev, "cannot create alsa card.\n"); return ret; } strcpy(card->driver, "6FireUSB"); strcpy(card->shortname, "TerraTec DMX6FireUSB"); sprintf(card->longname, "%s at %d:%d", card->shortname, device->bus->busnum, device->devnum); - snd_card_set_dev(card, &intf->dev); chip = card->private_data; chips[regidx] = chip; @@ -169,7 +168,7 @@ static int usb6fire_chip_probe(struct usb_interface *intf, ret = snd_card_register(card); if (ret < 0) { - snd_printk(KERN_ERR PREFIX "cannot register card."); + dev_err(&intf->dev, "cannot register card."); usb6fire_chip_destroy(chip); return ret; } diff --git a/sound/usb/6fire/comm.c b/sound/usb/6fire/comm.c index 23452ee617e..161215d78d9 100644 --- a/sound/usb/6fire/comm.c +++ b/sound/usb/6fire/comm.c @@ -51,7 +51,7 @@ static void usb6fire_comm_receiver_handler(struct urb *urb) urb->status = 0; urb->actual_length = 0; if (usb_submit_urb(urb, GFP_ATOMIC) < 0) - snd_printk(KERN_WARNING PREFIX + dev_warn(&urb->dev->dev, "comm data receiver aborted.\n"); } } @@ -179,7 +179,7 @@ int usb6fire_comm_init(struct sfire_chip *chip) if (ret < 0) { kfree(rt->receiver_buffer); kfree(rt); - snd_printk(KERN_ERR PREFIX "cannot create comm data receiver."); + dev_err(&chip->dev->dev, "cannot create comm data receiver."); return ret; } chip->comm = rt; diff --git a/sound/usb/6fire/control.c b/sound/usb/6fire/control.c index f6434c24572..184e3987ac2 100644 --- a/sound/usb/6fire/control.c +++ b/sound/usb/6fire/control.c @@ -194,7 +194,8 @@ static int usb6fire_control_output_vol_put(struct snd_kcontrol *kcontrol, int changed = 0; if (ch > 4) { - snd_printk(KERN_ERR PREFIX "Invalid channel in volume control."); + dev_err(&rt->chip->dev->dev, + "Invalid channel in volume control."); return -EINVAL; } @@ -222,7 +223,8 @@ static int usb6fire_control_output_vol_get(struct snd_kcontrol *kcontrol, unsigned int ch = kcontrol->private_value; if (ch > 4) { - snd_printk(KERN_ERR PREFIX "Invalid channel in volume control."); + dev_err(&rt->chip->dev->dev, + "Invalid channel in volume control."); return -EINVAL; } @@ -240,7 +242,8 @@ static int usb6fire_control_output_mute_put(struct snd_kcontrol *kcontrol, u8 value = 0; if (ch > 4) { - snd_printk(KERN_ERR PREFIX "Invalid channel in volume control."); + dev_err(&rt->chip->dev->dev, + "Invalid channel in volume control."); return -EINVAL; } @@ -265,7 +268,8 @@ static int usb6fire_control_output_mute_get(struct snd_kcontrol *kcontrol, u8 value = rt->output_mute >> ch; if (ch > 4) { - snd_printk(KERN_ERR PREFIX "Invalid channel in volume control."); + dev_err(&rt->chip->dev->dev, + "Invalid channel in volume control."); return -EINVAL; } @@ -594,14 +598,14 @@ int usb6fire_control_init(struct sfire_chip *chip) ret = usb6fire_control_add_virtual(rt, chip->card, "Master Playback Volume", vol_elements); if (ret) { - snd_printk(KERN_ERR PREFIX "cannot add control.\n"); + dev_err(&chip->dev->dev, "cannot add control.\n"); kfree(rt); return ret; } ret = usb6fire_control_add_virtual(rt, chip->card, "Master Playback Switch", mute_elements); if (ret) { - snd_printk(KERN_ERR PREFIX "cannot add control.\n"); + dev_err(&chip->dev->dev, "cannot add control.\n"); kfree(rt); return ret; } @@ -611,7 +615,7 @@ int usb6fire_control_init(struct sfire_chip *chip) ret = snd_ctl_add(chip->card, snd_ctl_new1(&elements[i], rt)); if (ret < 0) { kfree(rt); - snd_printk(KERN_ERR PREFIX "cannot add control.\n"); + dev_err(&chip->dev->dev, "cannot add control.\n"); return ret; } i++; diff --git a/sound/usb/6fire/firmware.c b/sound/usb/6fire/firmware.c index 780bf3f62d2..3b02e54b8f6 100644 --- a/sound/usb/6fire/firmware.c +++ b/sound/usb/6fire/firmware.c @@ -219,16 +219,16 @@ static int usb6fire_fw_ezusb_upload( ret = request_firmware(&fw, fwname, &device->dev); if (ret < 0) { kfree(rec); - snd_printk(KERN_ERR PREFIX "error requesting ezusb " - "firmware %s.\n", fwname); + dev_err(&intf->dev, + "error requesting ezusb firmware %s.\n", fwname); return ret; } ret = usb6fire_fw_ihex_init(fw, rec); if (ret < 0) { kfree(rec); release_firmware(fw); - snd_printk(KERN_ERR PREFIX "error validating ezusb " - "firmware %s.\n", fwname); + dev_err(&intf->dev, + "error validating ezusb firmware %s.\n", fwname); return ret; } /* upload firmware image */ @@ -237,8 +237,9 @@ static int usb6fire_fw_ezusb_upload( if (ret < 0) { kfree(rec); release_firmware(fw); - snd_printk(KERN_ERR PREFIX "unable to upload ezusb " - "firmware %s: begin message.\n", fwname); + dev_err(&intf->dev, + "unable to upload ezusb firmware %s: begin message.\n", + fwname); return ret; } @@ -248,8 +249,9 @@ static int usb6fire_fw_ezusb_upload( if (ret < 0) { kfree(rec); release_firmware(fw); - snd_printk(KERN_ERR PREFIX "unable to upload ezusb " - "firmware %s: data urb.\n", fwname); + dev_err(&intf->dev, + "unable to upload ezusb firmware %s: data urb.\n", + fwname); return ret; } } @@ -260,8 +262,9 @@ static int usb6fire_fw_ezusb_upload( ret = usb6fire_fw_ezusb_write(device, 0xa0, postaddr, postdata, postlen); if (ret < 0) { - snd_printk(KERN_ERR PREFIX "unable to upload ezusb " - "firmware %s: post urb.\n", fwname); + dev_err(&intf->dev, + "unable to upload ezusb firmware %s: post urb.\n", + fwname); return ret; } } @@ -269,8 +272,9 @@ static int usb6fire_fw_ezusb_upload( data = 0x00; /* resume ezusb cpu */ ret = usb6fire_fw_ezusb_write(device, 0xa0, 0xe600, &data, 1); if (ret < 0) { - snd_printk(KERN_ERR PREFIX "unable to upload ezusb " - "firmware %s: end message.\n", fwname); + dev_err(&intf->dev, + "unable to upload ezusb firmware %s: end message.\n", + fwname); return ret; } return 0; @@ -292,7 +296,7 @@ static int usb6fire_fw_fpga_upload( ret = request_firmware(&fw, fwname, &device->dev); if (ret < 0) { - snd_printk(KERN_ERR PREFIX "unable to get fpga firmware %s.\n", + dev_err(&intf->dev, "unable to get fpga firmware %s.\n", fwname); kfree(buffer); return -EIO; @@ -305,8 +309,8 @@ static int usb6fire_fw_fpga_upload( if (ret < 0) { kfree(buffer); release_firmware(fw); - snd_printk(KERN_ERR PREFIX "unable to upload fpga firmware: " - "begin urb.\n"); + dev_err(&intf->dev, + "unable to upload fpga firmware: begin urb.\n"); return ret; } @@ -318,8 +322,8 @@ static int usb6fire_fw_fpga_upload( if (ret < 0) { release_firmware(fw); kfree(buffer); - snd_printk(KERN_ERR PREFIX "unable to upload fpga " - "firmware: fw urb.\n"); + dev_err(&intf->dev, + "unable to upload fpga firmware: fw urb.\n"); return ret; } } @@ -328,8 +332,8 @@ static int usb6fire_fw_fpga_upload( ret = usb6fire_fw_ezusb_write(device, 9, 0, NULL, 0); if (ret < 0) { - snd_printk(KERN_ERR PREFIX "unable to upload fpga firmware: " - "end urb.\n"); + dev_err(&intf->dev, + "unable to upload fpga firmware: end urb.\n"); return ret; } return 0; @@ -338,7 +342,7 @@ static int usb6fire_fw_fpga_upload( /* check, if the firmware version the devices has currently loaded * is known by this driver. 'version' needs to have 4 bytes version * info data. */ -static int usb6fire_fw_check(u8 *version) +static int usb6fire_fw_check(struct usb_interface *intf, const u8 *version) { int i; @@ -346,7 +350,7 @@ static int usb6fire_fw_check(u8 *version) if (!memcmp(version, known_fw_versions + i, 2)) return 0; - snd_printk(KERN_ERR PREFIX "invalid fimware version in device: %4ph. " + dev_err(&intf->dev, "invalid fimware version in device: %4ph. " "please reconnect to power. if this failure " "still happens, check your firmware installation.", version); @@ -364,16 +368,16 @@ int usb6fire_fw_init(struct usb_interface *intf) ret = usb6fire_fw_ezusb_read(device, 1, 0, buffer, 8); if (ret < 0) { - snd_printk(KERN_ERR PREFIX "unable to receive device " - "firmware state.\n"); + dev_err(&intf->dev, + "unable to receive device firmware state.\n"); return ret; } if (buffer[0] != 0xeb || buffer[1] != 0xaa || buffer[2] != 0x55) { - snd_printk(KERN_ERR PREFIX "unknown device firmware state " - "received from device: "); + dev_err(&intf->dev, + "unknown device firmware state received from device:"); for (i = 0; i < 8; i++) - snd_printk("%02x ", buffer[i]); - snd_printk("\n"); + printk(KERN_CONT "%02x ", buffer[i]); + printk(KERN_CONT "\n"); return -EIO; } /* do we need fpga loader ezusb firmware? */ @@ -386,7 +390,7 @@ int usb6fire_fw_init(struct usb_interface *intf) } /* do we need fpga firmware and application ezusb firmware? */ else if (buffer[3] == 0x02) { - ret = usb6fire_fw_check(buffer + 4); + ret = usb6fire_fw_check(intf, buffer + 4); if (ret < 0) return ret; ret = usb6fire_fw_fpga_upload(intf, "6fire/dmx6firecf.bin"); @@ -402,14 +406,14 @@ int usb6fire_fw_init(struct usb_interface *intf) } /* all fw loaded? */ else if (buffer[3] == 0x03) - return usb6fire_fw_check(buffer + 4); + return usb6fire_fw_check(intf, buffer + 4); /* unknown data? */ else { - snd_printk(KERN_ERR PREFIX "unknown device firmware state " - "received from device: "); + dev_err(&intf->dev, + "unknown device firmware state received from device: "); for (i = 0; i < 8; i++) - snd_printk("%02x ", buffer[i]); - snd_printk("\n"); + printk(KERN_CONT "%02x ", buffer[i]); + printk(KERN_CONT "\n"); return -EIO; } return 0; diff --git a/sound/usb/6fire/midi.c b/sound/usb/6fire/midi.c index f3dd7266c39..3d410969553 100644 --- a/sound/usb/6fire/midi.c +++ b/sound/usb/6fire/midi.c @@ -41,8 +41,9 @@ static void usb6fire_midi_out_handler(struct urb *urb) ret = usb_submit_urb(urb, GFP_ATOMIC); if (ret < 0) - snd_printk(KERN_ERR PREFIX "midi out urb " - "submit failed: %d\n", ret); + dev_err(&urb->dev->dev, + "midi out urb submit failed: %d\n", + ret); } else /* no more data to transmit */ rt->out = NULL; } @@ -94,8 +95,9 @@ static void usb6fire_midi_out_trigger( ret = usb_submit_urb(urb, GFP_ATOMIC); if (ret < 0) - snd_printk(KERN_ERR PREFIX "midi out urb " - "submit failed: %d\n", ret); + dev_err(&urb->dev->dev, + "midi out urb submit failed: %d\n", + ret); else rt->out = alsa_sub; } @@ -181,7 +183,7 @@ int usb6fire_midi_init(struct sfire_chip *chip) if (ret < 0) { kfree(rt->out_buffer); kfree(rt); - snd_printk(KERN_ERR PREFIX "unable to create midi.\n"); + dev_err(&chip->dev->dev, "unable to create midi.\n"); return ret; } rt->instance->private_data = rt; diff --git a/sound/usb/6fire/pcm.c b/sound/usb/6fire/pcm.c index b5eb97fdc84..ba40489b2de 100644 --- a/sound/usb/6fire/pcm.c +++ b/sound/usb/6fire/pcm.c @@ -79,32 +79,35 @@ static int usb6fire_pcm_set_rate(struct pcm_runtime *rt) ctrl_rt->usb_streaming = false; ret = ctrl_rt->update_streaming(ctrl_rt); if (ret < 0) { - snd_printk(KERN_ERR PREFIX "error stopping streaming while " - "setting samplerate %d.\n", rates[rt->rate]); + dev_err(&rt->chip->dev->dev, + "error stopping streaming while setting samplerate %d.\n", + rates[rt->rate]); return ret; } ret = ctrl_rt->set_rate(ctrl_rt, rt->rate); if (ret < 0) { - snd_printk(KERN_ERR PREFIX "error setting samplerate %d.\n", - rates[rt->rate]); + dev_err(&rt->chip->dev->dev, + "error setting samplerate %d.\n", + rates[rt->rate]); return ret; } ret = ctrl_rt->set_channels(ctrl_rt, OUT_N_CHANNELS, IN_N_CHANNELS, false, false); if (ret < 0) { - snd_printk(KERN_ERR PREFIX "error initializing channels " - "while setting samplerate %d.\n", - rates[rt->rate]); + dev_err(&rt->chip->dev->dev, + "error initializing channels while setting samplerate %d.\n", + rates[rt->rate]); return ret; } ctrl_rt->usb_streaming = true; ret = ctrl_rt->update_streaming(ctrl_rt); if (ret < 0) { - snd_printk(KERN_ERR PREFIX "error starting streaming while " - "setting samplerate %d.\n", rates[rt->rate]); + dev_err(&rt->chip->dev->dev, + "error starting streaming while setting samplerate %d.\n", + rates[rt->rate]); return ret; } @@ -124,7 +127,7 @@ static struct pcm_substream *usb6fire_pcm_get_substream( return &rt->playback; else if (alsa_sub->stream == SNDRV_PCM_STREAM_CAPTURE) return &rt->capture; - snd_printk(KERN_ERR PREFIX "error getting pcm substream slot.\n"); + dev_err(&rt->chip->dev->dev, "error getting pcm substream slot.\n"); return NULL; } @@ -257,7 +260,7 @@ static void usb6fire_pcm_playback(struct pcm_substream *sub, else if (alsa_rt->format == SNDRV_PCM_FORMAT_S24_LE) dest = (u32 *) (urb->buffer); else { - snd_printk(KERN_ERR PREFIX "Unknown sample format."); + dev_err(&rt->chip->dev->dev, "Unknown sample format."); return; } @@ -307,8 +310,8 @@ static void usb6fire_pcm_in_urb_handler(struct urb *usb_urb) } if (rt->stream_state == STREAM_DISABLED) { - snd_printk(KERN_ERR PREFIX "internal error: " - "stream disabled in in-urb handler.\n"); + dev_err(&rt->chip->dev->dev, + "internal error: stream disabled in in-urb handler.\n"); return; } @@ -410,7 +413,7 @@ static int usb6fire_pcm_open(struct snd_pcm_substream *alsa_sub) if (!sub) { mutex_unlock(&rt->stream_mutex); - snd_printk(KERN_ERR PREFIX "invalid stream type.\n"); + dev_err(&rt->chip->dev->dev, "invalid stream type.\n"); return -EINVAL; } @@ -481,8 +484,9 @@ static int usb6fire_pcm_prepare(struct snd_pcm_substream *alsa_sub) break; if (rt->rate == ARRAY_SIZE(rates)) { mutex_unlock(&rt->stream_mutex); - snd_printk("invalid rate %d in prepare.\n", - alsa_rt->rate); + dev_err(&rt->chip->dev->dev, + "invalid rate %d in prepare.\n", + alsa_rt->rate); return -EINVAL; } @@ -494,8 +498,8 @@ static int usb6fire_pcm_prepare(struct snd_pcm_substream *alsa_sub) ret = usb6fire_pcm_stream_start(rt); if (ret) { mutex_unlock(&rt->stream_mutex); - snd_printk(KERN_ERR PREFIX - "could not start pcm stream.\n"); + dev_err(&rt->chip->dev->dev, + "could not start pcm stream.\n"); return ret; } } @@ -650,7 +654,7 @@ int usb6fire_pcm_init(struct sfire_chip *chip) if (ret < 0) { usb6fire_pcm_buffers_destroy(rt); kfree(rt); - snd_printk(KERN_ERR PREFIX "cannot create pcm instance.\n"); + dev_err(&chip->dev->dev, "cannot create pcm instance.\n"); return ret; } @@ -662,8 +666,8 @@ int usb6fire_pcm_init(struct sfire_chip *chip) if (ret) { usb6fire_pcm_buffers_destroy(rt); kfree(rt); - snd_printk(KERN_ERR PREFIX - "error preallocating pcm buffers.\n"); + dev_err(&chip->dev->dev, + "error preallocating pcm buffers.\n"); return ret; } rt->instance = pcm; diff --git a/sound/usb/caiaq/device.c b/sound/usb/caiaq/device.c index bc55f708a69..b871ba407e4 100644 --- a/sound/usb/caiaq/device.c +++ b/sound/usb/caiaq/device.c @@ -418,8 +418,9 @@ static int create_card(struct usb_device *usb_dev, if (devnum >= SNDRV_CARDS) return -ENODEV; - err = snd_card_create(index[devnum], id[devnum], THIS_MODULE, - sizeof(struct snd_usb_caiaqdev), &card); + err = snd_card_new(&intf->dev, + index[devnum], id[devnum], THIS_MODULE, + sizeof(struct snd_usb_caiaqdev), &card); if (err < 0) return err; @@ -429,7 +430,6 @@ static int create_card(struct usb_device *usb_dev, cdev->chip.usb_id = USB_ID(le16_to_cpu(usb_dev->descriptor.idVendor), le16_to_cpu(usb_dev->descriptor.idProduct)); spin_lock_init(&cdev->spinlock); - snd_card_set_dev(card, &intf->dev); *cardp = card; return 0; diff --git a/sound/usb/card.c b/sound/usb/card.c index d979050e6a6..893d5a1afc3 100644 --- a/sound/usb/card.c +++ b/sound/usb/card.c @@ -139,8 +139,8 @@ static int snd_usb_create_stream(struct snd_usb_audio *chip, int ctrlif, int int struct usb_interface *iface = usb_ifnum_to_if(dev, interface); if (!iface) { - snd_printk(KERN_ERR "%d:%u:%d : does not exist\n", - dev->devnum, ctrlif, interface); + dev_err(&dev->dev, "%u:%d : does not exist\n", + ctrlif, interface); return -EINVAL; } @@ -165,8 +165,8 @@ static int snd_usb_create_stream(struct snd_usb_audio *chip, int ctrlif, int int } if (usb_interface_claimed(iface)) { - snd_printdd(KERN_INFO "%d:%d:%d: skipping, already claimed\n", - dev->devnum, ctrlif, interface); + dev_dbg(&dev->dev, "%d:%d: skipping, already claimed\n", + ctrlif, interface); return -EINVAL; } @@ -176,8 +176,9 @@ static int snd_usb_create_stream(struct snd_usb_audio *chip, int ctrlif, int int int err = snd_usbmidi_create(chip->card, iface, &chip->midi_list, NULL); if (err < 0) { - snd_printk(KERN_ERR "%d:%u:%d: cannot create sequencer device\n", - dev->devnum, ctrlif, interface); + dev_err(&dev->dev, + "%u:%d: cannot create sequencer device\n", + ctrlif, interface); return -EINVAL; } usb_driver_claim_interface(&usb_audio_driver, iface, (void *)-1L); @@ -188,14 +189,15 @@ static int snd_usb_create_stream(struct snd_usb_audio *chip, int ctrlif, int int if ((altsd->bInterfaceClass != USB_CLASS_AUDIO && altsd->bInterfaceClass != USB_CLASS_VENDOR_SPEC) || altsd->bInterfaceSubClass != USB_SUBCLASS_AUDIOSTREAMING) { - snd_printdd(KERN_ERR "%d:%u:%d: skipping non-supported interface %d\n", - dev->devnum, ctrlif, interface, altsd->bInterfaceClass); + dev_dbg(&dev->dev, + "%u:%d: skipping non-supported interface %d\n", + ctrlif, interface, altsd->bInterfaceClass); /* skip non-supported classes */ return -EINVAL; } if (snd_usb_get_speed(dev) == USB_SPEED_LOW) { - snd_printk(KERN_ERR "low speed audio streaming not supported\n"); + dev_err(&dev->dev, "low speed audio streaming not supported\n"); return -EINVAL; } @@ -228,26 +230,27 @@ static int snd_usb_create_streams(struct snd_usb_audio *chip, int ctrlif) protocol = altsd->bInterfaceProtocol; if (!control_header) { - snd_printk(KERN_ERR "cannot find UAC_HEADER\n"); + dev_err(&dev->dev, "cannot find UAC_HEADER\n"); return -EINVAL; } switch (protocol) { default: - snd_printdd(KERN_WARNING "unknown interface protocol %#02x, assuming v1\n", - protocol); + dev_warn(&dev->dev, + "unknown interface protocol %#02x, assuming v1\n", + protocol); /* fall through */ case UAC_VERSION_1: { struct uac1_ac_header_descriptor *h1 = control_header; if (!h1->bInCollection) { - snd_printk(KERN_INFO "skipping empty audio interface (v1)\n"); + dev_info(&dev->dev, "skipping empty audio interface (v1)\n"); return -EINVAL; } if (h1->bLength < sizeof(*h1) + h1->bInCollection) { - snd_printk(KERN_ERR "invalid UAC_HEADER (v1)\n"); + dev_err(&dev->dev, "invalid UAC_HEADER (v1)\n"); return -EINVAL; } @@ -277,7 +280,7 @@ static int snd_usb_create_streams(struct snd_usb_audio *chip, int ctrlif) } if (!assoc) { - snd_printk(KERN_ERR "Audio class v2 interfaces need an interface association\n"); + dev_err(&dev->dev, "Audio class v2 interfaces need an interface association\n"); return -EINVAL; } @@ -328,7 +331,8 @@ static void remove_trailing_spaces(char *str) /* * create a chip instance and set its names. */ -static int snd_usb_audio_create(struct usb_device *dev, int idx, +static int snd_usb_audio_create(struct usb_interface *intf, + struct usb_device *dev, int idx, const struct snd_usb_audio_quirk *quirk, struct snd_usb_audio **rchip) { @@ -350,13 +354,14 @@ static int snd_usb_audio_create(struct usb_device *dev, int idx, case USB_SPEED_SUPER: break; default: - snd_printk(KERN_ERR "unknown device speed %d\n", snd_usb_get_speed(dev)); + dev_err(&dev->dev, "unknown device speed %d\n", snd_usb_get_speed(dev)); return -ENXIO; } - err = snd_card_create(index[idx], id[idx], THIS_MODULE, 0, &card); + err = snd_card_new(&intf->dev, index[idx], id[idx], THIS_MODULE, + 0, &card); if (err < 0) { - snd_printk(KERN_ERR "cannot create card instance %d\n", idx); + dev_err(&dev->dev, "cannot create card instance %d\n", idx); return err; } @@ -497,7 +502,7 @@ snd_usb_audio_probe(struct usb_device *dev, for (i = 0; i < SNDRV_CARDS; i++) { if (usb_chip[i] && usb_chip[i]->dev == dev) { if (usb_chip[i]->shutdown) { - snd_printk(KERN_ERR "USB device is in the shutdown state, cannot create a card instance\n"); + dev_err(&dev->dev, "USB device is in the shutdown state, cannot create a card instance\n"); goto __error; } chip = usb_chip[i]; @@ -513,15 +518,15 @@ snd_usb_audio_probe(struct usb_device *dev, if (enable[i] && ! usb_chip[i] && (vid[i] == -1 || vid[i] == USB_ID_VENDOR(id)) && (pid[i] == -1 || pid[i] == USB_ID_PRODUCT(id))) { - if (snd_usb_audio_create(dev, i, quirk, &chip) < 0) { + if (snd_usb_audio_create(intf, dev, i, quirk, + &chip) < 0) { goto __error; } - snd_card_set_dev(chip->card, &intf->dev); chip->pm_intf = intf; break; } if (!chip) { - printk(KERN_ERR "no available usb audio device\n"); + dev_err(&dev->dev, "no available usb audio device\n"); goto __error; } } @@ -691,12 +696,12 @@ static int usb_audio_suspend(struct usb_interface *intf, pm_message_t message) } list_for_each_entry(mixer, &chip->mixer_list, list) - snd_usb_mixer_inactivate(mixer); + snd_usb_mixer_suspend(mixer); return 0; } -static int usb_audio_resume(struct usb_interface *intf) +static int __usb_audio_resume(struct usb_interface *intf, bool reset_resume) { struct snd_usb_audio *chip = usb_get_intfdata(intf); struct usb_mixer_interface *mixer; @@ -711,7 +716,7 @@ static int usb_audio_resume(struct usb_interface *intf) * we just notify and restart the mixers */ list_for_each_entry(mixer, &chip->mixer_list, list) { - err = snd_usb_mixer_activate(mixer); + err = snd_usb_mixer_resume(mixer, reset_resume); if (err < 0) goto err_out; } @@ -723,9 +728,20 @@ static int usb_audio_resume(struct usb_interface *intf) err_out: return err; } + +static int usb_audio_resume(struct usb_interface *intf) +{ + return __usb_audio_resume(intf, false); +} + +static int usb_audio_reset_resume(struct usb_interface *intf) +{ + return __usb_audio_resume(intf, true); +} #else #define usb_audio_suspend NULL #define usb_audio_resume NULL +#define usb_audio_reset_resume NULL #endif /* CONFIG_PM */ static struct usb_device_id usb_audio_ids [] = { @@ -747,6 +763,7 @@ static struct usb_driver usb_audio_driver = { .disconnect = usb_audio_disconnect, .suspend = usb_audio_suspend, .resume = usb_audio_resume, + .reset_resume = usb_audio_reset_resume, .id_table = usb_audio_ids, .supports_autosuspend = 1, }; diff --git a/sound/usb/clock.c b/sound/usb/clock.c index 86f80c60b21..03fed6611d9 100644 --- a/sound/usb/clock.c +++ b/sound/usb/clock.c @@ -115,9 +115,9 @@ static int uac_clock_selector_set_val(struct snd_usb_audio *chip, int selector_i return ret; if (ret != sizeof(pin)) { - snd_printk(KERN_ERR - "usb-audio:%d: setting selector (id %d) unexpected length %d\n", - chip->dev->devnum, selector_id, ret); + usb_audio_err(chip, + "setting selector (id %d) unexpected length %d\n", + selector_id, ret); return -EINVAL; } @@ -126,9 +126,9 @@ static int uac_clock_selector_set_val(struct snd_usb_audio *chip, int selector_i return ret; if (ret != pin) { - snd_printk(KERN_ERR - "usb-audio:%d: setting selector (id %d) to %x failed (current: %d)\n", - chip->dev->devnum, selector_id, pin, ret); + usb_audio_err(chip, + "setting selector (id %d) to %x failed (current: %d)\n", + selector_id, pin, ret); return -EINVAL; } @@ -158,7 +158,8 @@ static bool uac_clock_source_is_valid(struct snd_usb_audio *chip, int source_id) &data, sizeof(data)); if (err < 0) { - snd_printk(KERN_WARNING "%s(): cannot get clock validity for id %d\n", + dev_warn(&dev->dev, + "%s(): cannot get clock validity for id %d\n", __func__, source_id); return 0; } @@ -177,9 +178,9 @@ static int __uac_clock_find_source(struct snd_usb_audio *chip, entity_id &= 0xff; if (test_and_set_bit(entity_id, visited)) { - snd_printk(KERN_WARNING - "%s(): recursive clock topology detected, id %d.\n", - __func__, entity_id); + usb_audio_warn(chip, + "%s(): recursive clock topology detected, id %d.\n", + __func__, entity_id); return -EINVAL; } @@ -188,8 +189,9 @@ static int __uac_clock_find_source(struct snd_usb_audio *chip, if (source) { entity_id = source->bClockID; if (validate && !uac_clock_source_is_valid(chip, entity_id)) { - snd_printk(KERN_ERR "usb-audio:%d: clock source %d is not valid, cannot use\n", - chip->dev->devnum, entity_id); + usb_audio_err(chip, + "clock source %d is not valid, cannot use\n", + entity_id); return -ENXIO; } return entity_id; @@ -208,7 +210,7 @@ static int __uac_clock_find_source(struct snd_usb_audio *chip, /* Selector values are one-based */ if (ret > selector->bNrInPins || ret < 1) { - snd_printk(KERN_ERR + usb_audio_err(chip, "%s(): selector reported illegal value, id %d, ret %d\n", __func__, selector->bClockID, ret); @@ -237,9 +239,9 @@ static int __uac_clock_find_source(struct snd_usb_audio *chip, if (err < 0) continue; - snd_printk(KERN_INFO - "usb-audio:%d: found and selected valid clock source %d\n", - chip->dev->devnum, ret); + usb_audio_info(chip, + "found and selected valid clock source %d\n", + ret); return ret; } @@ -296,8 +298,8 @@ static int set_sample_rate_v1(struct snd_usb_audio *chip, int iface, USB_TYPE_CLASS | USB_RECIP_ENDPOINT | USB_DIR_OUT, UAC_EP_CS_ATTR_SAMPLE_RATE << 8, ep, data, sizeof(data))) < 0) { - snd_printk(KERN_ERR "%d:%d:%d: cannot set freq %d to ep %#x\n", - dev->devnum, iface, fmt->altsetting, rate, ep); + dev_err(&dev->dev, "%d:%d: cannot set freq %d to ep %#x\n", + iface, fmt->altsetting, rate, ep); return err; } @@ -305,14 +307,14 @@ static int set_sample_rate_v1(struct snd_usb_audio *chip, int iface, USB_TYPE_CLASS | USB_RECIP_ENDPOINT | USB_DIR_IN, UAC_EP_CS_ATTR_SAMPLE_RATE << 8, ep, data, sizeof(data))) < 0) { - snd_printk(KERN_WARNING "%d:%d:%d: cannot get freq at ep %#x\n", - dev->devnum, iface, fmt->altsetting, ep); + dev_err(&dev->dev, "%d:%d: cannot get freq at ep %#x\n", + iface, fmt->altsetting, ep); return 0; /* some devices don't support reading */ } crate = data[0] | (data[1] << 8) | (data[2] << 16); if (crate != rate) { - snd_printd(KERN_WARNING "current rate %d is different from the runtime rate %d\n", crate, rate); + dev_warn(&dev->dev, "current rate %d is different from the runtime rate %d\n", crate, rate); // runtime->rate = crate; } @@ -332,8 +334,8 @@ static int get_sample_rate_v2(struct snd_usb_audio *chip, int iface, snd_usb_ctrl_intf(chip) | (clock << 8), &data, sizeof(data)); if (err < 0) { - snd_printk(KERN_WARNING "%d:%d:%d: cannot get freq (v2): err %d\n", - dev->devnum, iface, altsetting, err); + dev_warn(&dev->dev, "%d:%d: cannot get freq (v2): err %d\n", + iface, altsetting, err); return 0; } @@ -369,8 +371,9 @@ static int set_sample_rate_v2(struct snd_usb_audio *chip, int iface, snd_usb_ctrl_intf(chip) | (clock << 8), &data, sizeof(data)); if (err < 0) { - snd_printk(KERN_ERR "%d:%d:%d: cannot set freq %d (v2): err %d\n", - dev->devnum, iface, fmt->altsetting, rate, err); + usb_audio_err(chip, + "%d:%d: cannot set freq %d (v2): err %d\n", + iface, fmt->altsetting, rate, err); return err; } @@ -381,14 +384,14 @@ static int set_sample_rate_v2(struct snd_usb_audio *chip, int iface, if (cur_rate != rate) { if (!writeable) { - snd_printk(KERN_WARNING - "%d:%d:%d: freq mismatch (RO clock): req %d, clock runs @%d\n", - dev->devnum, iface, fmt->altsetting, rate, cur_rate); + usb_audio_warn(chip, + "%d:%d: freq mismatch (RO clock): req %d, clock runs @%d\n", + iface, fmt->altsetting, rate, cur_rate); return -ENXIO; } - snd_printd(KERN_WARNING - "current rate %d is different from the runtime rate %d\n", - cur_rate, rate); + usb_audio_dbg(chip, + "current rate %d is different from the runtime rate %d\n", + cur_rate, rate); } /* Some devices doesn't respond to sample rate changes while the diff --git a/sound/usb/endpoint.c b/sound/usb/endpoint.c index 83aabea259d..e70a87e0d9f 100644 --- a/sound/usb/endpoint.c +++ b/sound/usb/endpoint.c @@ -333,8 +333,9 @@ static void queue_pending_output_urbs(struct snd_usb_endpoint *ep) err = usb_submit_urb(ctx->urb, GFP_ATOMIC); if (err < 0) - snd_printk(KERN_ERR "Unable to submit urb #%d: %d (urb %p)\n", - ctx->index, err, ctx->urb); + usb_audio_err(ep->chip, + "Unable to submit urb #%d: %d (urb %p)\n", + ctx->index, err, ctx->urb); else set_bit(ctx->index, &ep->active_mask); } @@ -387,7 +388,7 @@ static void snd_complete_urb(struct urb *urb) if (err == 0) return; - snd_printk(KERN_ERR "cannot submit urb (err = %d)\n", err); + usb_audio_err(ep->chip, "cannot submit urb (err = %d)\n", err); //snd_pcm_stop(substream, SNDRV_PCM_STATE_XRUN); exit_clear: @@ -426,13 +427,14 @@ struct snd_usb_endpoint *snd_usb_add_endpoint(struct snd_usb_audio *chip, if (ep->ep_num == ep_num && ep->iface == alts->desc.bInterfaceNumber && ep->altsetting == alts->desc.bAlternateSetting) { - snd_printdd(KERN_DEBUG "Re-using EP %x in iface %d,%d @%p\n", + usb_audio_dbg(ep->chip, + "Re-using EP %x in iface %d,%d @%p\n", ep_num, ep->iface, ep->altsetting, ep); goto __exit_unlock; } } - snd_printdd(KERN_DEBUG "Creating new %s %s endpoint #%x\n", + usb_audio_dbg(chip, "Creating new %s %s endpoint #%x\n", is_playback ? "playback" : "capture", type == SND_USB_ENDPOINT_TYPE_DATA ? "data" : "sync", ep_num); @@ -496,8 +498,9 @@ static int wait_clear_urbs(struct snd_usb_endpoint *ep) } while (time_before(jiffies, end_time)); if (alive) - snd_printk(KERN_ERR "timeout: still %d active urbs on EP #%x\n", - alive, ep->ep_num); + usb_audio_err(ep->chip, + "timeout: still %d active urbs on EP #%x\n", + alive, ep->ep_num); clear_bit(EP_FLAG_STOPPING, &ep->flags); return 0; @@ -794,8 +797,9 @@ int snd_usb_endpoint_set_params(struct snd_usb_endpoint *ep, int err; if (ep->use_count != 0) { - snd_printk(KERN_WARNING "Unable to change format on ep #%x: already in use\n", - ep->ep_num); + usb_audio_warn(ep->chip, + "Unable to change format on ep #%x: already in use\n", + ep->ep_num); return -EBUSY; } @@ -830,8 +834,9 @@ int snd_usb_endpoint_set_params(struct snd_usb_endpoint *ep, err = -EINVAL; } - snd_printdd(KERN_DEBUG "Setting params for ep #%x (type %d, %d urbs), ret=%d\n", - ep->ep_num, ep->type, ep->nurbs, err); + usb_audio_dbg(ep->chip, + "Setting params for ep #%x (type %d, %d urbs), ret=%d\n", + ep->ep_num, ep->type, ep->nurbs, err); return err; } @@ -906,8 +911,9 @@ int snd_usb_endpoint_start(struct snd_usb_endpoint *ep, bool can_sleep) err = usb_submit_urb(urb, GFP_ATOMIC); if (err < 0) { - snd_printk(KERN_ERR "cannot submit urb %d, error %d: %s\n", - i, err, usb_error_string(err)); + usb_audio_err(ep->chip, + "cannot submit urb %d, error %d: %s\n", + i, err, usb_error_string(err)); goto __error; } set_bit(i, &ep->active_mask); diff --git a/sound/usb/format.c b/sound/usb/format.c index d244fd3703d..8bcc87cf566 100644 --- a/sound/usb/format.c +++ b/sound/usb/format.c @@ -74,8 +74,8 @@ static u64 parse_audio_format_i_type(struct snd_usb_audio *chip, if ((pcm_formats == 0) && (format == 0 || format == (1 << UAC_FORMAT_TYPE_I_UNDEFINED))) { /* some devices don't define this correctly... */ - snd_printdd(KERN_INFO "%d:%u:%d : format type 0 is detected, processed as PCM\n", - chip->dev->devnum, fp->iface, fp->altsetting); + usb_audio_info(chip, "%u:%d : format type 0 is detected, processed as PCM\n", + fp->iface, fp->altsetting); format = 1 << UAC_FORMAT_TYPE_I_PCM; } if (format & (1 << UAC_FORMAT_TYPE_I_PCM)) { @@ -83,9 +83,9 @@ static u64 parse_audio_format_i_type(struct snd_usb_audio *chip, sample_width == 24 && sample_bytes == 2) sample_bytes = 3; else if (sample_width > sample_bytes * 8) { - snd_printk(KERN_INFO "%d:%u:%d : sample bitwidth %d in over sample bytes %d\n", - chip->dev->devnum, fp->iface, fp->altsetting, - sample_width, sample_bytes); + usb_audio_info(chip, "%u:%d : sample bitwidth %d in over sample bytes %d\n", + fp->iface, fp->altsetting, + sample_width, sample_bytes); } /* check the format byte size */ switch (sample_bytes) { @@ -108,9 +108,10 @@ static u64 parse_audio_format_i_type(struct snd_usb_audio *chip, pcm_formats |= SNDRV_PCM_FMTBIT_S32_LE; break; default: - snd_printk(KERN_INFO "%d:%u:%d : unsupported sample bitwidth %d in %d bytes\n", - chip->dev->devnum, fp->iface, fp->altsetting, - sample_width, sample_bytes); + usb_audio_info(chip, + "%u:%d : unsupported sample bitwidth %d in %d bytes\n", + fp->iface, fp->altsetting, + sample_width, sample_bytes); break; } } @@ -132,8 +133,9 @@ static u64 parse_audio_format_i_type(struct snd_usb_audio *chip, pcm_formats |= SNDRV_PCM_FMTBIT_MU_LAW; } if (format & ~0x3f) { - snd_printk(KERN_INFO "%d:%u:%d : unsupported format bits %#x\n", - chip->dev->devnum, fp->iface, fp->altsetting, format); + usb_audio_info(chip, + "%u:%d : unsupported format bits %#x\n", + fp->iface, fp->altsetting, format); } pcm_formats |= snd_usb_interface_dsd_format_quirks(chip, fp, sample_bytes); @@ -158,8 +160,9 @@ static int parse_audio_format_rates_v1(struct snd_usb_audio *chip, struct audiof int nr_rates = fmt[offset]; if (fmt[0] < offset + 1 + 3 * (nr_rates ? nr_rates : 2)) { - snd_printk(KERN_ERR "%d:%u:%d : invalid UAC_FORMAT_TYPE desc\n", - chip->dev->devnum, fp->iface, fp->altsetting); + usb_audio_err(chip, + "%u:%d : invalid UAC_FORMAT_TYPE desc\n", + fp->iface, fp->altsetting); return -EINVAL; } @@ -171,7 +174,7 @@ static int parse_audio_format_rates_v1(struct snd_usb_audio *chip, struct audiof fp->rate_table = kmalloc(sizeof(int) * nr_rates, GFP_KERNEL); if (fp->rate_table == NULL) { - snd_printk(KERN_ERR "cannot malloc\n"); + usb_audio_err(chip, "cannot malloc\n"); return -ENOMEM; } @@ -222,7 +225,8 @@ static int parse_audio_format_rates_v1(struct snd_usb_audio *chip, struct audiof * get to know how many sample rates we have to expect. * Then fp->rate_table can be allocated and filled. */ -static int parse_uac2_sample_rate_range(struct audioformat *fp, int nr_triplets, +static int parse_uac2_sample_rate_range(struct snd_usb_audio *chip, + struct audioformat *fp, int nr_triplets, const unsigned char *data) { int i, nr_rates = 0; @@ -261,7 +265,7 @@ static int parse_uac2_sample_rate_range(struct audioformat *fp, int nr_triplets, nr_rates++; if (nr_rates >= MAX_NR_RATES) { - snd_printk(KERN_ERR "invalid uac2 rates\n"); + usb_audio_err(chip, "invalid uac2 rates\n"); break; } @@ -287,7 +291,8 @@ static int parse_audio_format_rates_v2(struct snd_usb_audio *chip, int clock = snd_usb_clock_find_source(chip, fp->clock, false); if (clock < 0) { - snd_printk(KERN_ERR "%s(): unable to find clock source (clock %d)\n", + dev_err(&dev->dev, + "%s(): unable to find clock source (clock %d)\n", __func__, clock); goto err; } @@ -300,7 +305,8 @@ static int parse_audio_format_rates_v2(struct snd_usb_audio *chip, tmp, sizeof(tmp)); if (ret < 0) { - snd_printk(KERN_ERR "%s(): unable to retrieve number of sample rates (clock %d)\n", + dev_err(&dev->dev, + "%s(): unable to retrieve number of sample rates (clock %d)\n", __func__, clock); goto err; } @@ -321,7 +327,8 @@ static int parse_audio_format_rates_v2(struct snd_usb_audio *chip, data, data_size); if (ret < 0) { - snd_printk(KERN_ERR "%s(): unable to retrieve sample rate range (clock %d)\n", + dev_err(&dev->dev, + "%s(): unable to retrieve sample rate range (clock %d)\n", __func__, clock); ret = -EINVAL; goto err_free; @@ -332,7 +339,7 @@ static int parse_audio_format_rates_v2(struct snd_usb_audio *chip, * will have to deal with. */ kfree(fp->rate_table); fp->rate_table = NULL; - fp->nr_rates = parse_uac2_sample_rate_range(fp, nr_triplets, data); + fp->nr_rates = parse_uac2_sample_rate_range(chip, fp, nr_triplets, data); if (fp->nr_rates == 0) { /* SNDRV_PCM_RATE_CONTINUOUS */ @@ -348,7 +355,7 @@ static int parse_audio_format_rates_v2(struct snd_usb_audio *chip, /* Call the triplet parser again, but this time, fp->rate_table is * allocated, so the rates will be stored */ - parse_uac2_sample_rate_range(fp, nr_triplets, data); + parse_uac2_sample_rate_range(chip, fp, nr_triplets, data); err_free: kfree(data); @@ -408,8 +415,9 @@ static int parse_audio_format_i(struct snd_usb_audio *chip, } if (fp->channels < 1) { - snd_printk(KERN_ERR "%d:%u:%d : invalid channels %d\n", - chip->dev->devnum, fp->iface, fp->altsetting, fp->channels); + usb_audio_err(chip, + "%u:%d : invalid channels %d\n", + fp->iface, fp->altsetting, fp->channels); return -EINVAL; } @@ -435,8 +443,9 @@ static int parse_audio_format_ii(struct snd_usb_audio *chip, fp->formats = SNDRV_PCM_FMTBIT_MPEG; break; default: - snd_printd(KERN_INFO "%d:%u:%d : unknown format tag %#x is detected. processed as MPEG.\n", - chip->dev->devnum, fp->iface, fp->altsetting, format); + usb_audio_info(chip, + "%u:%d : unknown format tag %#x is detected. processed as MPEG.\n", + fp->iface, fp->altsetting, format); fp->formats = SNDRV_PCM_FMTBIT_MPEG; break; } @@ -449,7 +458,7 @@ static int parse_audio_format_ii(struct snd_usb_audio *chip, struct uac_format_type_ii_discrete_descriptor *fmt = _fmt; brate = le16_to_cpu(fmt->wMaxBitRate); framesize = le16_to_cpu(fmt->wSamplesPerFrame); - snd_printd(KERN_INFO "found format II with max.bitrate = %d, frame size=%d\n", brate, framesize); + usb_audio_info(chip, "found format II with max.bitrate = %d, frame size=%d\n", brate, framesize); fp->frame_size = framesize; ret = parse_audio_format_rates_v1(chip, fp, _fmt, 8); /* fmt[8..] sample rates */ break; @@ -458,7 +467,7 @@ static int parse_audio_format_ii(struct snd_usb_audio *chip, struct uac_format_type_ii_ext_descriptor *fmt = _fmt; brate = le16_to_cpu(fmt->wMaxBitRate); framesize = le16_to_cpu(fmt->wSamplesPerFrame); - snd_printd(KERN_INFO "found format II with max.bitrate = %d, frame size=%d\n", brate, framesize); + usb_audio_info(chip, "found format II with max.bitrate = %d, frame size=%d\n", brate, framesize); fp->frame_size = framesize; ret = parse_audio_format_rates_v2(chip, fp); break; @@ -484,9 +493,10 @@ int snd_usb_parse_audio_format(struct snd_usb_audio *chip, err = parse_audio_format_ii(chip, fp, format, fmt); break; default: - snd_printd(KERN_INFO "%d:%u:%d : format type %d is not supported yet\n", - chip->dev->devnum, fp->iface, fp->altsetting, - fmt->bFormatType); + usb_audio_info(chip, + "%u:%d : format type %d is not supported yet\n", + fp->iface, fp->altsetting, + fmt->bFormatType); return -ENOTSUPP; } fp->fmt_type = fmt->bFormatType; diff --git a/sound/usb/hiface/chip.c b/sound/usb/hiface/chip.c index b0dcb3924ce..2670d646bda 100644 --- a/sound/usb/hiface/chip.c +++ b/sound/usb/hiface/chip.c @@ -64,7 +64,8 @@ struct hiface_vendor_quirk { u8 extra_freq; }; -static int hiface_chip_create(struct usb_device *device, int idx, +static int hiface_chip_create(struct usb_interface *intf, + struct usb_device *device, int idx, const struct hiface_vendor_quirk *quirk, struct hiface_chip **rchip) { @@ -76,7 +77,8 @@ static int hiface_chip_create(struct usb_device *device, int idx, *rchip = NULL; /* if we are here, card can be registered in alsa. */ - ret = snd_card_create(index[idx], id[idx], THIS_MODULE, sizeof(*chip), &card); + ret = snd_card_new(&intf->dev, index[idx], id[idx], THIS_MODULE, + sizeof(*chip), &card); if (ret < 0) { dev_err(&device->dev, "cannot create alsa card.\n"); return ret; @@ -132,12 +134,10 @@ static int hiface_chip_probe(struct usb_interface *intf, goto err; } - ret = hiface_chip_create(device, i, quirk, &chip); + ret = hiface_chip_create(intf, device, i, quirk, &chip); if (ret < 0) goto err; - snd_card_set_dev(chip->card, &intf->dev); - ret = hiface_pcm_init(chip, quirk ? quirk->extra_freq : 0); if (ret < 0) goto err_chip_destroy; diff --git a/sound/usb/midi.c b/sound/usb/midi.c index b901f468b67..9da74d2e8ee 100644 --- a/sound/usb/midi.c +++ b/sound/usb/midi.c @@ -191,16 +191,16 @@ static int snd_usbmidi_submit_urb(struct urb* urb, gfp_t flags) { int err = usb_submit_urb(urb, flags); if (err < 0 && err != -ENODEV) - snd_printk(KERN_ERR "usb_submit_urb: %d\n", err); + dev_err(&urb->dev->dev, "usb_submit_urb: %d\n", err); return err; } /* * Error handling for URB completion functions. */ -static int snd_usbmidi_urb_error(int status) +static int snd_usbmidi_urb_error(const struct urb *urb) { - switch (status) { + switch (urb->status) { /* manually unlinked, or device gone */ case -ENOENT: case -ECONNRESET: @@ -213,7 +213,7 @@ static int snd_usbmidi_urb_error(int status) case -EILSEQ: return -EIO; default: - snd_printk(KERN_ERR "urb status %d\n", status); + dev_err(&urb->dev->dev, "urb status %d\n", urb->status); return 0; /* continue */ } } @@ -227,7 +227,7 @@ static void snd_usbmidi_input_data(struct snd_usb_midi_in_endpoint* ep, int port struct usbmidi_in_port* port = &ep->ports[portidx]; if (!port->substream) { - snd_printd("unexpected port %d!\n", portidx); + dev_dbg(&ep->umidi->dev->dev, "unexpected port %d!\n", portidx); return; } if (!test_bit(port->substream->number, &ep->umidi->input_triggered)) @@ -259,7 +259,7 @@ static void snd_usbmidi_in_urb_complete(struct urb* urb) ep->umidi->usb_protocol_ops->input(ep, urb->transfer_buffer, urb->actual_length); } else { - int err = snd_usbmidi_urb_error(urb->status); + int err = snd_usbmidi_urb_error(urb); if (err < 0) { if (err != -ENODEV) { ep->error_resubmit = 1; @@ -289,7 +289,7 @@ static void snd_usbmidi_out_urb_complete(struct urb* urb) } spin_unlock(&ep->buffer_lock); if (urb->status < 0) { - int err = snd_usbmidi_urb_error(urb->status); + int err = snd_usbmidi_urb_error(urb); if (err < 0) { if (err != -ENODEV) mod_timer(&ep->umidi->error_timer, @@ -1668,7 +1668,7 @@ static void snd_usbmidi_init_substream(struct snd_usb_midi* umidi, struct snd_rawmidi_substream *substream = snd_usbmidi_find_substream(umidi, stream, number); if (!substream) { - snd_printd(KERN_ERR "substream %d:%d not found\n", stream, number); + dev_err(&umidi->dev->dev, "substream %d:%d not found\n", stream, number); return; } @@ -1717,7 +1717,7 @@ static int snd_usbmidi_create_endpoints(struct snd_usb_midi* umidi, } } } - snd_printdd(KERN_INFO "created %d output and %d input ports\n", + dev_dbg(&umidi->dev->dev, "created %d output and %d input ports\n", out_ports, in_ports); return 0; } @@ -1747,10 +1747,11 @@ static int snd_usbmidi_get_ms_info(struct snd_usb_midi* umidi, ms_header->bLength >= 7 && ms_header->bDescriptorType == USB_DT_CS_INTERFACE && ms_header->bDescriptorSubtype == UAC_HEADER) - snd_printdd(KERN_INFO "MIDIStreaming version %02x.%02x\n", + dev_dbg(&umidi->dev->dev, "MIDIStreaming version %02x.%02x\n", ms_header->bcdMSC[1], ms_header->bcdMSC[0]); else - snd_printk(KERN_WARNING "MIDIStreaming interface descriptor not found\n"); + dev_warn(&umidi->dev->dev, + "MIDIStreaming interface descriptor not found\n"); epidx = 0; for (i = 0; i < intfd->bNumEndpoints; ++i) { @@ -1767,7 +1768,8 @@ static int snd_usbmidi_get_ms_info(struct snd_usb_midi* umidi, if (usb_endpoint_dir_out(ep)) { if (endpoints[epidx].out_ep) { if (++epidx >= MIDI_MAX_ENDPOINTS) { - snd_printk(KERN_WARNING "too many endpoints\n"); + dev_warn(&umidi->dev->dev, + "too many endpoints\n"); break; } } @@ -1782,12 +1784,13 @@ static int snd_usbmidi_get_ms_info(struct snd_usb_midi* umidi, */ endpoints[epidx].out_interval = 1; endpoints[epidx].out_cables = (1 << ms_ep->bNumEmbMIDIJack) - 1; - snd_printdd(KERN_INFO "EP %02X: %d jack(s)\n", + dev_dbg(&umidi->dev->dev, "EP %02X: %d jack(s)\n", ep->bEndpointAddress, ms_ep->bNumEmbMIDIJack); } else { if (endpoints[epidx].in_ep) { if (++epidx >= MIDI_MAX_ENDPOINTS) { - snd_printk(KERN_WARNING "too many endpoints\n"); + dev_warn(&umidi->dev->dev, + "too many endpoints\n"); break; } } @@ -1797,7 +1800,7 @@ static int snd_usbmidi_get_ms_info(struct snd_usb_midi* umidi, else if (snd_usb_get_speed(umidi->dev) == USB_SPEED_LOW) endpoints[epidx].in_interval = 1; endpoints[epidx].in_cables = (1 << ms_ep->bNumEmbMIDIJack) - 1; - snd_printdd(KERN_INFO "EP %02X: %d jack(s)\n", + dev_dbg(&umidi->dev->dev, "EP %02X: %d jack(s)\n", ep->bEndpointAddress, ms_ep->bNumEmbMIDIJack); } } @@ -1865,7 +1868,7 @@ static void snd_usbmidi_switch_roland_altsetting(struct snd_usb_midi* umidi) (get_endpoint(hostif, 1)->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) != USB_ENDPOINT_XFER_INT) return; - snd_printdd(KERN_INFO "switching to altsetting %d with int ep\n", + dev_dbg(&umidi->dev->dev, "switching to altsetting %d with int ep\n", intfd->bAlternateSetting); usb_set_interface(umidi->dev, intfd->bInterfaceNumber, intfd->bAlternateSetting); @@ -2047,25 +2050,25 @@ static int snd_usbmidi_create_endpoints_midiman(struct snd_usb_midi* umidi, * input bulk endpoints (at indices 1 and 3) which aren't used. */ if (intfd->bNumEndpoints < (endpoint->out_cables > 0x0001 ? 5 : 3)) { - snd_printdd(KERN_ERR "not enough endpoints\n"); + dev_dbg(&umidi->dev->dev, "not enough endpoints\n"); return -ENOENT; } epd = get_endpoint(hostif, 0); if (!usb_endpoint_dir_in(epd) || !usb_endpoint_xfer_int(epd)) { - snd_printdd(KERN_ERR "endpoint[0] isn't interrupt\n"); + dev_dbg(&umidi->dev->dev, "endpoint[0] isn't interrupt\n"); return -ENXIO; } epd = get_endpoint(hostif, 2); if (!usb_endpoint_dir_out(epd) || !usb_endpoint_xfer_bulk(epd)) { - snd_printdd(KERN_ERR "endpoint[2] isn't bulk output\n"); + dev_dbg(&umidi->dev->dev, "endpoint[2] isn't bulk output\n"); return -ENXIO; } if (endpoint->out_cables > 0x0001) { epd = get_endpoint(hostif, 4); if (!usb_endpoint_dir_out(epd) || !usb_endpoint_xfer_bulk(epd)) { - snd_printdd(KERN_ERR "endpoint[4] isn't bulk output\n"); + dev_dbg(&umidi->dev->dev, "endpoint[4] isn't bulk output\n"); return -ENXIO; } } @@ -2289,7 +2292,7 @@ int snd_usbmidi_create(struct snd_card *card, err = snd_usbmidi_detect_per_port_endpoints(umidi, endpoints); break; default: - snd_printd(KERN_ERR "invalid quirk type %d\n", quirk->type); + dev_err(&umidi->dev->dev, "invalid quirk type %d\n", quirk->type); err = -ENXIO; break; } diff --git a/sound/usb/misc/ua101.c b/sound/usb/misc/ua101.c index 509315937f2..a1bab149df4 100644 --- a/sound/usb/misc/ua101.c +++ b/sound/usb/misc/ua101.c @@ -1243,8 +1243,9 @@ static int ua101_probe(struct usb_interface *interface, mutex_unlock(&devices_mutex); return -ENOENT; } - err = snd_card_create(index[card_index], id[card_index], THIS_MODULE, - sizeof(*ua), &card); + err = snd_card_new(&interface->dev, + index[card_index], id[card_index], THIS_MODULE, + sizeof(*ua), &card); if (err < 0) { mutex_unlock(&devices_mutex); return err; @@ -1283,8 +1284,6 @@ static int ua101_probe(struct usb_interface *interface, } } - snd_card_set_dev(card, &interface->dev); - err = detect_usb_format(ua); if (err < 0) goto probe_error; diff --git a/sound/usb/mixer.c b/sound/usb/mixer.c index 1bed780e21d..d40a2850e27 100644 --- a/sound/usb/mixer.c +++ b/sound/usb/mixer.c @@ -305,8 +305,9 @@ static int get_ctl_value_v1(struct usb_mixer_elem_info *cval, int request, int v goto out; } } - snd_printdd(KERN_ERR "cannot get ctl value: req = %#x, wValue = %#x, wIndex = %#x, type = %d\n", - request, validx, idx, cval->val_type); + usb_audio_dbg(chip, + "cannot get ctl value: req = %#x, wValue = %#x, wIndex = %#x, type = %d\n", + request, validx, idx, cval->val_type); err = -EINVAL; out: @@ -351,8 +352,9 @@ static int get_ctl_value_v2(struct usb_mixer_elem_info *cval, int request, int v if (ret < 0) { error: - snd_printk(KERN_ERR "cannot get ctl value: req = %#x, wValue = %#x, wIndex = %#x, type = %d\n", - request, validx, idx, cval->val_type); + usb_audio_err(chip, + "cannot get ctl value: req = %#x, wValue = %#x, wIndex = %#x, type = %d\n", + request, validx, idx, cval->val_type); return ret; } @@ -413,7 +415,8 @@ static int get_cur_mix_value(struct usb_mixer_elem_info *cval, err = get_cur_mix_raw(cval, channel, value); if (err < 0) { if (!cval->mixer->ignore_ctl_error) - snd_printd(KERN_ERR "cannot get current value for control %d ch %d: err = %d\n", + usb_audio_dbg(cval->mixer->chip, + "cannot get current value for control %d ch %d: err = %d\n", cval->control, channel, err); return err; } @@ -444,7 +447,7 @@ int snd_usb_mixer_set_ctl_value(struct usb_mixer_elem_info *cval, /* FIXME */ if (request != UAC_SET_CUR) { - snd_printdd(KERN_WARNING "RANGE setting not yet supported\n"); + usb_audio_dbg(chip, "RANGE setting not yet supported\n"); return -EINVAL; } @@ -470,7 +473,7 @@ int snd_usb_mixer_set_ctl_value(struct usb_mixer_elem_info *cval, goto out; } } - snd_printdd(KERN_ERR "cannot set ctl value: req = %#x, wValue = %#x, wIndex = %#x, type = %d, data = %#x/%#x\n", + usb_audio_dbg(chip, "cannot set ctl value: req = %#x, wValue = %#x, wIndex = %#x, type = %d, data = %#x/%#x\n", request, validx, idx, cval->val_type, buf[0], buf[1]); err = -EINVAL; @@ -494,7 +497,8 @@ static int set_cur_mix_value(struct usb_mixer_elem_info *cval, int channel, cval->ch_readonly & (1 << (channel - 1)); if (read_only) { - snd_printdd(KERN_INFO "%s(): channel %d of control %d is read_only\n", + usb_audio_dbg(cval->mixer->chip, + "%s(): channel %d of control %d is read_only\n", __func__, channel, cval->control); return 0; } @@ -560,7 +564,7 @@ int snd_usb_mixer_add_control(struct usb_mixer_interface *mixer, while (snd_ctl_find_id(mixer->chip->card, &kctl->id)) kctl->id.index++; if ((err = snd_ctl_add(mixer->chip->card, kctl)) < 0) { - snd_printd(KERN_ERR "cannot add control (err = %d)\n", err); + usb_audio_dbg(mixer->chip, "cannot add control (err = %d)\n", err); return err; } cval->elem_id = &kctl->id; @@ -807,7 +811,8 @@ static void usb_mixer_elem_free(struct snd_kcontrol *kctl) static void volume_control_quirks(struct usb_mixer_elem_info *cval, struct snd_kcontrol *kctl) { - switch (cval->mixer->chip->usb_id) { + struct snd_usb_audio *chip = cval->mixer->chip; + switch (chip->usb_id) { case USB_ID(0x0763, 0x2030): /* M-Audio Fast Track C400 */ case USB_ID(0x0763, 0x2031): /* M-Audio Fast Track C600 */ if (strcmp(kctl->id.name, "Effect Duration") == 0) { @@ -839,8 +844,8 @@ static void volume_control_quirks(struct usb_mixer_elem_info *cval, case USB_ID(0x0763, 0x2081): /* M-Audio Fast Track Ultra 8R */ case USB_ID(0x0763, 0x2080): /* M-Audio Fast Track Ultra */ if (strcmp(kctl->id.name, "Effect Duration") == 0) { - snd_printk(KERN_INFO - "usb-audio: set quirk for FTU Effect Duration\n"); + usb_audio_info(chip, + "set quirk for FTU Effect Duration\n"); cval->min = 0x0000; cval->max = 0x7f00; cval->res = 0x0100; @@ -848,8 +853,8 @@ static void volume_control_quirks(struct usb_mixer_elem_info *cval, } if (strcmp(kctl->id.name, "Effect Volume") == 0 || strcmp(kctl->id.name, "Effect Feedback Volume") == 0) { - snd_printk(KERN_INFO - "usb-audio: set quirks for FTU Effect Feedback/Volume\n"); + usb_audio_info(chip, + "set quirks for FTU Effect Feedback/Volume\n"); cval->min = 0x00; cval->max = 0x7f; break; @@ -867,7 +872,7 @@ static void volume_control_quirks(struct usb_mixer_elem_info *cval, */ if (!strcmp(kctl->id.name, "PCM Playback Volume") && cval->min == -15616) { - snd_printk(KERN_INFO + usb_audio_info(chip, "set volume quirk for UDA1321/N101 chip\n"); cval->max = -256; } @@ -875,7 +880,7 @@ static void volume_control_quirks(struct usb_mixer_elem_info *cval, case USB_ID(0x046d, 0x09a4): if (!strcmp(kctl->id.name, "Mic Capture Volume")) { - snd_printk(KERN_INFO + usb_audio_info(chip, "set volume quirk for QuickCam E3500\n"); cval->min = 6080; cval->max = 8768; @@ -896,7 +901,7 @@ static void volume_control_quirks(struct usb_mixer_elem_info *cval, * Proboly there is some logitech magic behind this number --fishor */ if (!strcmp(kctl->id.name, "Mic Capture Volume")) { - snd_printk(KERN_INFO + usb_audio_info(chip, "set resolution quirk: cval->res = 384\n"); cval->res = 384; } @@ -932,7 +937,8 @@ static int get_min_max_with_quirks(struct usb_mixer_elem_info *cval, } if (get_ctl_value(cval, UAC_GET_MAX, (cval->control << 8) | minchn, &cval->max) < 0 || get_ctl_value(cval, UAC_GET_MIN, (cval->control << 8) | minchn, &cval->min) < 0) { - snd_printd(KERN_ERR "%d:%d: cannot get min/max values for control %d (id %d)\n", + usb_audio_err(cval->mixer->chip, + "%d:%d: cannot get min/max values for control %d (id %d)\n", cval->id, snd_usb_ctrl_intf(cval->mixer->chip), cval->control, cval->id); return -EINVAL; } @@ -1196,7 +1202,7 @@ static void build_feature_ctl(struct mixer_build *state, void *raw_desc, cval = kzalloc(sizeof(*cval), GFP_KERNEL); if (! cval) { - snd_printk(KERN_ERR "cannot malloc kcontrol\n"); + usb_audio_err(state->chip, "cannot malloc kcontrol\n"); return; } cval->mixer = state->mixer; @@ -1225,7 +1231,7 @@ static void build_feature_ctl(struct mixer_build *state, void *raw_desc, kctl = snd_ctl_new1(&usb_feature_unit_ctl, cval); if (! kctl) { - snd_printk(KERN_ERR "cannot malloc kcontrol\n"); + usb_audio_err(state->chip, "cannot malloc kcontrol\n"); kfree(cval); return; } @@ -1299,16 +1305,16 @@ static void build_feature_ctl(struct mixer_build *state, void *raw_desc, * devices. It will definitively catch all buggy Logitech devices. */ if (range > 384) { - snd_printk(KERN_WARNING "usb_audio: Warning! Unlikely big " + usb_audio_warn(state->chip, "Warning! Unlikely big " "volume range (=%u), cval->res is probably wrong.", range); - snd_printk(KERN_WARNING "usb_audio: [%d] FU [%s] ch = %d, " + usb_audio_warn(state->chip, "[%d] FU [%s] ch = %d, " "val = %d/%d/%d", cval->id, kctl->id.name, cval->channels, cval->min, cval->max, cval->res); } - snd_printdd(KERN_INFO "[%d] FU [%s] ch = %d, val = %d/%d/%d\n", + usb_audio_dbg(state->chip, "[%d] FU [%s] ch = %d, val = %d/%d/%d\n", cval->id, kctl->id.name, cval->channels, cval->min, cval->max, cval->res); snd_usb_mixer_add_control(state->mixer, kctl); } @@ -1332,16 +1338,17 @@ static int parse_audio_feature_unit(struct mixer_build *state, int unitid, void if (state->mixer->protocol == UAC_VERSION_1) { csize = hdr->bControlSize; if (!csize) { - snd_printdd(KERN_ERR "usbaudio: unit %u: " - "invalid bControlSize == 0\n", unitid); + usb_audio_dbg(state->chip, + "unit %u: invalid bControlSize == 0\n", + unitid); return -EINVAL; } channels = (hdr->bLength - 7) / csize - 1; bmaControls = hdr->bmaControls; if (hdr->bLength < 7 + csize) { - snd_printk(KERN_ERR "usbaudio: unit %u: " - "invalid UAC_FEATURE_UNIT descriptor\n", - unitid); + usb_audio_err(state->chip, + "unit %u: invalid UAC_FEATURE_UNIT descriptor\n", + unitid); return -EINVAL; } } else { @@ -1350,9 +1357,9 @@ static int parse_audio_feature_unit(struct mixer_build *state, int unitid, void channels = (hdr->bLength - 6) / 4 - 1; bmaControls = ftr->bmaControls; if (hdr->bLength < 6 + csize) { - snd_printk(KERN_ERR "usbaudio: unit %u: " - "invalid UAC_FEATURE_UNIT descriptor\n", - unitid); + usb_audio_err(state->chip, + "unit %u: invalid UAC_FEATURE_UNIT descriptor\n", + unitid); return -EINVAL; } } @@ -1370,14 +1377,14 @@ static int parse_audio_feature_unit(struct mixer_build *state, int unitid, void /* master configuration quirks */ switch (state->chip->usb_id) { case USB_ID(0x08bb, 0x2702): - snd_printk(KERN_INFO - "usbmixer: master volume quirk for PCM2702 chip\n"); + usb_audio_info(state->chip, + "usbmixer: master volume quirk for PCM2702 chip\n"); /* disable non-functional volume control */ master_bits &= ~UAC_CONTROL_BIT(UAC_FU_VOLUME); break; case USB_ID(0x1130, 0xf211): - snd_printk(KERN_INFO - "usbmixer: volume control quirk for Tenx TP6911 Audio Headset\n"); + usb_audio_info(state->chip, + "usbmixer: volume control quirk for Tenx TP6911 Audio Headset\n"); /* disable non-functional volume control */ channels = 0; break; @@ -1479,7 +1486,7 @@ static void build_mixer_unit_ctl(struct mixer_build *state, kctl = snd_ctl_new1(&usb_feature_unit_ctl, cval); if (! kctl) { - snd_printk(KERN_ERR "cannot malloc kcontrol\n"); + usb_audio_err(state->chip, "cannot malloc kcontrol\n"); kfree(cval); return; } @@ -1492,7 +1499,7 @@ static void build_mixer_unit_ctl(struct mixer_build *state, len = sprintf(kctl->id.name, "Mixer Source %d", in_ch + 1); append_ctl_name(kctl, " Volume"); - snd_printdd(KERN_INFO "[%d] MU [%s] ch = %d, val = %d/%d\n", + usb_audio_dbg(state->chip, "[%d] MU [%s] ch = %d, val = %d/%d\n", cval->id, kctl->id.name, cval->channels, cval->min, cval->max); snd_usb_mixer_add_control(state->mixer, kctl); } @@ -1509,12 +1516,12 @@ static int parse_audio_mixer_unit(struct mixer_build *state, int unitid, void *r int pin, ich, err; if (desc->bLength < 11 || ! (input_pins = desc->bNrInPins) || ! (num_outs = uac_mixer_unit_bNrChannels(desc))) { - snd_printk(KERN_ERR "invalid MIXER UNIT descriptor %d\n", unitid); + usb_audio_err(state->chip, "invalid MIXER UNIT descriptor %d\n", unitid); return -EINVAL; } /* no bmControls field (e.g. Maya44) -> ignore */ if (desc->bLength <= 10 + input_pins) { - snd_printdd(KERN_INFO "MU %d has no bmControls field\n", unitid); + usb_audio_dbg(state->chip, "MU %d has no bmControls field\n", unitid); return 0; } @@ -1713,7 +1720,7 @@ static int build_audio_procunit(struct mixer_build *state, int unitid, void *raw if (desc->bLength < 13 || desc->bLength < 13 + num_ins || desc->bLength < num_ins + uac_processing_unit_bControlSize(desc, state->mixer->protocol)) { - snd_printk(KERN_ERR "invalid %s descriptor (id %d)\n", name, unitid); + usb_audio_err(state->chip, "invalid %s descriptor (id %d)\n", name, unitid); return -EINVAL; } @@ -1739,7 +1746,7 @@ static int build_audio_procunit(struct mixer_build *state, int unitid, void *raw continue; cval = kzalloc(sizeof(*cval), GFP_KERNEL); if (! cval) { - snd_printk(KERN_ERR "cannot malloc kcontrol\n"); + usb_audio_err(state->chip, "cannot malloc kcontrol\n"); return -ENOMEM; } cval->mixer = state->mixer; @@ -1771,7 +1778,7 @@ static int build_audio_procunit(struct mixer_build *state, int unitid, void *raw kctl = snd_ctl_new1(&mixer_procunit_ctl, cval); if (! kctl) { - snd_printk(KERN_ERR "cannot malloc kcontrol\n"); + usb_audio_err(state->chip, "cannot malloc kcontrol\n"); kfree(cval); return -ENOMEM; } @@ -1793,7 +1800,8 @@ static int build_audio_procunit(struct mixer_build *state, int unitid, void *raw append_ctl_name(kctl, " "); append_ctl_name(kctl, valinfo->suffix); - snd_printdd(KERN_INFO "[%d] PU [%s] ch = %d, val = %d/%d\n", + usb_audio_dbg(state->chip, + "[%d] PU [%s] ch = %d, val = %d/%d\n", cval->id, kctl->id.name, cval->channels, cval->min, cval->max); if ((err = snd_usb_mixer_add_control(state->mixer, kctl)) < 0) return err; @@ -1918,7 +1926,8 @@ static int parse_audio_selector_unit(struct mixer_build *state, int unitid, void char **namelist; if (!desc->bNrInPins || desc->bLength < 5 + desc->bNrInPins) { - snd_printk(KERN_ERR "invalid SELECTOR UNIT descriptor %d\n", unitid); + usb_audio_err(state->chip, + "invalid SELECTOR UNIT descriptor %d\n", unitid); return -EINVAL; } @@ -1936,7 +1945,7 @@ static int parse_audio_selector_unit(struct mixer_build *state, int unitid, void cval = kzalloc(sizeof(*cval), GFP_KERNEL); if (! cval) { - snd_printk(KERN_ERR "cannot malloc kcontrol\n"); + usb_audio_err(state->chip, "cannot malloc kcontrol\n"); return -ENOMEM; } cval->mixer = state->mixer; @@ -1955,7 +1964,7 @@ static int parse_audio_selector_unit(struct mixer_build *state, int unitid, void namelist = kmalloc(sizeof(char *) * desc->bNrInPins, GFP_KERNEL); if (! namelist) { - snd_printk(KERN_ERR "cannot malloc\n"); + usb_audio_err(state->chip, "cannot malloc\n"); kfree(cval); return -ENOMEM; } @@ -1965,7 +1974,7 @@ static int parse_audio_selector_unit(struct mixer_build *state, int unitid, void len = 0; namelist[i] = kmalloc(MAX_ITEM_NAME_LEN, GFP_KERNEL); if (! namelist[i]) { - snd_printk(KERN_ERR "cannot malloc\n"); + usb_audio_err(state->chip, "cannot malloc\n"); while (i--) kfree(namelist[i]); kfree(namelist); @@ -1982,7 +1991,7 @@ static int parse_audio_selector_unit(struct mixer_build *state, int unitid, void kctl = snd_ctl_new1(&mixer_selectunit_ctl, cval); if (! kctl) { - snd_printk(KERN_ERR "cannot malloc kcontrol\n"); + usb_audio_err(state->chip, "cannot malloc kcontrol\n"); kfree(namelist); kfree(cval); return -ENOMEM; @@ -2010,7 +2019,7 @@ static int parse_audio_selector_unit(struct mixer_build *state, int unitid, void append_ctl_name(kctl, " Playback Source"); } - snd_printdd(KERN_INFO "[%d] SU [%s] items = %d\n", + usb_audio_dbg(state->chip, "[%d] SU [%s] items = %d\n", cval->id, kctl->id.name, desc->bNrInPins); if ((err = snd_usb_mixer_add_control(state->mixer, kctl)) < 0) return err; @@ -2032,7 +2041,7 @@ static int parse_audio_unit(struct mixer_build *state, int unitid) p1 = find_audio_control_unit(state, unitid); if (!p1) { - snd_printk(KERN_ERR "usbaudio: unit %d not found!\n", unitid); + usb_audio_err(state->chip, "unit %d not found!\n", unitid); return -EINVAL; } @@ -2062,7 +2071,8 @@ static int parse_audio_unit(struct mixer_build *state, int unitid) case UAC2_EXTENSION_UNIT_V2: return parse_audio_extension_unit(state, unitid, p1); default: - snd_printk(KERN_ERR "usbaudio: unit %u: unexpected type 0x%02x\n", unitid, p1[2]); + usb_audio_err(state->chip, + "unit %u: unexpected type 0x%02x\n", unitid, p1[2]); return -EINVAL; } } @@ -2210,8 +2220,9 @@ static void snd_usb_mixer_interrupt_v2(struct usb_mixer_interface *mixer, __u8 channel = value & 0xff; if (channel >= MAX_CHANNELS) { - snd_printk(KERN_DEBUG "%s(): bogus channel number %d\n", - __func__, channel); + usb_audio_dbg(mixer->chip, + "%s(): bogus channel number %d\n", + __func__, channel); return; } @@ -2240,8 +2251,9 @@ static void snd_usb_mixer_interrupt_v2(struct usb_mixer_interface *mixer, break; default: - snd_printk(KERN_DEBUG "unknown attribute %d in interrupt\n", - attribute); + usb_audio_dbg(mixer->chip, + "unknown attribute %d in interrupt\n", + attribute); break; } /* switch */ } @@ -2262,7 +2274,7 @@ static void snd_usb_mixer_interrupt(struct urb *urb) for (status = urb->transfer_buffer; len >= sizeof(*status); len -= sizeof(*status), status++) { - snd_printd(KERN_DEBUG "status interrupt: %02x %02x\n", + dev_dbg(&urb->dev->dev, "status interrupt: %02x %02x\n", status->bStatusType, status->bOriginator); @@ -2300,26 +2312,6 @@ requeue: } } -/* stop any bus activity of a mixer */ -void snd_usb_mixer_inactivate(struct usb_mixer_interface *mixer) -{ - usb_kill_urb(mixer->urb); - usb_kill_urb(mixer->rc_urb); -} - -int snd_usb_mixer_activate(struct usb_mixer_interface *mixer) -{ - int err; - - if (mixer->urb) { - err = usb_submit_urb(mixer->urb, GFP_NOIO); - if (err < 0) - return err; - } - - return 0; -} - /* create the handler for the optional status interrupt endpoint */ static int snd_usb_mixer_status_create(struct usb_mixer_interface *mixer) { @@ -2394,7 +2386,7 @@ int snd_usb_create_mixer(struct snd_usb_audio *chip, int ctrlif, snd_usb_mixer_apply_create_quirk(mixer); - err = snd_device_new(chip->card, SNDRV_DEV_LOWLEVEL, mixer, &dev_ops); + err = snd_device_new(chip->card, SNDRV_DEV_CODEC, mixer, &dev_ops); if (err < 0) goto _error; @@ -2418,3 +2410,82 @@ void snd_usb_mixer_disconnect(struct list_head *p) usb_kill_urb(mixer->urb); usb_kill_urb(mixer->rc_urb); } + +#ifdef CONFIG_PM +/* stop any bus activity of a mixer */ +static void snd_usb_mixer_inactivate(struct usb_mixer_interface *mixer) +{ + usb_kill_urb(mixer->urb); + usb_kill_urb(mixer->rc_urb); +} + +static int snd_usb_mixer_activate(struct usb_mixer_interface *mixer) +{ + int err; + + if (mixer->urb) { + err = usb_submit_urb(mixer->urb, GFP_NOIO); + if (err < 0) + return err; + } + + return 0; +} + +int snd_usb_mixer_suspend(struct usb_mixer_interface *mixer) +{ + snd_usb_mixer_inactivate(mixer); + return 0; +} + +static int restore_mixer_value(struct usb_mixer_elem_info *cval) +{ + int c, err, idx; + + if (cval->cmask) { + idx = 0; + for (c = 0; c < MAX_CHANNELS; c++) { + if (!(cval->cmask & (1 << c))) + continue; + if (cval->cached & (1 << c)) { + err = set_cur_mix_value(cval, c + 1, idx, + cval->cache_val[idx]); + if (err < 0) + return err; + } + idx++; + } + } else { + /* master */ + if (cval->cached) { + err = set_cur_mix_value(cval, 0, 0, *cval->cache_val); + if (err < 0) + return err; + } + } + + return 0; +} + +int snd_usb_mixer_resume(struct usb_mixer_interface *mixer, bool reset_resume) +{ + struct usb_mixer_elem_info *cval; + int id, err; + + /* FIXME: any mixer quirks? */ + + if (reset_resume) { + /* restore cached mixer values */ + for (id = 0; id < MAX_ID_ELEMS; id++) { + for (cval = mixer->id_elems[id]; cval; + cval = cval->next_id_elem) { + err = restore_mixer_value(cval); + if (err < 0) + return err; + } + } + } + + return snd_usb_mixer_activate(mixer); +} +#endif diff --git a/sound/usb/mixer.h b/sound/usb/mixer.h index aab80df201b..73b1f649447 100644 --- a/sound/usb/mixer.h +++ b/sound/usb/mixer.h @@ -63,8 +63,6 @@ void snd_usb_mixer_notify_id(struct usb_mixer_interface *mixer, int unitid); int snd_usb_mixer_set_ctl_value(struct usb_mixer_elem_info *cval, int request, int validx, int value_set); -void snd_usb_mixer_inactivate(struct usb_mixer_interface *mixer); -int snd_usb_mixer_activate(struct usb_mixer_interface *mixer); int snd_usb_mixer_add_control(struct usb_mixer_interface *mixer, struct snd_kcontrol *kctl); @@ -72,4 +70,9 @@ int snd_usb_mixer_add_control(struct usb_mixer_interface *mixer, int snd_usb_mixer_vol_tlv(struct snd_kcontrol *kcontrol, int op_flag, unsigned int size, unsigned int __user *_tlv); +#ifdef CONFIG_PM +int snd_usb_mixer_suspend(struct usb_mixer_interface *mixer); +int snd_usb_mixer_resume(struct usb_mixer_interface *mixer, bool reset_resume); +#endif + #endif /* __USBMIXER_H */ diff --git a/sound/usb/mixer_quirks.c b/sound/usb/mixer_quirks.c index f4b12c216f1..f119a41ed9a 100644 --- a/sound/usb/mixer_quirks.c +++ b/sound/usb/mixer_quirks.c @@ -600,8 +600,8 @@ static int snd_nativeinstruments_control_get(struct snd_kcontrol *kcontrol, up_read(&mixer->chip->shutdown_rwsem); if (ret < 0) { - snd_printk(KERN_ERR - "unable to issue vendor read request (ret = %d)", ret); + dev_err(&dev->dev, + "unable to issue vendor read request (ret = %d)", ret); return ret; } @@ -631,8 +631,8 @@ static int snd_nativeinstruments_control_put(struct snd_kcontrol *kcontrol, up_read(&mixer->chip->shutdown_rwsem); if (ret < 0) { - snd_printk(KERN_ERR - "unable to issue vendor write request (ret = %d)", ret); + dev_err(&dev->dev, + "unable to issue vendor write request (ret = %d)", ret); return ret; } @@ -1699,7 +1699,7 @@ void snd_usb_mixer_rc_memory_change(struct usb_mixer_interface *mixer, snd_usb_mixer_notify_id(mixer, mixer->rc_cfg->mute_mixer_id); break; default: - snd_printd(KERN_DEBUG "memory change in unknown unit %d\n", unitid); + usb_audio_dbg(mixer->chip, "memory change in unknown unit %d\n", unitid); break; } } diff --git a/sound/usb/pcm.c b/sound/usb/pcm.c index ca3256d6fde..49de5c1284f 100644 --- a/sound/usb/pcm.c +++ b/sound/usb/pcm.c @@ -166,8 +166,8 @@ static int init_pitch_v1(struct snd_usb_audio *chip, int iface, USB_TYPE_CLASS|USB_RECIP_ENDPOINT|USB_DIR_OUT, UAC_EP_CS_ATTR_PITCH_CONTROL << 8, ep, data, sizeof(data))) < 0) { - snd_printk(KERN_ERR "%d:%d:%d: cannot set enable PITCH\n", - dev->devnum, iface, ep); + usb_audio_err(chip, "%d:%d: cannot set enable PITCH\n", + iface, ep); return err; } @@ -187,8 +187,8 @@ static int init_pitch_v2(struct snd_usb_audio *chip, int iface, USB_TYPE_CLASS | USB_RECIP_ENDPOINT | USB_DIR_OUT, UAC2_EP_CS_PITCH << 8, 0, data, sizeof(data))) < 0) { - snd_printk(KERN_ERR "%d:%d:%d: cannot set enable PITCH (v2)\n", - dev->devnum, iface, fmt->altsetting); + usb_audio_err(chip, "%d:%d: cannot set enable PITCH (v2)\n", + iface, fmt->altsetting); return err; } @@ -226,7 +226,7 @@ static int start_endpoints(struct snd_usb_substream *subs, bool can_sleep) if (!test_and_set_bit(SUBSTREAM_FLAG_DATA_EP_STARTED, &subs->flags)) { struct snd_usb_endpoint *ep = subs->data_endpoint; - snd_printdd(KERN_DEBUG "Starting data EP @%p\n", ep); + dev_dbg(&subs->dev->dev, "Starting data EP @%p\n", ep); ep->data_subs = subs; err = snd_usb_endpoint_start(ep, can_sleep); @@ -247,16 +247,15 @@ static int start_endpoints(struct snd_usb_substream *subs, bool can_sleep) subs->sync_endpoint->altsetting); if (err < 0) { clear_bit(SUBSTREAM_FLAG_SYNC_EP_STARTED, &subs->flags); - snd_printk(KERN_ERR - "%d:%d:%d: cannot set interface (%d)\n", - subs->dev->devnum, + dev_err(&subs->dev->dev, + "%d:%d: cannot set interface (%d)\n", subs->sync_endpoint->iface, subs->sync_endpoint->altsetting, err); return -EIO; } } - snd_printdd(KERN_DEBUG "Starting sync EP @%p\n", ep); + dev_dbg(&subs->dev->dev, "Starting sync EP @%p\n", ep); ep->sync_slave = subs->data_endpoint; err = snd_usb_endpoint_start(ep, can_sleep); @@ -410,8 +409,9 @@ static int set_sync_endpoint(struct snd_usb_substream *subs, if ((get_endpoint(alts, 1)->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) != USB_ENDPOINT_XFER_ISOC || (get_endpoint(alts, 1)->bLength >= USB_DT_ENDPOINT_AUDIO_SIZE && get_endpoint(alts, 1)->bSynchAddress != 0)) { - snd_printk(KERN_ERR "%d:%d:%d : invalid sync pipe. bmAttributes %02x, bLength %d, bSynchAddress %02x\n", - dev->devnum, fmt->iface, fmt->altsetting, + dev_err(&dev->dev, + "%d:%d : invalid sync pipe. bmAttributes %02x, bLength %d, bSynchAddress %02x\n", + fmt->iface, fmt->altsetting, get_endpoint(alts, 1)->bmAttributes, get_endpoint(alts, 1)->bLength, get_endpoint(alts, 1)->bSynchAddress); @@ -421,8 +421,9 @@ static int set_sync_endpoint(struct snd_usb_substream *subs, if (get_endpoint(alts, 0)->bLength >= USB_DT_ENDPOINT_AUDIO_SIZE && ((is_playback && ep != (unsigned int)(get_endpoint(alts, 0)->bSynchAddress | USB_DIR_IN)) || (!is_playback && ep != (unsigned int)(get_endpoint(alts, 0)->bSynchAddress & ~USB_DIR_IN)))) { - snd_printk(KERN_ERR "%d:%d:%d : invalid sync pipe. is_playback %d, ep %02x, bSynchAddress %02x\n", - dev->devnum, fmt->iface, fmt->altsetting, + dev_err(&dev->dev, + "%d:%d : invalid sync pipe. is_playback %d, ep %02x, bSynchAddress %02x\n", + fmt->iface, fmt->altsetting, is_playback, ep, get_endpoint(alts, 0)->bSynchAddress); return -EINVAL; } @@ -469,8 +470,9 @@ static int set_format(struct snd_usb_substream *subs, struct audioformat *fmt) if (subs->interface >= 0 && subs->interface != fmt->iface) { err = usb_set_interface(subs->dev, subs->interface, 0); if (err < 0) { - snd_printk(KERN_ERR "%d:%d:%d: return to setting 0 failed (%d)\n", - dev->devnum, fmt->iface, fmt->altsetting, err); + dev_err(&dev->dev, + "%d:%d: return to setting 0 failed (%d)\n", + fmt->iface, fmt->altsetting, err); return -EIO; } subs->interface = -1; @@ -482,12 +484,13 @@ static int set_format(struct snd_usb_substream *subs, struct audioformat *fmt) subs->altset_idx != fmt->altset_idx) { err = usb_set_interface(dev, fmt->iface, fmt->altsetting); if (err < 0) { - snd_printk(KERN_ERR "%d:%d:%d: usb_set_interface failed (%d)\n", - dev->devnum, fmt->iface, fmt->altsetting, err); + dev_err(&dev->dev, + "%d:%d: usb_set_interface failed (%d)\n", + fmt->iface, fmt->altsetting, err); return -EIO; } - snd_printdd(KERN_INFO "setting usb interface %d:%d\n", - fmt->iface, fmt->altsetting); + dev_dbg(&dev->dev, "setting usb interface %d:%d\n", + fmt->iface, fmt->altsetting); subs->interface = fmt->iface; subs->altset_idx = fmt->altset_idx; @@ -523,20 +526,23 @@ static int set_format(struct snd_usb_substream *subs, struct audioformat *fmt) * - Requested PCM format is not supported. * - Requested sample rate is not supported. */ -static int match_endpoint_audioformats(struct audioformat *fp, - struct audioformat *match, int rate, - snd_pcm_format_t pcm_format) +static int match_endpoint_audioformats(struct snd_usb_substream *subs, + struct audioformat *fp, + struct audioformat *match, int rate, + snd_pcm_format_t pcm_format) { int i; int score = 0; if (fp->channels < 1) { - snd_printdd("%s: (fmt @%p) no channels\n", __func__, fp); + dev_dbg(&subs->dev->dev, + "%s: (fmt @%p) no channels\n", __func__, fp); return 0; } if (!(fp->formats & pcm_format_to_bits(pcm_format))) { - snd_printdd("%s: (fmt @%p) no match for format %d\n", __func__, + dev_dbg(&subs->dev->dev, + "%s: (fmt @%p) no match for format %d\n", __func__, fp, pcm_format); return 0; } @@ -548,7 +554,8 @@ static int match_endpoint_audioformats(struct audioformat *fp, } } if (!score) { - snd_printdd("%s: (fmt @%p) no match for rate %d\n", __func__, + dev_dbg(&subs->dev->dev, + "%s: (fmt @%p) no match for rate %d\n", __func__, fp, rate); return 0; } @@ -556,7 +563,8 @@ static int match_endpoint_audioformats(struct audioformat *fp, if (fp->channels == match->channels) score++; - snd_printdd("%s: (fmt @%p) score %d\n", __func__, fp, score); + dev_dbg(&subs->dev->dev, + "%s: (fmt @%p) score %d\n", __func__, fp, score); return score; } @@ -587,7 +595,8 @@ static int configure_sync_endpoint(struct snd_usb_substream *subs) /* Try to find the best matching audioformat. */ list_for_each_entry(fp, &sync_subs->fmt_list, list) { - int score = match_endpoint_audioformats(fp, subs->cur_audiofmt, + int score = match_endpoint_audioformats(subs, + fp, subs->cur_audiofmt, subs->cur_rate, subs->pcm_format); if (score > cur_score) { @@ -597,7 +606,8 @@ static int configure_sync_endpoint(struct snd_usb_substream *subs) } if (unlikely(sync_fp == NULL)) { - snd_printk(KERN_ERR "%s: no valid audioformat for sync ep %x found\n", + dev_err(&subs->dev->dev, + "%s: no valid audioformat for sync ep %x found\n", __func__, sync_subs->ep_num); return -EINVAL; } @@ -609,7 +619,8 @@ static int configure_sync_endpoint(struct snd_usb_substream *subs) if (sync_fp->channels != subs->channels) { sync_period_bytes = (subs->period_bytes / subs->channels) * sync_fp->channels; - snd_printdd("%s: adjusted sync ep period bytes (%d -> %d)\n", + dev_dbg(&subs->dev->dev, + "%s: adjusted sync ep period bytes (%d -> %d)\n", __func__, subs->period_bytes, sync_period_bytes); } @@ -685,7 +696,8 @@ static int snd_usb_hw_params(struct snd_pcm_substream *substream, fmt = find_format(subs); if (!fmt) { - snd_printd(KERN_DEBUG "cannot set format: format = %#x, rate = %d, channels = %d\n", + dev_dbg(&subs->dev->dev, + "cannot set format: format = %#x, rate = %d, channels = %d\n", subs->pcm_format, subs->cur_rate, subs->channels); return -EINVAL; } @@ -742,7 +754,7 @@ static int snd_usb_pcm_prepare(struct snd_pcm_substream *substream) int ret; if (! subs->cur_audiofmt) { - snd_printk(KERN_ERR "usbaudio: no format is specified!\n"); + dev_err(&subs->dev->dev, "no format is specified!\n"); return -ENXIO; } @@ -1235,7 +1247,8 @@ static void retire_capture_urb(struct snd_usb_substream *subs, for (i = 0; i < urb->number_of_packets; i++) { cp = (unsigned char *)urb->transfer_buffer + urb->iso_frame_desc[i].offset + subs->pkt_offset_adj; if (urb->iso_frame_desc[i].status && printk_ratelimit()) { - snd_printdd(KERN_ERR "frame %d active: %d\n", i, urb->iso_frame_desc[i].status); + dev_dbg(&subs->dev->dev, "frame %d active: %d\n", + i, urb->iso_frame_desc[i].status); // continue; } bytes = urb->iso_frame_desc[i].actual_length; @@ -1245,7 +1258,8 @@ static void retire_capture_urb(struct snd_usb_substream *subs, if (bytes % (runtime->sample_bits >> 3) != 0) { int oldbytes = bytes; bytes = frames * stride; - snd_printdd(KERN_ERR "Corrected urb data len. %d->%d\n", + dev_warn(&subs->dev->dev, + "Corrected urb data len. %d->%d\n", oldbytes, bytes); } /* update the current pointer */ @@ -1488,7 +1502,8 @@ static void retire_playback_urb(struct snd_usb_substream *subs, * on two reads of a counter updated every ms. */ if (abs(est_delay - subs->last_delay) * 1000 > runtime->rate * 2) - snd_printk(KERN_DEBUG "delay: estimated %d, actual %d\n", + dev_dbg(&subs->dev->dev, + "delay: estimated %d, actual %d\n", est_delay, subs->last_delay); if (!subs->running) { diff --git a/sound/usb/quirks.c b/sound/usb/quirks.c index 89730707614..7c57f2268dd 100644 --- a/sound/usb/quirks.c +++ b/sound/usb/quirks.c @@ -110,7 +110,7 @@ static int create_standard_audio_quirk(struct snd_usb_audio *chip, altsd = get_iface_desc(alts); err = snd_usb_parse_audio_interface(chip, altsd->bInterfaceNumber); if (err < 0) { - snd_printk(KERN_ERR "cannot setup if %d: error %d\n", + usb_audio_err(chip, "cannot setup if %d: error %d\n", altsd->bInterfaceNumber, err); return err; } @@ -135,7 +135,7 @@ static int create_fixed_stream_quirk(struct snd_usb_audio *chip, fp = kmemdup(quirk->data, sizeof(*fp), GFP_KERNEL); if (!fp) { - snd_printk(KERN_ERR "cannot memdup\n"); + usb_audio_err(chip, "cannot memdup\n"); return -ENOMEM; } if (fp->nr_rates > MAX_NR_RATES) { @@ -464,7 +464,7 @@ static int create_uaxx_quirk(struct snd_usb_audio *chip, fp->rate_max = fp->rate_min = 96000; break; default: - snd_printk(KERN_ERR "unknown sample rate\n"); + usb_audio_err(chip, "unknown sample rate\n"); kfree(fp); return -ENXIO; } @@ -536,7 +536,7 @@ int snd_usb_create_quirk(struct snd_usb_audio *chip, if (quirk->type < QUIRK_TYPE_COUNT) { return quirk_funcs[quirk->type](chip, iface, driver, quirk); } else { - snd_printd(KERN_ERR "invalid quirk type %d\n", quirk->type); + usb_audio_err(chip, "invalid quirk type %d\n", quirk->type); return -ENXIO; } } @@ -555,18 +555,21 @@ static int snd_usb_extigy_boot_quirk(struct usb_device *dev, struct usb_interfac if (le16_to_cpu(get_cfg_desc(config)->wTotalLength) == EXTIGY_FIRMWARE_SIZE_OLD || le16_to_cpu(get_cfg_desc(config)->wTotalLength) == EXTIGY_FIRMWARE_SIZE_NEW) { - snd_printdd("sending Extigy boot sequence...\n"); + dev_dbg(&dev->dev, "sending Extigy boot sequence...\n"); /* Send message to force it to reconnect with full interface. */ err = snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev,0), 0x10, 0x43, 0x0001, 0x000a, NULL, 0); - if (err < 0) snd_printdd("error sending boot message: %d\n", err); + if (err < 0) + dev_dbg(&dev->dev, "error sending boot message: %d\n", err); err = usb_get_descriptor(dev, USB_DT_DEVICE, 0, &dev->descriptor, sizeof(dev->descriptor)); config = dev->actconfig; - if (err < 0) snd_printdd("error usb_get_descriptor: %d\n", err); + if (err < 0) + dev_dbg(&dev->dev, "error usb_get_descriptor: %d\n", err); err = usb_reset_configuration(dev); - if (err < 0) snd_printdd("error usb_reset_configuration: %d\n", err); - snd_printdd("extigy_boot: new boot length = %d\n", + if (err < 0) + dev_dbg(&dev->dev, "error usb_reset_configuration: %d\n", err); + dev_dbg(&dev->dev, "extigy_boot: new boot length = %d\n", le16_to_cpu(get_cfg_desc(config)->wTotalLength)); return -ENODEV; /* quit this anyway */ } @@ -594,7 +597,7 @@ static int snd_usb_fasttrackpro_boot_quirk(struct usb_device *dev) int err; if (dev->actconfig->desc.bConfigurationValue == 1) { - snd_printk(KERN_INFO "usb-audio: " + dev_info(&dev->dev, "Fast Track Pro switching to config #2\n"); /* This function has to be available by the usb core module. * if it is not avialable the boot quirk has to be left out @@ -603,14 +606,15 @@ static int snd_usb_fasttrackpro_boot_quirk(struct usb_device *dev) */ err = usb_driver_set_configuration(dev, 2); if (err < 0) - snd_printdd("error usb_driver_set_configuration: %d\n", - err); + dev_dbg(&dev->dev, + "error usb_driver_set_configuration: %d\n", + err); /* Always return an error, so that we stop creating a device that will just be destroyed and recreated with a new configuration */ return -ENODEV; } else - snd_printk(KERN_INFO "usb-audio: Fast Track Pro config OK\n"); + dev_info(&dev->dev, "Fast Track Pro config OK\n"); return 0; } @@ -779,11 +783,11 @@ static int snd_usb_mbox2_boot_quirk(struct usb_device *dev) fwsize = le16_to_cpu(get_cfg_desc(config)->wTotalLength); if (fwsize != MBOX2_FIRMWARE_SIZE) { - snd_printk(KERN_ERR "usb-audio: Invalid firmware size=%d.\n", fwsize); + dev_err(&dev->dev, "Invalid firmware size=%d.\n", fwsize); return -ENODEV; } - snd_printd("usb-audio: Sending Digidesign Mbox 2 boot sequence...\n"); + dev_dbg(&dev->dev, "Sending Digidesign Mbox 2 boot sequence...\n"); count = 0; bootresponse[0] = MBOX2_BOOT_LOADING; @@ -794,32 +798,32 @@ static int snd_usb_mbox2_boot_quirk(struct usb_device *dev) 0x85, 0xc0, 0x0001, 0x0000, &bootresponse, 0x0012); if (bootresponse[0] == MBOX2_BOOT_READY) break; - snd_printd("usb-audio: device not ready, resending boot sequence...\n"); + dev_dbg(&dev->dev, "device not ready, resending boot sequence...\n"); count++; } if (bootresponse[0] != MBOX2_BOOT_READY) { - snd_printk(KERN_ERR "usb-audio: Unknown bootresponse=%d, or timed out, ignoring device.\n", bootresponse[0]); + dev_err(&dev->dev, "Unknown bootresponse=%d, or timed out, ignoring device.\n", bootresponse[0]); return -ENODEV; } - snd_printdd("usb-audio: device initialised!\n"); + dev_dbg(&dev->dev, "device initialised!\n"); err = usb_get_descriptor(dev, USB_DT_DEVICE, 0, &dev->descriptor, sizeof(dev->descriptor)); config = dev->actconfig; if (err < 0) - snd_printd("error usb_get_descriptor: %d\n", err); + dev_dbg(&dev->dev, "error usb_get_descriptor: %d\n", err); err = usb_reset_configuration(dev); if (err < 0) - snd_printd("error usb_reset_configuration: %d\n", err); - snd_printdd("mbox2_boot: new boot length = %d\n", + dev_dbg(&dev->dev, "error usb_reset_configuration: %d\n", err); + dev_dbg(&dev->dev, "mbox2_boot: new boot length = %d\n", le16_to_cpu(get_cfg_desc(config)->wTotalLength)); mbox2_setup_48_24_magic(dev); - snd_printk(KERN_INFO "usb-audio: Digidesign Mbox 2: 24bit 48kHz"); + dev_info(&dev->dev, "Digidesign Mbox 2: 24bit 48kHz"); return 0; /* Successful boot */ } @@ -865,7 +869,7 @@ static int quattro_skip_setting_quirk(struct snd_usb_audio *chip, return 1; /* skip this altsetting */ } } - snd_printdd(KERN_INFO + usb_audio_dbg(chip, "using altsetting %d for interface %d config %d\n", altno, iface, chip->setup); return 0; /* keep this altsetting */ @@ -932,7 +936,7 @@ static int fasttrackpro_skip_setting_quirk(struct snd_usb_audio *chip, return 1; } - snd_printdd(KERN_INFO + usb_audio_dbg(chip, "using altsetting %d for interface %d config %d\n", altno, iface, chip->setup); return 0; /* keep this altsetting */ diff --git a/sound/usb/stream.c b/sound/usb/stream.c index 2fb71be5e10..310a3822d2b 100644 --- a/sound/usb/stream.c +++ b/sound/usb/stream.c @@ -411,10 +411,9 @@ static int parse_uac_endpoint_attributes(struct snd_usb_audio *chip, if (!csep || csep->bLength < 7 || csep->bDescriptorSubtype != UAC_EP_GENERAL) { - snd_printk(KERN_WARNING "%d:%u:%d : no or invalid" - " class specific endpoint descriptor\n", - chip->dev->devnum, iface_no, - altsd->bAlternateSetting); + usb_audio_warn(chip, + "%u:%d : no or invalid class specific endpoint descriptor\n", + iface_no, altsd->bAlternateSetting); return 0; } @@ -533,8 +532,8 @@ int snd_usb_parse_audio_interface(struct snd_usb_audio *chip, int iface_no) /* get audio formats */ switch (protocol) { default: - snd_printdd(KERN_WARNING "%d:%u:%d: unknown interface protocol %#02x, assuming v1\n", - dev->devnum, iface_no, altno, protocol); + dev_dbg(&dev->dev, "%u:%d: unknown interface protocol %#02x, assuming v1\n", + iface_no, altno, protocol); protocol = UAC_VERSION_1; /* fall through */ @@ -544,14 +543,16 @@ int snd_usb_parse_audio_interface(struct snd_usb_audio *chip, int iface_no) struct uac_input_terminal_descriptor *iterm; if (!as) { - snd_printk(KERN_ERR "%d:%u:%d : UAC_AS_GENERAL descriptor not found\n", - dev->devnum, iface_no, altno); + dev_err(&dev->dev, + "%u:%d : UAC_AS_GENERAL descriptor not found\n", + iface_no, altno); continue; } if (as->bLength < sizeof(*as)) { - snd_printk(KERN_ERR "%d:%u:%d : invalid UAC_AS_GENERAL desc\n", - dev->devnum, iface_no, altno); + dev_err(&dev->dev, + "%u:%d : invalid UAC_AS_GENERAL desc\n", + iface_no, altno); continue; } @@ -574,14 +575,16 @@ int snd_usb_parse_audio_interface(struct snd_usb_audio *chip, int iface_no) snd_usb_find_csint_desc(alts->extra, alts->extralen, NULL, UAC_AS_GENERAL); if (!as) { - snd_printk(KERN_ERR "%d:%u:%d : UAC_AS_GENERAL descriptor not found\n", - dev->devnum, iface_no, altno); + dev_err(&dev->dev, + "%u:%d : UAC_AS_GENERAL descriptor not found\n", + iface_no, altno); continue; } if (as->bLength < sizeof(*as)) { - snd_printk(KERN_ERR "%d:%u:%d : invalid UAC_AS_GENERAL desc\n", - dev->devnum, iface_no, altno); + dev_err(&dev->dev, + "%u:%d : invalid UAC_AS_GENERAL desc\n", + iface_no, altno); continue; } @@ -607,8 +610,9 @@ int snd_usb_parse_audio_interface(struct snd_usb_audio *chip, int iface_no) break; } - snd_printk(KERN_ERR "%d:%u:%d : bogus bTerminalLink %d\n", - dev->devnum, iface_no, altno, as->bTerminalLink); + dev_err(&dev->dev, + "%u:%d : bogus bTerminalLink %d\n", + iface_no, altno, as->bTerminalLink); continue; } } @@ -616,14 +620,16 @@ int snd_usb_parse_audio_interface(struct snd_usb_audio *chip, int iface_no) /* get format type */ fmt = snd_usb_find_csint_desc(alts->extra, alts->extralen, NULL, UAC_FORMAT_TYPE); if (!fmt) { - snd_printk(KERN_ERR "%d:%u:%d : no UAC_FORMAT_TYPE desc\n", - dev->devnum, iface_no, altno); + dev_err(&dev->dev, + "%u:%d : no UAC_FORMAT_TYPE desc\n", + iface_no, altno); continue; } if (((protocol == UAC_VERSION_1) && (fmt->bLength < 8)) || ((protocol == UAC_VERSION_2) && (fmt->bLength < 6))) { - snd_printk(KERN_ERR "%d:%u:%d : invalid UAC_FORMAT_TYPE desc\n", - dev->devnum, iface_no, altno); + dev_err(&dev->dev, + "%u:%d : invalid UAC_FORMAT_TYPE desc\n", + iface_no, altno); continue; } @@ -644,7 +650,7 @@ int snd_usb_parse_audio_interface(struct snd_usb_audio *chip, int iface_no) fp = kzalloc(sizeof(*fp), GFP_KERNEL); if (! fp) { - snd_printk(KERN_ERR "cannot malloc\n"); + dev_err(&dev->dev, "cannot malloc\n"); return -ENOMEM; } @@ -707,7 +713,7 @@ int snd_usb_parse_audio_interface(struct snd_usb_audio *chip, int iface_no) chconfig = 0; fp->chmap = convert_chmap(fp->channels, chconfig, protocol); - snd_printdd(KERN_INFO "%d:%u:%d: add audio endpoint %#x\n", dev->devnum, iface_no, altno, fp->endpoint); + dev_dbg(&dev->dev, "%u:%d: add audio endpoint %#x\n", iface_no, altno, fp->endpoint); err = snd_usb_add_audio_stream(chip, stream, fp); if (err < 0) { kfree(fp->rate_table); diff --git a/sound/usb/usbaudio.h b/sound/usb/usbaudio.h index 5d2fe053074..25c4c7e217d 100644 --- a/sound/usb/usbaudio.h +++ b/sound/usb/usbaudio.h @@ -60,6 +60,15 @@ struct snd_usb_audio { struct usb_host_interface *ctrl_intf; /* the audio control interface */ }; +#define usb_audio_err(chip, fmt, args...) \ + dev_err(&(chip)->dev->dev, fmt, ##args) +#define usb_audio_warn(chip, fmt, args...) \ + dev_warn(&(chip)->dev->dev, fmt, ##args) +#define usb_audio_info(chip, fmt, args...) \ + dev_info(&(chip)->dev->dev, fmt, ##args) +#define usb_audio_dbg(chip, fmt, args...) \ + dev_dbg(&(chip)->dev->dev, fmt, ##args) + /* * Information about devices with broken descriptors */ diff --git a/sound/usb/usx2y/us122l.c b/sound/usb/usx2y/us122l.c index 999550bbad4..cf5dc33f4a6 100644 --- a/sound/usb/usx2y/us122l.c +++ b/sound/usb/usx2y/us122l.c @@ -535,7 +535,9 @@ static void snd_us122l_free(struct snd_card *card) snd_us122l_card_used[index] = 0; } -static int usx2y_create_card(struct usb_device *device, struct snd_card **cardp) +static int usx2y_create_card(struct usb_device *device, + struct usb_interface *intf, + struct snd_card **cardp) { int dev; struct snd_card *card; @@ -546,8 +548,8 @@ static int usx2y_create_card(struct usb_device *device, struct snd_card **cardp) break; if (dev >= SNDRV_CARDS) return -ENODEV; - err = snd_card_create(index[dev], id[dev], THIS_MODULE, - sizeof(struct us122l), &card); + err = snd_card_new(&intf->dev, index[dev], id[dev], THIS_MODULE, + sizeof(struct us122l), &card); if (err < 0) return err; snd_us122l_card_used[US122L(card)->card_index = dev] = 1; @@ -578,11 +580,10 @@ static int us122l_usb_probe(struct usb_interface *intf, struct snd_card *card; int err; - err = usx2y_create_card(device, &card); + err = usx2y_create_card(device, intf, &card); if (err < 0) return err; - snd_card_set_dev(card, &intf->dev); if (!us122l_create_card(card)) { snd_card_free(card); return -EINVAL; diff --git a/sound/usb/usx2y/usbusx2y.c b/sound/usb/usx2y/usbusx2y.c index 5a51b18c50f..91e0e2a4808 100644 --- a/sound/usb/usx2y/usbusx2y.c +++ b/sound/usb/usx2y/usbusx2y.c @@ -332,7 +332,9 @@ static struct usb_device_id snd_usX2Y_usb_id_table[] = { { /* terminator */ } }; -static int usX2Y_create_card(struct usb_device *device, struct snd_card **cardp) +static int usX2Y_create_card(struct usb_device *device, + struct usb_interface *intf, + struct snd_card **cardp) { int dev; struct snd_card * card; @@ -343,15 +345,15 @@ static int usX2Y_create_card(struct usb_device *device, struct snd_card **cardp) break; if (dev >= SNDRV_CARDS) return -ENODEV; - err = snd_card_create(index[dev], id[dev], THIS_MODULE, - sizeof(struct usX2Ydev), &card); + err = snd_card_new(&intf->dev, index[dev], id[dev], THIS_MODULE, + sizeof(struct usX2Ydev), &card); if (err < 0) return err; snd_usX2Y_card_used[usX2Y(card)->card_index = dev] = 1; card->private_free = snd_usX2Y_card_private_free; usX2Y(card)->dev = device; init_waitqueue_head(&usX2Y(card)->prepare_wait_queue); - mutex_init(&usX2Y(card)->prepare_mutex); + mutex_init(&usX2Y(card)->pcm_mutex); INIT_LIST_HEAD(&usX2Y(card)->midi_list); strcpy(card->driver, "USB "NAME_ALLCAPS""); sprintf(card->shortname, "TASCAM "NAME_ALLCAPS""); @@ -382,10 +384,9 @@ static int usX2Y_usb_probe(struct usb_device *device, le16_to_cpu(device->descriptor.idProduct) != USB_ID_US428)) return -EINVAL; - err = usX2Y_create_card(device, &card); + err = usX2Y_create_card(device, intf, &card); if (err < 0) return err; - snd_card_set_dev(card, &intf->dev); if ((err = usX2Y_hwdep_new(card, device)) < 0 || (err = snd_card_register(card)) < 0) { snd_card_free(card); diff --git a/sound/usb/usx2y/usbusx2y.h b/sound/usb/usx2y/usbusx2y.h index e43c0a86441..6ae6b080693 100644 --- a/sound/usb/usx2y/usbusx2y.h +++ b/sound/usb/usx2y/usbusx2y.h @@ -36,7 +36,7 @@ struct usX2Ydev { unsigned int rate, format; int chip_status; - struct mutex prepare_mutex; + struct mutex pcm_mutex; struct us428ctls_sharedmem *us428ctls_sharedmem; int wait_iso_frame; wait_queue_head_t us428ctls_wait_queue_head; diff --git a/sound/usb/usx2y/usbusx2yaudio.c b/sound/usb/usx2y/usbusx2yaudio.c index 6234a51625b..a63330dd140 100644 --- a/sound/usb/usx2y/usbusx2yaudio.c +++ b/sound/usb/usx2y/usbusx2yaudio.c @@ -752,36 +752,44 @@ static int snd_usX2Y_pcm_hw_params(struct snd_pcm_substream *substream, unsigned int rate = params_rate(hw_params); snd_pcm_format_t format = params_format(hw_params); struct snd_card *card = substream->pstr->pcm->card; - struct list_head *list; + struct usX2Ydev *dev = usX2Y(card); + int i; + mutex_lock(&usX2Y(card)->pcm_mutex); snd_printdd("snd_usX2Y_hw_params(%p, %p)\n", substream, hw_params); - // all pcm substreams off one usX2Y have to operate at the same rate & format - list_for_each(list, &card->devices) { - struct snd_device *dev; - struct snd_pcm *pcm; - int s; - dev = snd_device(list); - if (dev->type != SNDRV_DEV_PCM) + /* all pcm substreams off one usX2Y have to operate at the same + * rate & format + */ + for (i = 0; i < dev->pcm_devs * 2; i++) { + struct snd_usX2Y_substream *subs = dev->subs[i]; + struct snd_pcm_substream *test_substream; + + if (!subs) + continue; + test_substream = subs->pcm_substream; + if (!test_substream || test_substream == substream || + !test_substream->runtime) continue; - pcm = dev->device_data; - for (s = 0; s < 2; ++s) { - struct snd_pcm_substream *test_substream; - test_substream = pcm->streams[s].substream; - if (test_substream && test_substream != substream && - test_substream->runtime && - ((test_substream->runtime->format && - test_substream->runtime->format != format) || - (test_substream->runtime->rate && - test_substream->runtime->rate != rate))) - return -EINVAL; + if ((test_substream->runtime->format && + test_substream->runtime->format != format) || + (test_substream->runtime->rate && + test_substream->runtime->rate != rate)) { + err = -EINVAL; + goto error; } } - if (0 > (err = snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params)))) { + + err = snd_pcm_lib_malloc_pages(substream, + params_buffer_bytes(hw_params)); + if (err < 0) { snd_printk(KERN_ERR "snd_pcm_lib_malloc_pages(%p, %i) returned %i\n", substream, params_buffer_bytes(hw_params), err); - return err; + goto error; } - return 0; + + error: + mutex_unlock(&usX2Y(card)->pcm_mutex); + return err; } /* @@ -791,7 +799,7 @@ static int snd_usX2Y_pcm_hw_free(struct snd_pcm_substream *substream) { struct snd_pcm_runtime *runtime = substream->runtime; struct snd_usX2Y_substream *subs = runtime->private_data; - mutex_lock(&subs->usX2Y->prepare_mutex); + mutex_lock(&subs->usX2Y->pcm_mutex); snd_printdd("snd_usX2Y_hw_free(%p)\n", substream); if (SNDRV_PCM_STREAM_PLAYBACK == substream->stream) { @@ -812,7 +820,7 @@ static int snd_usX2Y_pcm_hw_free(struct snd_pcm_substream *substream) usX2Y_urbs_release(subs); } } - mutex_unlock(&subs->usX2Y->prepare_mutex); + mutex_unlock(&subs->usX2Y->pcm_mutex); return snd_pcm_lib_free_pages(substream); } /* @@ -829,7 +837,7 @@ static int snd_usX2Y_pcm_prepare(struct snd_pcm_substream *substream) int err = 0; snd_printdd("snd_usX2Y_pcm_prepare(%p)\n", substream); - mutex_lock(&usX2Y->prepare_mutex); + mutex_lock(&usX2Y->pcm_mutex); usX2Y_subs_prepare(subs); // Start hardware streams // SyncStream first.... @@ -849,7 +857,7 @@ static int snd_usX2Y_pcm_prepare(struct snd_pcm_substream *substream) err = usX2Y_urbs_start(subs); up_prepare_mutex: - mutex_unlock(&usX2Y->prepare_mutex); + mutex_unlock(&usX2Y->pcm_mutex); return err; } diff --git a/sound/usb/usx2y/usx2yhwdeppcm.c b/sound/usb/usx2y/usx2yhwdeppcm.c index 814d0e887c6..90766a92e7f 100644 --- a/sound/usb/usx2y/usx2yhwdeppcm.c +++ b/sound/usb/usx2y/usx2yhwdeppcm.c @@ -358,7 +358,7 @@ static int snd_usX2Y_usbpcm_hw_free(struct snd_pcm_substream *substream) struct snd_pcm_runtime *runtime = substream->runtime; struct snd_usX2Y_substream *subs = runtime->private_data, *cap_subs2 = subs->usX2Y->subs[SNDRV_PCM_STREAM_CAPTURE + 2]; - mutex_lock(&subs->usX2Y->prepare_mutex); + mutex_lock(&subs->usX2Y->pcm_mutex); snd_printdd("snd_usX2Y_usbpcm_hw_free(%p)\n", substream); if (SNDRV_PCM_STREAM_PLAYBACK == substream->stream) { @@ -387,7 +387,7 @@ static int snd_usX2Y_usbpcm_hw_free(struct snd_pcm_substream *substream) usX2Y_usbpcm_urbs_release(cap_subs2); } } - mutex_unlock(&subs->usX2Y->prepare_mutex); + mutex_unlock(&subs->usX2Y->pcm_mutex); return snd_pcm_lib_free_pages(substream); } @@ -493,7 +493,7 @@ static int snd_usX2Y_usbpcm_prepare(struct snd_pcm_substream *substream) memset(usX2Y->hwdep_pcm_shm, 0, sizeof(struct snd_usX2Y_hwdep_pcm_shm)); } - mutex_lock(&usX2Y->prepare_mutex); + mutex_lock(&usX2Y->pcm_mutex); usX2Y_subs_prepare(subs); // Start hardware streams // SyncStream first.... @@ -534,7 +534,7 @@ static int snd_usX2Y_usbpcm_prepare(struct snd_pcm_substream *substream) usX2Y->hwdep_pcm_shm->capture_iso_start = -1; up_prepare_mutex: - mutex_unlock(&usX2Y->prepare_mutex); + mutex_unlock(&usX2Y->pcm_mutex); return err; } @@ -600,59 +600,30 @@ static struct snd_pcm_ops snd_usX2Y_usbpcm_ops = }; -static int usX2Y_pcms_lock_check(struct snd_card *card) +static int usX2Y_pcms_busy_check(struct snd_card *card) { - struct list_head *list; - struct snd_device *dev; - struct snd_pcm *pcm; - int err = 0; - list_for_each(list, &card->devices) { - dev = snd_device(list); - if (dev->type != SNDRV_DEV_PCM) - continue; - pcm = dev->device_data; - mutex_lock(&pcm->open_mutex); - } - list_for_each(list, &card->devices) { - int s; - dev = snd_device(list); - if (dev->type != SNDRV_DEV_PCM) - continue; - pcm = dev->device_data; - for (s = 0; s < 2; ++s) { - struct snd_pcm_substream *substream; - substream = pcm->streams[s].substream; - if (substream && SUBSTREAM_BUSY(substream)) - err = -EBUSY; - } - } - return err; -} - + struct usX2Ydev *dev = usX2Y(card); + int i; -static void usX2Y_pcms_unlock(struct snd_card *card) -{ - struct list_head *list; - struct snd_device *dev; - struct snd_pcm *pcm; - list_for_each(list, &card->devices) { - dev = snd_device(list); - if (dev->type != SNDRV_DEV_PCM) - continue; - pcm = dev->device_data; - mutex_unlock(&pcm->open_mutex); + for (i = 0; i < dev->pcm_devs * 2; i++) { + struct snd_usX2Y_substream *subs = dev->subs[i]; + if (subs && subs->pcm_substream && + SUBSTREAM_BUSY(subs->pcm_substream)) + return -EBUSY; } + return 0; } - static int snd_usX2Y_hwdep_pcm_open(struct snd_hwdep *hw, struct file *file) { - // we need to be the first struct snd_card *card = hw->card; - int err = usX2Y_pcms_lock_check(card); - if (0 == err) + int err; + + mutex_lock(&usX2Y(card)->pcm_mutex); + err = usX2Y_pcms_busy_check(card); + if (!err) usX2Y(card)->chip_status |= USX2Y_STAT_CHIP_MMAP_PCM_URBS; - usX2Y_pcms_unlock(card); + mutex_unlock(&usX2Y(card)->pcm_mutex); return err; } @@ -660,10 +631,13 @@ static int snd_usX2Y_hwdep_pcm_open(struct snd_hwdep *hw, struct file *file) static int snd_usX2Y_hwdep_pcm_release(struct snd_hwdep *hw, struct file *file) { struct snd_card *card = hw->card; - int err = usX2Y_pcms_lock_check(card); - if (0 == err) + int err; + + mutex_lock(&usX2Y(card)->pcm_mutex); + err = usX2Y_pcms_busy_check(card); + if (!err) usX2Y(hw->card)->chip_status &= ~USX2Y_STAT_CHIP_MMAP_PCM_URBS; - usX2Y_pcms_unlock(card); + mutex_unlock(&usX2Y(card)->pcm_mutex); return err; } |