sound updates for 5.12

A relatively calm release at this time, and no massive code changes
 are found in the stats, while a wide range of code refactoring and
 cleanup have been done.
 
 Note that this update includes the tree-wide trivial changes for
 dropping the return value from ISA remove callbacks, too.
 
 Below lists up some highlight:
 
 * ALSA Core:
 - Support for the software jack injection via debugfs
 - Fixes for sync_stop PCM operations
 
 * HD-audio and USB-audio:
 - A few usual HD-audio device quirks
 - Updates for Tegra HD-audio
 - More quirks for Pioneer and other USB-audio devices
 - Stricter state checks at USB-audio disconnection
 
 * ASoC:
 - Continued code refactoring, cleanup and fixes in ASoC core API
 - A KUnit testsuite for the topology code
 - Lots of ASoC Intel driver Realtek codec updates, quirk additions and
   fixes
 - Support for Ingenic JZ4760(B), Intel AlderLake-P, DT configured
   nVidia cards, Qualcomm lpass-rx-macro and lpass-tx-macro
 - Removal of obsolete SIRF prima/atlas, Txx9 and ZTE zx drivers
 
 * Others:
 - Drop return value from ISA driver remove callback
 - Cleanup with DIV_ROUND_UP() macro
 - FireWire updates, HDSP output loopback support
 -----BEGIN PGP SIGNATURE-----
 
 iQJCBAABCAAsFiEEIXTw5fNLNI7mMiVaLtJE4w1nLE8FAmAvhXoOHHRpd2FpQHN1
 c2UuZGUACgkQLtJE4w1nLE9XGA/+MmRBSMipHpZBj6AB2mxbsam2dbPHuycKz1Dd
 7W4Rx9QdQcCF2BQ909HKSaE76mTrxkaYc3Ubn8uyfeKz7tB9YpqY5HfIiWRz8iyU
 FJK/INbkeunLhS61wjKbb8x+pP5M2ZXBTGSRkgVROCgMq4osM+J17c/5wSPE5BoG
 BGTXUk8LcDE+Iq/6bt2OrXgEBhHCXw7eB/wRWw5v0sIc2cnrexXYUZmHaRj1L3Dd
 ukpteFEmemOdbowitV+GPSlsnrCD6zselYWms/MLvwLMvTqT4W2SRfsGF5VvGKJC
 AJsHTWQ5JRKfLt2LJkDs3ymHrKdhnDCWjCUAFNEXd7IRG0Qsk/S+wXsyl3oEhgeQ
 ND9RoE5pSGG/2Y3Zvt3OevAuVenzQW04/2hFIoAyQg5s/DSom8lNtAsmXkc5dWNI
 GZJHnvPrdKgzZ0lI9TAbG0v48lnyiQB2sD0FAatWpv3NHcRt0u3fowZgc6Bb3JHK
 7cv3upNa1CY7mDSYiT0k3sIHJMrCdoWTPSiewEOxrmLFM1r5O5gHX3dpXhSfh5WJ
 MI1a93N7sK6WHm6KpeNcHnjrIbP14vOjatOHN+0stuFhLcOGygDX/L0Lu07+15aJ
 Fxicp23RRwNsb57JcTZTw/+nZhrndSeG3eHYZG2QvQJCv6Ph1tEJ+WAM+tlj85GT
 feGP0jg=
 =QgvS
 -----END PGP SIGNATURE-----

Merge tag 'sound-5.12-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound

Pull sound updates from Takashi Iwai:
 "A relatively calm release at this time, and no massive code changes
  are found in the stats, while a wide range of code refactoring and
  cleanup have been done.

  Note that this update includes the tree-wide trivial changes for
  dropping the return value from ISA remove callbacks, too.

  Below lists up some highlight:

  ALSA Core:
   - Support for the software jack injection via debugfs
   - Fixes for sync_stop PCM operations

  HD-audio and USB-audio:
   - A few usual HD-audio device quirks
   - Updates for Tegra HD-audio
   - More quirks for Pioneer and other USB-audio devices
   - Stricter state checks at USB-audio disconnection

  ASoC:
   - Continued code refactoring, cleanup and fixes in ASoC core API
   - A KUnit testsuite for the topology code
   - Lots of ASoC Intel driver Realtek codec updates, quirk additions
     and fixes
   - Support for Ingenic JZ4760(B), Intel AlderLake-P, DT configured
     nVidia cards, Qualcomm lpass-rx-macro and lpass-tx-macro
   - Removal of obsolete SIRF prima/atlas, Txx9 and ZTE zx drivers

  Others:
   - Drop return value from ISA driver remove callback
   - Cleanup with DIV_ROUND_UP() macro
   - FireWire updates, HDSP output loopback support"

* tag 'sound-5.12-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound: (322 commits)
  ALSA: hda: intel-dsp-config: add Alder Lake support
  ASoC: soc-pcm: fix hw param limits calculation for multi-DAI
  ASoC: Intel: bytcr_rt5640: Add quirk for the Acer One S1002 tablet
  ASoC: Intel: bytcr_rt5651: Add quirk for the Jumper EZpad 7 tablet
  ASoC: Intel: bytcr_rt5640: Add quirk for the Voyo Winpad A15 tablet
  ASoC: Intel: bytcr_rt5640: Add quirk for the Estar Beauty HD MID 7316R tablet
  ASoC: soc-pcm: fix hwparams min/max init for dpcm
  ALSA: hda/realtek: Quirk for HP Spectre x360 14 amp setup
  ALSA: usb-audio: Add implicit fb quirk for BOSS GP-10
  ALSA: hda: Add another CometLake-H PCI ID
  ASoC: soc-pcm: add soc_pcm_hw_update_format()
  ASoC: soc-pcm: add soc_pcm_hw_update_chan()
  ASoC: soc-pcm: add soc_pcm_hw_update_rate()
  ASoC: wm_adsp: Remove unused control callback structure
  ASoC: SOF: relax ABI checks and avoid unnecessary warnings
  ASoC: codecs: lpass-tx-macro: add dapm widgets and route
  ASoC: codecs: lpass-tx-macro: add support for lpass tx macro
  ASoC: qcom: dt-bindings: add bindings for lpass tx macro codec
  ASoC: codecs: lpass-rx-macro: add iir widgets
  ASoC: codecs: lpass-rx-macro: add dapm widgets and route
  ...
This commit is contained in:
Linus Torvalds 2021-02-21 14:21:35 -08:00
commit 10e2ec8ede
470 changed files with 12558 additions and 6663 deletions

View File

@ -71,9 +71,6 @@ properties:
description: CPU to Codec rate channels. description: CPU to Codec rate channels.
$ref: /schemas/types.yaml#/definitions/uint32 $ref: /schemas/types.yaml#/definitions/uint32
required:
- remote-endpoint
ports: ports:
description: multi OF-Graph subnode description: multi OF-Graph subnode
type: object type: object

View File

@ -15,9 +15,14 @@ properties:
compatible: compatible:
oneOf: oneOf:
- const: ingenic,jz4770-codec - enum:
- const: ingenic,jz4725b-codec - ingenic,jz4770-codec
- const: ingenic,jz4740-codec - ingenic,jz4760-codec
- ingenic,jz4725b-codec
- ingenic,jz4740-codec
- items:
- const: ingenic,jz4760b-codec
- const: ingenic,jz4760-codec
reg: reg:
maxItems: 1 maxItems: 1

View File

@ -18,6 +18,7 @@ properties:
enum: enum:
- intel,keembay-i2s - intel,keembay-i2s
- intel,keembay-tdm - intel,keembay-tdm
- intel,keembay-hdmi-i2s
"#sound-dai-cells": "#sound-dai-cells":
const: 0 const: 0
@ -45,6 +46,16 @@ properties:
- const: osc - const: osc
- const: apb_clk - const: apb_clk
dmas:
items:
- description: DMA TX channel
- description: DMA RX channel
dma-names:
items:
- const: tx
- const: rx
required: required:
- compatible - compatible
- "#sound-dai-cells" - "#sound-dai-cells"
@ -70,4 +81,6 @@ examples:
interrupts = <GIC_SPI 120 IRQ_TYPE_LEVEL_HIGH>; interrupts = <GIC_SPI 120 IRQ_TYPE_LEVEL_HIGH>;
clock-names = "osc", "apb_clk"; clock-names = "osc", "apb_clk";
clocks = <&scmi_clk KEEM_BAY_PSS_AUX_I2S3>, <&scmi_clk KEEM_BAY_PSS_I2S3>; clocks = <&scmi_clk KEEM_BAY_PSS_AUX_I2S3>, <&scmi_clk KEEM_BAY_PSS_I2S3>;
dmas = <&axi_dma0 29 &axi_dma0 33>;
dma-names = "tx", "rx";
}; };

View File

@ -23,6 +23,10 @@ properties:
$ref: "/schemas/types.yaml#/definitions/phandle" $ref: "/schemas/types.yaml#/definitions/phandle"
description: The phandle of MT8192 ASoC platform. description: The phandle of MT8192 ASoC platform.
mediatek,hdmi-codec:
$ref: "/schemas/types.yaml#/definitions/phandle"
description: The phandle of HDMI codec.
additionalProperties: false additionalProperties: false
required: required:
@ -35,6 +39,7 @@ examples:
sound: mt8192-sound { sound: mt8192-sound {
compatible = "mediatek,mt8192_mt6359_rt1015_rt5682"; compatible = "mediatek,mt8192_mt6359_rt1015_rt5682";
mediatek,platform = <&afe>; mediatek,platform = <&afe>;
mediatek,hdmi-codec = <&anx_bridge_dp>;
pinctrl-names = "aud_clk_mosi_off", pinctrl-names = "aud_clk_mosi_off",
"aud_clk_mosi_on"; "aud_clk_mosi_on";
pinctrl-0 = <&aud_clk_mosi_off>; pinctrl-0 = <&aud_clk_mosi_off>;

View File

@ -0,0 +1,190 @@
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/sound/nvidia,tegra-audio-graph-card.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Audio Graph based Tegra sound card driver
description: |
This is based on generic audio graph card driver along with additional
customizations for Tegra platforms. It uses the same bindings with
additional standard clock DT bindings required for Tegra.
maintainers:
- Jon Hunter <jonathanh@nvidia.com>
- Sameer Pujar <spujar@nvidia.com>
allOf:
- $ref: audio-graph.yaml#
properties:
compatible:
enum:
- nvidia,tegra210-audio-graph-card
- nvidia,tegra186-audio-graph-card
clocks:
minItems: 2
clock-names:
minItems: 2
items:
- const: pll_a
- const: plla_out0
assigned-clocks:
minItems: 1
maxItems: 3
assigned-clock-parents:
minItems: 1
maxItems: 3
assigned-clock-rates:
minItems: 1
maxItems: 3
iommus:
maxItems: 1
required:
- clocks
- clock-names
- assigned-clocks
- assigned-clock-parents
unevaluatedProperties: false
examples:
- |
#include<dt-bindings/clock/tegra210-car.h>
tegra_sound {
compatible = "nvidia,tegra210-audio-graph-card";
clocks = <&tegra_car TEGRA210_CLK_PLL_A>,
<&tegra_car TEGRA210_CLK_PLL_A_OUT0>;
clock-names = "pll_a", "plla_out0";
assigned-clocks = <&tegra_car TEGRA210_CLK_PLL_A>,
<&tegra_car TEGRA210_CLK_PLL_A_OUT0>,
<&tegra_car TEGRA210_CLK_EXTERN1>;
assigned-clock-parents = <0>, <0>, <&tegra_car TEGRA210_CLK_PLL_A_OUT0>;
assigned-clock-rates = <368640000>, <49152000>, <12288000>;
dais = /* FE */
<&admaif1_port>,
/* Router */
<&xbar_i2s1_port>,
/* I/O DAP Ports */
<&i2s1_port>;
label = "jetson-tx1-ape";
};
// The ports are defined for AHUB and its child devices.
ahub@702d0800 {
compatible = "nvidia,tegra210-ahub";
reg = <0x702d0800 0x800>;
clocks = <&tegra_car TEGRA210_CLK_D_AUDIO>;
clock-names = "ahub";
assigned-clocks = <&tegra_car TEGRA210_CLK_D_AUDIO>;
assigned-clock-parents = <&tegra_car TEGRA210_CLK_PLL_A_OUT0>;
#address-cells = <1>;
#size-cells = <1>;
ranges = <0x702d0000 0x702d0000 0x0000e400>;
ports {
#address-cells = <1>;
#size-cells = <0>;
port@0 {
reg = <0x0>;
xbar_admaif1_ep: endpoint {
remote-endpoint = <&admaif1_ep>;
};
};
// ...
xbar_i2s1_port: port@a {
reg = <0xa>;
xbar_i2s1_ep: endpoint {
remote-endpoint = <&i2s1_cif_ep>;
};
};
};
admaif@702d0000 {
compatible = "nvidia,tegra210-admaif";
reg = <0x702d0000 0x800>;
dmas = <&adma 1>, <&adma 1>,
<&adma 2>, <&adma 2>,
<&adma 3>, <&adma 3>,
<&adma 4>, <&adma 4>,
<&adma 5>, <&adma 5>,
<&adma 6>, <&adma 6>,
<&adma 7>, <&adma 7>,
<&adma 8>, <&adma 8>,
<&adma 9>, <&adma 9>,
<&adma 10>, <&adma 10>;
dma-names = "rx1", "tx1",
"rx2", "tx2",
"rx3", "tx3",
"rx4", "tx4",
"rx5", "tx5",
"rx6", "tx6",
"rx7", "tx7",
"rx8", "tx8",
"rx9", "tx9",
"rx10", "tx10";
ports {
#address-cells = <1>;
#size-cells = <0>;
admaif1_port: port@0 {
reg = <0x0>;
admaif1_ep: endpoint {
remote-endpoint = <&xbar_admaif1_ep>;
};
};
// More ADMAIF ports to follow
};
};
i2s@702d1000 {
compatible = "nvidia,tegra210-i2s";
clocks = <&tegra_car TEGRA210_CLK_I2S0>;
clock-names = "i2s";
assigned-clocks = <&tegra_car TEGRA210_CLK_I2S0>;
assigned-clock-parents = <&tegra_car TEGRA210_CLK_PLL_A_OUT0>;
assigned-clock-rates = <1536000>;
reg = <0x702d1000 0x100>;
ports {
#address-cells = <1>;
#size-cells = <0>;
port@0 {
reg = <0x0>;
i2s1_cif_ep: endpoint {
remote-endpoint = <&xbar_i2s1_ep>;
};
};
i2s1_port: port@1 {
reg = <0x1>;
i2s1_dap: endpoint {
dai-format = "i2s";
};
};
};
};
};
...

View File

@ -17,6 +17,9 @@ maintainers:
- Jon Hunter <jonathanh@nvidia.com> - Jon Hunter <jonathanh@nvidia.com>
- Sameer Pujar <spujar@nvidia.com> - Sameer Pujar <spujar@nvidia.com>
allOf:
- $ref: audio-graph-port.yaml#
properties: properties:
$nodename: $nodename:
pattern: "^dspk@[0-9a-f]*$" pattern: "^dspk@[0-9a-f]*$"
@ -55,6 +58,19 @@ properties:
The name can be "DSPK1" or "DSPKx", where x depends on the maximum The name can be "DSPK1" or "DSPKx", where x depends on the maximum
available instances on a Tegra SoC. available instances on a Tegra SoC.
ports:
type: object
properties:
port@0:
description: |
DSPK ACIF (Audio Client Interface) port connected to the
corresponding AHUB (Audio Hub) ACIF port.
port@1:
description: |
DSPK DAP (Digital Audio Port) interface which can be connected
to external audio codec for playback.
required: required:
- compatible - compatible
- reg - reg
@ -64,7 +80,7 @@ required:
- assigned-clock-parents - assigned-clock-parents
- sound-name-prefix - sound-name-prefix
additionalProperties: false unevaluatedProperties: false
examples: examples:
- | - |

View File

@ -17,6 +17,9 @@ maintainers:
- Jon Hunter <jonathanh@nvidia.com> - Jon Hunter <jonathanh@nvidia.com>
- Sameer Pujar <spujar@nvidia.com> - Sameer Pujar <spujar@nvidia.com>
allOf:
- $ref: audio-graph-port.yaml#
properties: properties:
$nodename: $nodename:
pattern: "^admaif@[0-9a-f]*$" pattern: "^admaif@[0-9a-f]*$"
@ -37,6 +40,14 @@ properties:
dma-names: true dma-names: true
ports:
description: |
Contains list of ACIF (Audio CIF) port nodes for ADMAIF channels.
The number of port nodes depends on the number of ADMAIF channels
that SoC may have. These are interfaced with respective ACIF ports
in AHUB (Audio Hub). Each port is capable of data transfers in
both directions.
if: if:
properties: properties:
compatible: compatible:
@ -81,7 +92,7 @@ required:
- dmas - dmas
- dma-names - dma-names
additionalProperties: false unevaluatedProperties: false
examples: examples:
- | - |

View File

@ -17,6 +17,9 @@ maintainers:
- Jon Hunter <jonathanh@nvidia.com> - Jon Hunter <jonathanh@nvidia.com>
- Sameer Pujar <spujar@nvidia.com> - Sameer Pujar <spujar@nvidia.com>
allOf:
- $ref: audio-graph-port.yaml#
properties: properties:
$nodename: $nodename:
pattern: "^ahub@[0-9a-f]*$" pattern: "^ahub@[0-9a-f]*$"
@ -56,6 +59,13 @@ properties:
ranges: true ranges: true
ports:
description: |
Contains list of ACIF (Audio CIF) port nodes for AHUB (Audio Hub).
These are connected to ACIF interfaces of AHUB clients. Thus the
number of port nodes depend on the number of clients that AHUB may
have depending on the SoC revision.
required: required:
- compatible - compatible
- reg - reg
@ -67,8 +77,7 @@ required:
- "#size-cells" - "#size-cells"
- ranges - ranges
additionalProperties: unevaluatedProperties: false
type: object
examples: examples:
- | - |

View File

@ -16,6 +16,9 @@ maintainers:
- Jon Hunter <jonathanh@nvidia.com> - Jon Hunter <jonathanh@nvidia.com>
- Sameer Pujar <spujar@nvidia.com> - Sameer Pujar <spujar@nvidia.com>
allOf:
- $ref: audio-graph-port.yaml#
properties: properties:
$nodename: $nodename:
pattern: "^dmic@[0-9a-f]*$" pattern: "^dmic@[0-9a-f]*$"
@ -56,6 +59,19 @@ properties:
The name can be "DMIC1" or "DMIC2" ... "DMICx", where x depends The name can be "DMIC1" or "DMIC2" ... "DMICx", where x depends
on the maximum available instances on a Tegra SoC. on the maximum available instances on a Tegra SoC.
ports:
type: object
properties:
port@0:
description: |
DMIC ACIF (Audio Client Interface) port connected to the
corresponding AHUB (Audio Hub) ACIF port.
port@1:
description: |
DMIC DAP (Digital Audio Port) interface which can be connected
to external audio codec for capture.
required: required:
- compatible - compatible
- reg - reg
@ -64,7 +80,7 @@ required:
- assigned-clocks - assigned-clocks
- assigned-clock-parents - assigned-clock-parents
additionalProperties: false unevaluatedProperties: false
examples: examples:
- | - |

View File

@ -16,6 +16,9 @@ maintainers:
- Jon Hunter <jonathanh@nvidia.com> - Jon Hunter <jonathanh@nvidia.com>
- Sameer Pujar <spujar@nvidia.com> - Sameer Pujar <spujar@nvidia.com>
allOf:
- $ref: audio-graph-port.yaml#
properties: properties:
$nodename: $nodename:
pattern: "^i2s@[0-9a-f]*$" pattern: "^i2s@[0-9a-f]*$"
@ -74,6 +77,19 @@ properties:
The name can be "I2S1" or "I2S2" ... "I2Sx", where x depends The name can be "I2S1" or "I2S2" ... "I2Sx", where x depends
on the maximum available instances on a Tegra SoC. on the maximum available instances on a Tegra SoC.
ports:
type: object
properties:
port@0:
description: |
I2S ACIF (Audio Client Interface) port connected to the
corresponding AHUB (Audio Hub) ACIF port.
port@1:
description: |
I2S DAP (Digital Audio Port) interface which can be connected
to external audio codec for playback or capture.
required: required:
- compatible - compatible
- reg - reg
@ -82,7 +98,7 @@ required:
- assigned-clocks - assigned-clocks
- assigned-clock-parents - assigned-clock-parents
additionalProperties: false unevaluatedProperties: false
examples: examples:
- | - |

View File

@ -0,0 +1,62 @@
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/sound/qcom,lpass-rx-macro.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: LPASS(Low Power Audio Subsystem) RX Macro audio codec DT bindings
maintainers:
- Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
properties:
compatible:
const: qcom,sm8250-lpass-rx-macro
reg:
maxItems: 1
"#sound-dai-cells":
const: 1
'#clock-cells':
const: 0
clocks:
maxItems: 5
clock-names:
items:
- const: mclk
- const: npl
- const: macro
- const: dcodec
- const: fsgen
clock-output-names:
items:
- const: mclk
required:
- compatible
- reg
- "#sound-dai-cells"
additionalProperties: false
examples:
- |
#include <dt-bindings/sound/qcom,q6afe.h>
codec@3200000 {
compatible = "qcom,sm8250-lpass-rx-macro";
reg = <0x3200000 0x1000>;
#sound-dai-cells = <1>;
#clock-cells = <0>;
clocks = <&audiocc 0>,
<&audiocc 1>,
<&q6afecc LPASS_HW_MACRO_VOTE LPASS_CLK_ATTRIBUTE_COUPLE_NO>,
<&q6afecc LPASS_HW_DCODEC_VOTE LPASS_CLK_ATTRIBUTE_COUPLE_NO>,
<&vamacro>;
clock-names = "mclk", "npl", "macro", "dcodec", "fsgen";
clock-output-names = "mclk";
};

View File

@ -0,0 +1,67 @@
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/sound/qcom,lpass-tx-macro.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: LPASS(Low Power Audio Subsystem) TX Macro audio codec DT bindings
maintainers:
- Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
properties:
compatible:
const: qcom,sm8250-lpass-tx-macro
reg:
maxItems: 1
"#sound-dai-cells":
const: 1
'#clock-cells':
const: 0
clocks:
maxItems: 5
clock-names:
items:
- const: mclk
- const: npl
- const: macro
- const: dcodec
- const: fsgen
clock-output-names:
items:
- const: mclk
qcom,dmic-sample-rate:
description: dmic sample rate
$ref: /schemas/types.yaml#/definitions/uint32
required:
- compatible
- reg
- "#sound-dai-cells"
additionalProperties: false
examples:
- |
#include <dt-bindings/sound/qcom,q6afe.h>
codec@3220000 {
compatible = "qcom,sm8250-lpass-tx-macro";
reg = <0x3220000 0x1000>;
#sound-dai-cells = <1>;
#clock-cells = <0>;
clocks = <&aoncc 0>,
<&aoncc 1>,
<&q6afecc LPASS_HW_MACRO_VOTE LPASS_CLK_ATTRIBUTE_COUPLE_NO>,
<&q6afecc LPASS_HW_DCODEC_VOTE LPASS_CLK_ATTRIBUTE_COUPLE_NO>,
<&vamacro>;
clock-names = "mclk", "npl", "macro", "dcodec", "fsgen";
clock-output-names = "mclk";
qcom,dmic-sample-rate = <600000>;
};

View File

@ -404,7 +404,7 @@ examples:
/* DAI base */ /* DAI base */
rcar_sound,dai { rcar_sound,dai {
dai0 { dai0 {
playback = <&ssi5 &src5>; playback = <&ssi5>, <&src5>;
capture = <&ssi6>; capture = <&ssi6>;
}; };
dai1 { dai1 {
@ -430,8 +430,8 @@ examples:
bitclock-master = <&rsnd_endpoint0>; bitclock-master = <&rsnd_endpoint0>;
frame-master = <&rsnd_endpoint0>; frame-master = <&rsnd_endpoint0>;
playback = <&ssi0 &src0 &dvc0>; playback = <&ssi0>, <&src0>, <&dvc0>;
capture = <&ssi1 &src1 &dvc1>; capture = <&ssi1>, <&src1>, <&dvc1>;
}; };
}; };
}; };

View File

@ -37,10 +37,21 @@ Optional properties:
- realtek,jd-src - realtek,jd-src
0: No JD is used 0: No JD is used
1: using JD3 as JD source 1: using JD3 as JD source
2: JD source for Intel HDA header
- realtek,ldo1-en-gpios : The GPIO that controls the CODEC's LDO1_EN pin. - realtek,ldo1-en-gpios : The GPIO that controls the CODEC's LDO1_EN pin.
- realtek,reset-gpios : The GPIO that controls the CODEC's RESET pin. - realtek,reset-gpios : The GPIO that controls the CODEC's RESET pin.
- sound-name-prefix: Please refer to name-prefix.txt
- ports: A Codec may have a single or multiple I2S interfaces. These
interfaces on Codec side can be described under 'ports' or 'port'.
When the SoC or host device is connected to multiple interfaces of
the Codec, the connectivity can be described using 'ports' property.
If a single interface is used, then 'port' can be used. The usage
depends on the platform or board design.
Please refer to Documentation/devicetree/bindings/graph.txt
Pins on the device (for linking into audio routes) for RT5659/RT5658: Pins on the device (for linking into audio routes) for RT5659/RT5658:
* DMIC L1 * DMIC L1

View File

@ -1,17 +0,0 @@
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>;
};

View File

@ -1,27 +0,0 @@
* SiRF SoC USP module
Required properties:
- compatible: "sirf,prima2-usp-pcm"
- 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").
- clocks: USP controller clock source
- pinctrl-names: Must contain a "default" entry.
- pinctrl-NNN: One property must exist for each entry in pinctrl-names.
Example:
usp0: usp@b0080000 {
compatible = "sirf,prima2-usp-pcm";
reg = <0xb0080000 0x10000>;
clocks = <&clks 28>;
dmas = <&dmac1 1>, <&dmac1 2>;
dma-names = "rx", "tx";
pinctrl-names = "default";
pinctrl-0 = <&usp0_only_utfs_pins_a>;
};

View File

@ -54,6 +54,10 @@ properties:
resets: resets:
maxItems: 1 maxItems: 1
"#clock-cells":
description: Configure the I2S device as MCLK clock provider.
const: 0
required: required:
- compatible - compatible
- "#sound-dai-cells" - "#sound-dai-cells"

View File

@ -9,6 +9,9 @@ Required properties:
- reg : the I2C address of the device. - reg : the I2C address of the device.
Optional properties: Optional properties:
- clocks : The clock source of the mclk
- spk-mono: This is a boolean property. If present, the SPK_MONO bit - spk-mono: This is a boolean property. If present, the SPK_MONO bit
of R51 (Class D Control 2) gets set, indicating that the speaker is of R51 (Class D Control 2) gets set, indicating that the speaker is
in mono mode. in mono mode.
@ -27,6 +30,7 @@ Example:
wm8962: codec@1a { wm8962: codec@1a {
compatible = "wlf,wm8962"; compatible = "wlf,wm8962";
reg = <0x1a>; reg = <0x1a>;
clocks = <&clks IMX6QDL_CLK_CKO>;
gpio-cfg = < gpio-cfg = <
0x0000 /* 0:Default */ 0x0000 /* 0:Default */

View File

@ -1,30 +0,0 @@
ZTE TDM DAI driver
Required properties:
- compatible : should be one of the following.
* zte,zx296718-tdm
- reg : physical base address of the controller and length of memory mapped
region.
- clocks : Pairs of phandle and specifier referencing the controller's clocks.
- clock-names: "wclk" for the wclk.
"pclk" for the pclk.
-#clock-cells: should be 1.
- zte,tdm-dma-sysctrl : Reference to the sysctrl controller controlling
the dma. includes:
phandle of sysctrl.
register offset in sysctrl for control dma.
mask of the register that be written to sysctrl.
Example:
tdm: tdm@1487000 {
compatible = "zte,zx296718-tdm";
reg = <0x01487000 0x1000>;
clocks = <&audiocrm AUDIO_TDM_WCLK>, <&audiocrm AUDIO_TDM_PCLK>;
clock-names = "wclk", "pclk";
#clock-cells = <1>;
pinctrl-names = "default";
pinctrl-0 = <&tdm_global_pin>;
zte,tdm-dma-sysctrl = <&sysctrl 0x10c 4>;
};

View File

@ -1,24 +0,0 @@
ZTE ZX AUD96P22 Audio Codec
Required properties:
- compatible: Must be "zte,zx-aud96p22"
- #sound-dai-cells: Should be 0
- reg: I2C bus slave address of AUD96P22
Example:
i2c0: i2c@1486000 {
compatible = "zte,zx296718-i2c";
reg = <0x01486000 0x1000>;
interrupts = <GIC_SPI 35 IRQ_TYPE_LEVEL_HIGH>;
#address-cells = <1>;
#size-cells = <0>;
clocks = <&audiocrm AUDIO_I2C0_WCLK>;
clock-frequency = <1600000>;
aud96p22: codec@22 {
compatible = "zte,zx-aud96p22";
#sound-dai-cells = <0>;
reg = <0x22>;
};
};

View File

@ -1,45 +0,0 @@
ZTE ZX296702 I2S controller
Required properties:
- compatible : Must be one of:
"zte,zx296718-i2s", "zte,zx296702-i2s"
"zte,zx296702-i2s"
- reg : Must contain I2S core's registers location and length
- clocks : Pairs of phandle and specifier referencing the controller's clocks.
- clock-names: "wclk" for the wclk, "pclk" for the pclk to the I2S interface.
- dmas: Pairs of phandle and specifier for the DMA channel that is used by
the core. The core expects two dma channels for transmit.
- dma-names : Must be "tx" and "rx"
For more details on the 'dma', 'dma-names', 'clock' and 'clock-names' properties
please check:
* resource-names.txt
* clock/clock-bindings.txt
* dma/dma.txt
Example:
i2s0: i2s@b005000 {
#sound-dai-cells = <0>;
compatible = "zte,zx296718-i2s", "zte,zx296702-i2s";
reg = <0x0b005000 0x1000>;
clocks = <&audiocrm AUDIO_I2S0_WCLK>, <&audiocrm AUDIO_I2S0_PCLK>;
clock-names = "wclk", "pclk";
interrupts = <GIC_SPI 22 IRQ_TYPE_LEVEL_HIGH>;
dmas = <&dma 5>, <&dma 6>;
dma-names = "tx", "rx";
};
sound {
compatible = "simple-audio-card";
simple-audio-card,name = "zx296702_snd";
simple-audio-card,format = "left_j";
simple-audio-card,bitclock-master = <&sndcodec>;
simple-audio-card,frame-master = <&sndcodec>;
sndcpu: simple-audio-card,cpu {
sound-dai = <&i2s0>;
};
sndcodec: simple-audio-card,codec {
sound-dai = <&acodec>;
};
};

View File

@ -1,27 +0,0 @@
ZTE ZX296702 SPDIF controller
Required properties:
- compatible : Must be "zte,zx296702-spdif"
- reg : Must contain SPDIF core's registers location and length
- clocks : Pairs of phandle and specifier referencing the controller's clocks.
- clock-names: "tx" for the clock to the SPDIF interface.
- dmas: Pairs of phandle and specifier for the DMA channel that is used by
the core. The core expects one dma channel for transmit.
- dma-names : Must be "tx"
For more details on the 'dma', 'dma-names', 'clock' and 'clock-names' properties
please check:
* resource-names.txt
* clock/clock-bindings.txt
* dma/dma.txt
Example:
spdif0: spdif0@b004000 {
compatible = "zte,zx296702-spdif";
reg = <0x0b004000 0x1000>;
clocks = <&lsp0clk ZX296702_SPDIF0_DIV>;
clock-names = "tx";
interrupts = <GIC_SPI 21 IRQ_TYPE_LEVEL_HIGH>;
dmas = <&dma 4>;
dma-names = "tx";
};

View File

@ -14,3 +14,4 @@ Designs and Implementations
powersave powersave
oss-emulation oss-emulation
seq-oss seq-oss
jack-injection

View File

@ -0,0 +1,166 @@
============================
ALSA Jack Software Injection
============================
Simple Introduction On Jack Injection
=====================================
Here jack injection means users could inject plugin or plugout events
to the audio jacks through debugfs interface, it is helpful to
validate ALSA userspace changes. For example, we change the audio
profile switching code in the pulseaudio, and we want to verify if the
change works as expected and if the change introduce the regression,
in this case, we could inject plugin or plugout events to an audio
jack or to some audio jacks, we don't need to physically access the
machine and plug/unplug physical devices to the audio jack.
In this design, an audio jack doesn't equal to a physical audio jack.
Sometimes a physical audio jack contains multi functions, and the
ALSA driver creates multi ``jack_kctl`` for a ``snd_jack``, here the
``snd_jack`` represents a physical audio jack and the ``jack_kctl``
represents a function, for example a physical jack has two functions:
headphone and mic_in, the ALSA ASoC driver will build 2 ``jack_kctl``
for this jack. The jack injection is implemented based on the
``jack_kctl`` instead of ``snd_jack``.
To inject events to audio jacks, we need to enable the jack injection
via ``sw_inject_enable`` first, once it is enabled, this jack will not
change the state by hardware events anymore, we could inject plugin or
plugout events via ``jackin_inject`` and check the jack state via
``status``, after we finish our test, we need to disable the jack
injection via ``sw_inject_enable`` too, once it is disabled, the jack
state will be restored according to the last reported hardware events
and will change by future hardware events.
The Layout of Jack Injection Interface
======================================
If users enable the SND_JACK_INJECTION_DEBUG in the kernel, the audio
jack injection interface will be created as below:
::
$debugfs_mount_dir/sound
|-- card0
|-- |-- HDMI_DP_pcm_10_Jack
|-- |-- |-- jackin_inject
|-- |-- |-- kctl_id
|-- |-- |-- mask_bits
|-- |-- |-- status
|-- |-- |-- sw_inject_enable
|-- |-- |-- type
...
|-- |-- HDMI_DP_pcm_9_Jack
|-- |-- jackin_inject
|-- |-- kctl_id
|-- |-- mask_bits
|-- |-- status
|-- |-- sw_inject_enable
|-- |-- type
|-- card1
|-- HDMI_DP_pcm_5_Jack
|-- |-- jackin_inject
|-- |-- kctl_id
|-- |-- mask_bits
|-- |-- status
|-- |-- sw_inject_enable
|-- |-- type
...
|-- Headphone_Jack
|-- |-- jackin_inject
|-- |-- kctl_id
|-- |-- mask_bits
|-- |-- status
|-- |-- sw_inject_enable
|-- |-- type
|-- Headset_Mic_Jack
|-- jackin_inject
|-- kctl_id
|-- mask_bits
|-- status
|-- sw_inject_enable
|-- type
The Explanation Of The Nodes
======================================
kctl_id
read-only, get jack_kctl->kctl's id
::
sound/card1/Headphone_Jack# cat kctl_id
Headphone Jack
mask_bits
read-only, get jack_kctl's supported events mask_bits
::
sound/card1/Headphone_Jack# cat mask_bits
0x0001 HEADPHONE(0x0001)
status
read-only, get jack_kctl's current status
- headphone unplugged:
::
sound/card1/Headphone_Jack# cat status
Unplugged
- headphone plugged:
::
sound/card1/Headphone_Jack# cat status
Plugged
type
read-only, get snd_jack's supported events from type (all supported events on the physical audio jack)
::
sound/card1/Headphone_Jack# cat type
0x7803 HEADPHONE(0x0001) MICROPHONE(0x0002) BTN_3(0x0800) BTN_2(0x1000) BTN_1(0x2000) BTN_0(0x4000)
sw_inject_enable
read-write, enable or disable injection
- injection disabled:
::
sound/card1/Headphone_Jack# cat sw_inject_enable
Jack: Headphone Jack Inject Enabled: 0
- injection enabled:
::
sound/card1/Headphone_Jack# cat sw_inject_enable
Jack: Headphone Jack Inject Enabled: 1
- to enable jack injection:
::
sound/card1/Headphone_Jack# echo 1 > sw_inject_enable
- to disable jack injection:
::
sound/card1/Headphone_Jack# echo 0 > sw_inject_enable
jackin_inject
write-only, inject plugin or plugout
- to inject plugin:
::
sound/card1/Headphone_Jack# echo 1 > jackin_inject
- to inject plugout:
::
sound/card1/Headphone_Jack# echo 0 > jackin_inject

View File

@ -51,7 +51,7 @@ static int isa_bus_remove(struct device *dev)
struct isa_driver *isa_driver = dev->platform_data; struct isa_driver *isa_driver = dev->platform_data;
if (isa_driver && isa_driver->remove) if (isa_driver && isa_driver->remove)
return isa_driver->remove(dev, to_isa_dev(dev)->id); isa_driver->remove(dev, to_isa_dev(dev)->id);
return 0; return 0;
} }

View File

@ -282,7 +282,7 @@ static int elektor_probe(struct device *dev, unsigned int id)
return -ENODEV; return -ENODEV;
} }
static int elektor_remove(struct device *dev, unsigned int id) static void elektor_remove(struct device *dev, unsigned int id)
{ {
i2c_del_adapter(&pcf_isa_ops); i2c_del_adapter(&pcf_isa_ops);
@ -298,8 +298,6 @@ static int elektor_remove(struct device *dev, unsigned int id)
iounmap(base_iomem); iounmap(base_iomem);
release_mem_region(base, 2); release_mem_region(base, 2);
} }
return 0;
} }
static struct isa_driver i2c_elektor_driver = { static struct isa_driver i2c_elektor_driver = {

View File

@ -161,7 +161,7 @@ static int pca_isa_probe(struct device *dev, unsigned int id)
return -ENODEV; return -ENODEV;
} }
static int pca_isa_remove(struct device *dev, unsigned int id) static void pca_isa_remove(struct device *dev, unsigned int id)
{ {
i2c_del_adapter(&pca_isa_ops); i2c_del_adapter(&pca_isa_ops);
@ -170,8 +170,6 @@ static int pca_isa_remove(struct device *dev, unsigned int id)
free_irq(irq, &pca_isa_ops); free_irq(irq, &pca_isa_ops);
} }
release_region(base, IO_SIZE); release_region(base, IO_SIZE);
return 0;
} }
static struct isa_driver pca_isa_driver = { static struct isa_driver pca_isa_driver = {

View File

@ -171,7 +171,7 @@ static int htcpen_isa_probe(struct device *dev, unsigned int id)
return err; return err;
} }
static int htcpen_isa_remove(struct device *dev, unsigned int id) static void htcpen_isa_remove(struct device *dev, unsigned int id)
{ {
struct input_dev *htcpen_dev = dev_get_drvdata(dev); struct input_dev *htcpen_dev = dev_get_drvdata(dev);
@ -182,8 +182,6 @@ static int htcpen_isa_remove(struct device *dev, unsigned int id)
release_region(HTCPEN_PORT_INDEX, 2); release_region(HTCPEN_PORT_INDEX, 2);
release_region(HTCPEN_PORT_INIT, 1); release_region(HTCPEN_PORT_INIT, 1);
release_region(HTCPEN_PORT_IRQ_CLEAR, 1); release_region(HTCPEN_PORT_IRQ_CLEAR, 1);
return 0;
} }
#ifdef CONFIG_PM #ifdef CONFIG_PM

View File

@ -273,8 +273,8 @@ err_dev_reg:
return res; return res;
} }
static int radio_isa_common_remove(struct radio_isa_card *isa, static void radio_isa_common_remove(struct radio_isa_card *isa,
unsigned region_size) unsigned region_size)
{ {
const struct radio_isa_ops *ops = isa->drv->ops; const struct radio_isa_ops *ops = isa->drv->ops;
@ -285,7 +285,6 @@ static int radio_isa_common_remove(struct radio_isa_card *isa,
release_region(isa->io, region_size); release_region(isa->io, region_size);
v4l2_info(&isa->v4l2_dev, "Removed radio card %s\n", isa->drv->card); v4l2_info(&isa->v4l2_dev, "Removed radio card %s\n", isa->drv->card);
kfree(isa); kfree(isa);
return 0;
} }
int radio_isa_probe(struct device *pdev, unsigned int dev) int radio_isa_probe(struct device *pdev, unsigned int dev)
@ -338,11 +337,11 @@ int radio_isa_probe(struct device *pdev, unsigned int dev)
} }
EXPORT_SYMBOL_GPL(radio_isa_probe); EXPORT_SYMBOL_GPL(radio_isa_probe);
int radio_isa_remove(struct device *pdev, unsigned int dev) void radio_isa_remove(struct device *pdev, unsigned int dev)
{ {
struct radio_isa_card *isa = dev_get_drvdata(pdev); struct radio_isa_card *isa = dev_get_drvdata(pdev);
return radio_isa_common_remove(isa, isa->drv->region_size); radio_isa_common_remove(isa, isa->drv->region_size);
} }
EXPORT_SYMBOL_GPL(radio_isa_remove); EXPORT_SYMBOL_GPL(radio_isa_remove);

View File

@ -91,7 +91,7 @@ struct radio_isa_driver {
int radio_isa_match(struct device *pdev, unsigned int dev); int radio_isa_match(struct device *pdev, unsigned int dev);
int radio_isa_probe(struct device *pdev, unsigned int dev); int radio_isa_probe(struct device *pdev, unsigned int dev);
int radio_isa_remove(struct device *pdev, unsigned int dev); void radio_isa_remove(struct device *pdev, unsigned int dev);
#ifdef CONFIG_PNP #ifdef CONFIG_PNP
int radio_isa_pnp_probe(struct pnp_dev *dev, int radio_isa_pnp_probe(struct pnp_dev *dev,
const struct pnp_device_id *dev_id); const struct pnp_device_id *dev_id);

View File

@ -293,11 +293,9 @@ static void fmr2_remove(struct fmr2 *fmr2)
kfree(fmr2); kfree(fmr2);
} }
static int fmr2_isa_remove(struct device *pdev, unsigned int ndev) static void fmr2_isa_remove(struct device *pdev, unsigned int ndev)
{ {
fmr2_remove(dev_get_drvdata(pdev)); fmr2_remove(dev_get_drvdata(pdev));
return 0;
} }
static void fmr2_pnp_remove(struct pnp_dev *pdev) static void fmr2_pnp_remove(struct pnp_dev *pdev)

View File

@ -797,17 +797,6 @@ const struct dev_pm_ops arizona_pm_ops = {
EXPORT_SYMBOL_GPL(arizona_pm_ops); EXPORT_SYMBOL_GPL(arizona_pm_ops);
#ifdef CONFIG_OF #ifdef CONFIG_OF
unsigned long arizona_of_get_type(struct device *dev)
{
const struct of_device_id *id = of_match_device(arizona_of_match, dev);
if (id)
return (unsigned long)id->data;
else
return 0;
}
EXPORT_SYMBOL_GPL(arizona_of_get_type);
static int arizona_of_get_core_pdata(struct arizona *arizona) static int arizona_of_get_core_pdata(struct arizona *arizona)
{ {
struct arizona_pdata *pdata = &arizona->pdata; struct arizona_pdata *pdata = &arizona->pdata;

View File

@ -23,14 +23,16 @@
static int arizona_i2c_probe(struct i2c_client *i2c, static int arizona_i2c_probe(struct i2c_client *i2c,
const struct i2c_device_id *id) const struct i2c_device_id *id)
{ {
const void *match_data;
struct arizona *arizona; struct arizona *arizona;
const struct regmap_config *regmap_config = NULL; const struct regmap_config *regmap_config = NULL;
unsigned long type; unsigned long type = 0;
int ret; int ret;
if (i2c->dev.of_node) match_data = device_get_match_data(&i2c->dev);
type = arizona_of_get_type(&i2c->dev); if (match_data)
else type = (unsigned long)match_data;
else if (id)
type = id->driver_data; type = id->driver_data;
switch (type) { switch (type) {
@ -115,6 +117,7 @@ static struct i2c_driver arizona_i2c_driver = {
module_i2c_driver(arizona_i2c_driver); module_i2c_driver(arizona_i2c_driver);
MODULE_SOFTDEP("pre: arizona_ldo1");
MODULE_DESCRIPTION("Arizona I2C bus interface"); MODULE_DESCRIPTION("Arizona I2C bus interface");
MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>"); MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>");
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");

View File

@ -7,7 +7,10 @@
* Author: Mark Brown <broonie@opensource.wolfsonmicro.com> * Author: Mark Brown <broonie@opensource.wolfsonmicro.com>
*/ */
#include <linux/acpi.h>
#include <linux/err.h> #include <linux/err.h>
#include <linux/gpio/consumer.h>
#include <linux/gpio/machine.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/pm_runtime.h> #include <linux/pm_runtime.h>
#include <linux/regmap.h> #include <linux/regmap.h>
@ -15,22 +18,141 @@
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/spi/spi.h> #include <linux/spi/spi.h>
#include <linux/of.h> #include <linux/of.h>
#include <uapi/linux/input-event-codes.h>
#include <linux/mfd/arizona/core.h> #include <linux/mfd/arizona/core.h>
#include "arizona.h" #include "arizona.h"
#ifdef CONFIG_ACPI
const struct acpi_gpio_params reset_gpios = { 1, 0, false };
const struct acpi_gpio_params ldoena_gpios = { 2, 0, false };
static const struct acpi_gpio_mapping arizona_acpi_gpios[] = {
{ "reset-gpios", &reset_gpios, 1, },
{ "wlf,ldoena-gpios", &ldoena_gpios, 1 },
{ }
};
/*
* The ACPI resources for the device only describe external GPIO-s. They do
* not provide mappings for the GPIO-s coming from the Arizona codec itself.
*/
static const struct gpiod_lookup arizona_soc_gpios[] = {
{ "arizona", 2, "wlf,spkvdd-ena", 0, GPIO_ACTIVE_HIGH },
{ "arizona", 4, "wlf,micd-pol", 0, GPIO_ACTIVE_LOW },
};
/*
* The AOSP 3.5 mm Headset: Accessory Specification gives the following values:
* Function A Play/Pause: 0 ohm
* Function D Voice assistant: 135 ohm
* Function B Volume Up 240 ohm
* Function C Volume Down 470 ohm
* Minimum Mic DC resistance 1000 ohm
* Minimum Ear speaker impedance 16 ohm
* Note the first max value below must be less then the min. speaker impedance,
* to allow CTIA/OMTP detection to work. The other max values are the closest
* value from extcon-arizona.c:arizona_micd_levels halfway 2 button resistances.
*/
static const struct arizona_micd_range arizona_micd_aosp_ranges[] = {
{ .max = 11, .key = KEY_PLAYPAUSE },
{ .max = 186, .key = KEY_VOICECOMMAND },
{ .max = 348, .key = KEY_VOLUMEUP },
{ .max = 752, .key = KEY_VOLUMEDOWN },
};
static void arizona_spi_acpi_remove_lookup(void *lookup)
{
gpiod_remove_lookup_table(lookup);
}
static int arizona_spi_acpi_probe(struct arizona *arizona)
{
struct gpiod_lookup_table *lookup;
acpi_status status;
int ret;
/* Add mappings for the 2 ACPI declared GPIOs used for reset and ldo-ena */
devm_acpi_dev_add_driver_gpios(arizona->dev, arizona_acpi_gpios);
/* Add lookups for the SoCs own GPIOs used for micdet-polarity and spkVDD-enable */
lookup = devm_kzalloc(arizona->dev,
struct_size(lookup, table, ARRAY_SIZE(arizona_soc_gpios) + 1),
GFP_KERNEL);
if (!lookup)
return -ENOMEM;
lookup->dev_id = dev_name(arizona->dev);
memcpy(lookup->table, arizona_soc_gpios, sizeof(arizona_soc_gpios));
gpiod_add_lookup_table(lookup);
ret = devm_add_action_or_reset(arizona->dev, arizona_spi_acpi_remove_lookup, lookup);
if (ret)
return ret;
/* Enable 32KHz clock from SoC to codec for jack-detect */
status = acpi_evaluate_object(ACPI_HANDLE(arizona->dev), "CLKE", NULL, NULL);
if (ACPI_FAILURE(status))
dev_warn(arizona->dev, "Failed to enable 32KHz clk ACPI error %d\n", status);
/*
* Some DSDTs wrongly declare the IRQ trigger-type as IRQF_TRIGGER_FALLING
* The IRQ line will stay low when a new IRQ event happens between reading
* the IRQ status flags and acknowledging them. When the IRQ line stays
* low like this the IRQ will never trigger again when its type is set
* to IRQF_TRIGGER_FALLING. Correct the IRQ trigger-type to fix this.
*
* Note theoretically it is possible that some boards are not capable
* of handling active low level interrupts. In that case setting the
* flag to IRQF_TRIGGER_FALLING would not be a bug (and we would need
* to work around this) but so far all known usages of IRQF_TRIGGER_FALLING
* are a bug in the board's DSDT.
*/
arizona->pdata.irq_flags = IRQF_TRIGGER_LOW;
/* Wait 200 ms after jack insertion */
arizona->pdata.micd_detect_debounce = 200;
/* Use standard AOSP values for headset-button mappings */
arizona->pdata.micd_ranges = arizona_micd_aosp_ranges;
arizona->pdata.num_micd_ranges = ARRAY_SIZE(arizona_micd_aosp_ranges);
return 0;
}
static const struct acpi_device_id arizona_acpi_match[] = {
{
.id = "WM510204",
.driver_data = WM5102,
},
{
.id = "WM510205",
.driver_data = WM5102,
},
{ }
};
MODULE_DEVICE_TABLE(acpi, arizona_acpi_match);
#else
static int arizona_spi_acpi_probe(struct arizona *arizona)
{
return -ENODEV;
}
#endif
static int arizona_spi_probe(struct spi_device *spi) static int arizona_spi_probe(struct spi_device *spi)
{ {
const struct spi_device_id *id = spi_get_device_id(spi); const struct spi_device_id *id = spi_get_device_id(spi);
const void *match_data;
struct arizona *arizona; struct arizona *arizona;
const struct regmap_config *regmap_config = NULL; const struct regmap_config *regmap_config = NULL;
unsigned long type; unsigned long type = 0;
int ret; int ret;
if (spi->dev.of_node) match_data = device_get_match_data(&spi->dev);
type = arizona_of_get_type(&spi->dev); if (match_data)
else type = (unsigned long)match_data;
else if (id)
type = id->driver_data; type = id->driver_data;
switch (type) { switch (type) {
@ -75,6 +197,12 @@ static int arizona_spi_probe(struct spi_device *spi)
arizona->dev = &spi->dev; arizona->dev = &spi->dev;
arizona->irq = spi->irq; arizona->irq = spi->irq;
if (has_acpi_companion(&spi->dev)) {
ret = arizona_spi_acpi_probe(arizona);
if (ret)
return ret;
}
return arizona_dev_init(arizona); return arizona_dev_init(arizona);
} }
@ -102,6 +230,7 @@ static struct spi_driver arizona_spi_driver = {
.name = "arizona", .name = "arizona",
.pm = &arizona_pm_ops, .pm = &arizona_pm_ops,
.of_match_table = of_match_ptr(arizona_of_match), .of_match_table = of_match_ptr(arizona_of_match),
.acpi_match_table = ACPI_PTR(arizona_acpi_match),
}, },
.probe = arizona_spi_probe, .probe = arizona_spi_probe,
.remove = arizona_spi_remove, .remove = arizona_spi_remove,
@ -110,6 +239,7 @@ static struct spi_driver arizona_spi_driver = {
module_spi_driver(arizona_spi_driver); module_spi_driver(arizona_spi_driver);
MODULE_SOFTDEP("pre: arizona_ldo1");
MODULE_DESCRIPTION("Arizona SPI bus interface"); MODULE_DESCRIPTION("Arizona SPI bus interface");
MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>"); MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>");
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");

View File

@ -50,13 +50,4 @@ int arizona_dev_exit(struct arizona *arizona);
int arizona_irq_init(struct arizona *arizona); int arizona_irq_init(struct arizona *arizona);
int arizona_irq_exit(struct arizona *arizona); int arizona_irq_exit(struct arizona *arizona);
#ifdef CONFIG_OF
unsigned long arizona_of_get_type(struct device *dev);
#else
static inline unsigned long arizona_of_get_type(struct device *dev)
{
return 0;
}
#endif
#endif #endif

View File

@ -159,7 +159,7 @@ static int tscan1_probe(struct device *dev, unsigned id)
return -ENXIO; return -ENXIO;
} }
static int tscan1_remove(struct device *dev, unsigned id /*unused*/) static void tscan1_remove(struct device *dev, unsigned id /*unused*/)
{ {
struct net_device *netdev; struct net_device *netdev;
struct sja1000_priv *priv; struct sja1000_priv *priv;
@ -179,8 +179,6 @@ static int tscan1_remove(struct device *dev, unsigned id /*unused*/)
release_region(pld_base, TSCAN1_PLD_SIZE); release_region(pld_base, TSCAN1_PLD_SIZE);
free_sja1000dev(netdev); free_sja1000dev(netdev);
return 0;
} }
static struct isa_driver tscan1_isa_driver = { static struct isa_driver tscan1_isa_driver = {

View File

@ -335,12 +335,11 @@ static int el3_isa_match(struct device *pdev, unsigned int ndev)
return 1; return 1;
} }
static int el3_isa_remove(struct device *pdev, static void el3_isa_remove(struct device *pdev,
unsigned int ndev) unsigned int ndev)
{ {
el3_device_remove(pdev); el3_device_remove(pdev);
dev_set_drvdata(pdev, NULL); dev_set_drvdata(pdev, NULL);
return 0;
} }
#ifdef CONFIG_PM #ifdef CONFIG_PM

View File

@ -11459,12 +11459,11 @@ static int advansys_isa_probe(struct device *dev, unsigned int id)
return err; return err;
} }
static int advansys_isa_remove(struct device *dev, unsigned int id) static void advansys_isa_remove(struct device *dev, unsigned int id)
{ {
int ioport = _asc_def_iop_base[id]; int ioport = _asc_def_iop_base[id];
advansys_release(dev_get_drvdata(dev)); advansys_release(dev_get_drvdata(dev));
release_region(ioport, ASC_IOADR_GAP); release_region(ioport, ASC_IOADR_GAP);
return 0;
} }
static struct isa_driver advansys_isa_driver = { static struct isa_driver advansys_isa_driver = {

View File

@ -1025,12 +1025,11 @@ static int aha1542_isa_match(struct device *pdev, unsigned int ndev)
return 1; return 1;
} }
static int aha1542_isa_remove(struct device *pdev, static void aha1542_isa_remove(struct device *pdev,
unsigned int ndev) unsigned int ndev)
{ {
aha1542_release(dev_get_drvdata(pdev)); aha1542_release(dev_get_drvdata(pdev));
dev_set_drvdata(pdev, NULL); dev_set_drvdata(pdev, NULL);
return 0;
} }
static struct isa_driver aha1542_isa_driver = { static struct isa_driver aha1542_isa_driver = {

View File

@ -175,7 +175,7 @@ static int fdomain_isa_param_match(struct device *dev, unsigned int ndev)
return 1; return 1;
} }
static int fdomain_isa_remove(struct device *dev, unsigned int ndev) static void fdomain_isa_remove(struct device *dev, unsigned int ndev)
{ {
struct Scsi_Host *sh = dev_get_drvdata(dev); struct Scsi_Host *sh = dev_get_drvdata(dev);
int base = sh->io_port; int base = sh->io_port;
@ -183,7 +183,6 @@ static int fdomain_isa_remove(struct device *dev, unsigned int ndev)
fdomain_destroy(sh); fdomain_destroy(sh);
release_region(base, FDOMAIN_REGION_SIZE); release_region(base, FDOMAIN_REGION_SIZE);
dev_set_drvdata(dev, NULL); dev_set_drvdata(dev, NULL);
return 0;
} }
static struct isa_driver fdomain_isa_driver = { static struct isa_driver fdomain_isa_driver = {

View File

@ -720,12 +720,11 @@ static int generic_NCR5380_isa_match(struct device *pdev, unsigned int ndev)
return 1; return 1;
} }
static int generic_NCR5380_isa_remove(struct device *pdev, static void generic_NCR5380_isa_remove(struct device *pdev,
unsigned int ndev) unsigned int ndev)
{ {
generic_NCR5380_release_resources(dev_get_drvdata(pdev)); generic_NCR5380_release_resources(dev_get_drvdata(pdev));
dev_set_drvdata(pdev, NULL); dev_set_drvdata(pdev, NULL);
return 0;
} }
static struct isa_driver generic_NCR5380_isa_driver = { static struct isa_driver generic_NCR5380_isa_driver = {

View File

@ -951,14 +951,11 @@ error_request_region:
return ret; return ret;
} }
static int pcwd_isa_remove(struct device *dev, unsigned int id) static void pcwd_isa_remove(struct device *dev, unsigned int id)
{ {
if (debug >= DEBUG) if (debug >= DEBUG)
pr_debug("pcwd_isa_remove id=%d\n", id); pr_debug("pcwd_isa_remove id=%d\n", id);
if (!pcwd_private.io_addr)
return 1;
/* Disable the board */ /* Disable the board */
if (!nowayout) if (!nowayout)
pcwd_stop(); pcwd_stop();
@ -971,8 +968,6 @@ static int pcwd_isa_remove(struct device *dev, unsigned int id)
(pcwd_private.revision == PCWD_REVISION_A) ? 2 : 4); (pcwd_private.revision == PCWD_REVISION_A) ? 2 : 4);
pcwd_private.io_addr = 0x0000; pcwd_private.io_addr = 0x0000;
cards_found--; cards_found--;
return 0;
} }
static void pcwd_isa_shutdown(struct device *dev, unsigned int id) static void pcwd_isa_shutdown(struct device *dev, unsigned int id)

View File

@ -13,7 +13,7 @@
struct isa_driver { struct isa_driver {
int (*match)(struct device *, unsigned int); int (*match)(struct device *, unsigned int);
int (*probe)(struct device *, unsigned int); int (*probe)(struct device *, unsigned int);
int (*remove)(struct device *, unsigned int); void (*remove)(struct device *, unsigned int);
void (*shutdown)(struct device *, unsigned int); void (*shutdown)(struct device *, unsigned int);
int (*suspend)(struct device *, unsigned int, pm_message_t); int (*suspend)(struct device *, unsigned int, pm_message_t);
int (*resume)(struct device *, unsigned int); int (*resume)(struct device *, unsigned int);

View File

@ -4610,6 +4610,7 @@ enum ec_codec_i2s_rx_subcmd {
EC_CODEC_I2S_RX_SET_SAMPLE_DEPTH = 0x2, EC_CODEC_I2S_RX_SET_SAMPLE_DEPTH = 0x2,
EC_CODEC_I2S_RX_SET_DAIFMT = 0x3, EC_CODEC_I2S_RX_SET_DAIFMT = 0x3,
EC_CODEC_I2S_RX_SET_BCLK = 0x4, EC_CODEC_I2S_RX_SET_BCLK = 0x4,
EC_CODEC_I2S_RX_RESET = 0x5,
EC_CODEC_I2S_RX_SUBCMD_COUNT, EC_CODEC_I2S_RX_SUBCMD_COUNT,
}; };

View File

@ -122,6 +122,9 @@ struct snd_card {
size_t total_pcm_alloc_bytes; /* total amount of allocated buffers */ size_t total_pcm_alloc_bytes; /* total amount of allocated buffers */
struct mutex memory_mutex; /* protection for the above */ struct mutex memory_mutex; /* protection for the above */
#ifdef CONFIG_SND_DEBUG
struct dentry *debugfs_root; /* debugfs root for card */
#endif
#ifdef CONFIG_PM #ifdef CONFIG_PM
unsigned int power_state; /* power state */ unsigned int power_state; /* power state */
@ -180,6 +183,9 @@ static inline struct device *snd_card_get_device_link(struct snd_card *card)
extern int snd_major; extern int snd_major;
extern int snd_ecards_limit; extern int snd_ecards_limit;
extern struct class *sound_class; extern struct class *sound_class;
#ifdef CONFIG_SND_DEBUG
extern struct dentry *sound_debugfs_root;
#endif
void snd_request_card(int card); void snd_request_card(int card);

View File

@ -66,6 +66,9 @@ struct dma_chan *snd_dmaengine_pcm_get_chan(struct snd_pcm_substream *substream)
* @chan_name: Custom channel name to use when requesting DMA channel. * @chan_name: Custom channel name to use when requesting DMA channel.
* @fifo_size: FIFO size of the DAI controller in bytes * @fifo_size: FIFO size of the DAI controller in bytes
* @flags: PCM_DAI flags, only SND_DMAENGINE_PCM_DAI_FLAG_PACK for now * @flags: PCM_DAI flags, only SND_DMAENGINE_PCM_DAI_FLAG_PACK for now
* @peripheral_config: peripheral configuration for programming peripheral
* for dmaengine transfer
* @peripheral_size: peripheral configuration buffer size
*/ */
struct snd_dmaengine_dai_dma_data { struct snd_dmaengine_dai_dma_data {
dma_addr_t addr; dma_addr_t addr;
@ -76,6 +79,8 @@ struct snd_dmaengine_dai_dma_data {
const char *chan_name; const char *chan_name;
unsigned int fifo_size; unsigned int fifo_size;
unsigned int flags; unsigned int flags;
void *peripheral_config;
size_t peripheral_size;
}; };
void snd_dmaengine_pcm_set_config_from_dai_data( void snd_dmaengine_pcm_set_config_from_dai_data(

View File

@ -9,8 +9,10 @@
#include <sound/simple_card_utils.h> #include <sound/simple_card_utils.h>
int graph_card_probe(struct snd_soc_card *card); int audio_graph_card_probe(struct snd_soc_card *card);
int graph_parse_of(struct asoc_simple_priv *priv, struct device *dev); int audio_graph_parse_of(struct asoc_simple_priv *priv, struct device *dev);
int audio_graph_remove(struct platform_device *pdev);
#endif /* __GRAPH_CARD_H */ #endif /* __GRAPH_CARD_H */

View File

@ -241,6 +241,8 @@ struct hdac_bus_ops {
/* get a response from the last command */ /* get a response from the last command */
int (*get_response)(struct hdac_bus *bus, unsigned int addr, int (*get_response)(struct hdac_bus *bus, unsigned int addr,
unsigned int *res); unsigned int *res);
/* notify of codec link power-up/down */
void (*link_power)(struct hdac_device *hdev, bool enable);
}; };
/* /*
@ -378,15 +380,8 @@ void snd_hdac_bus_exit(struct hdac_bus *bus);
int snd_hdac_bus_exec_verb_unlocked(struct hdac_bus *bus, unsigned int addr, int snd_hdac_bus_exec_verb_unlocked(struct hdac_bus *bus, unsigned int addr,
unsigned int cmd, unsigned int *res); unsigned int cmd, unsigned int *res);
static inline void snd_hdac_codec_link_up(struct hdac_device *codec) void snd_hdac_codec_link_up(struct hdac_device *codec);
{ void snd_hdac_codec_link_down(struct hdac_device *codec);
set_bit(codec->addr, &codec->bus->codec_powered);
}
static inline void snd_hdac_codec_link_down(struct hdac_device *codec)
{
clear_bit(codec->addr, &codec->bus->codec_powered);
}
int snd_hdac_bus_send_cmd(struct hdac_bus *bus, unsigned int val); int snd_hdac_bus_send_cmd(struct hdac_bus *bus, unsigned int val);
int snd_hdac_bus_get_response(struct hdac_bus *bus, unsigned int addr, int snd_hdac_bus_get_response(struct hdac_bus *bus, unsigned int addr,
@ -400,6 +395,7 @@ void snd_hdac_bus_stop_cmd_io(struct hdac_bus *bus);
void snd_hdac_bus_enter_link_reset(struct hdac_bus *bus); void snd_hdac_bus_enter_link_reset(struct hdac_bus *bus);
void snd_hdac_bus_exit_link_reset(struct hdac_bus *bus); void snd_hdac_bus_exit_link_reset(struct hdac_bus *bus);
int snd_hdac_bus_reset_link(struct hdac_bus *bus, bool full_reset); int snd_hdac_bus_reset_link(struct hdac_bus *bus, bool full_reset);
void snd_hdac_bus_link_power(struct hdac_device *hdev, bool enable);
void snd_hdac_bus_update_rirb(struct hdac_bus *bus); void snd_hdac_bus_update_rirb(struct hdac_bus *bus);
int snd_hdac_bus_handle_stream_irq(struct hdac_bus *bus, unsigned int status, int snd_hdac_bus_handle_stream_irq(struct hdac_bus *bus, unsigned int status,

View File

@ -131,6 +131,8 @@ void snd_hdac_ext_link_clear_stream_id(struct hdac_ext_link *link,
int snd_hdac_ext_bus_link_get(struct hdac_bus *bus, struct hdac_ext_link *link); int snd_hdac_ext_bus_link_get(struct hdac_bus *bus, struct hdac_ext_link *link);
int snd_hdac_ext_bus_link_put(struct hdac_bus *bus, struct hdac_ext_link *link); int snd_hdac_ext_bus_link_put(struct hdac_bus *bus, struct hdac_ext_link *link);
void snd_hdac_ext_bus_link_power(struct hdac_device *codec, bool enable);
/* update register macro */ /* update register macro */
#define snd_hdac_updatel(addr, reg, mask, val) \ #define snd_hdac_updatel(addr, reg, mask, val) \
writel(((readl(addr + reg) & ~(mask)) | (val)), \ writel(((readl(addr + reg) & ~(mask)) | (val)), \

View File

@ -34,6 +34,11 @@ struct hdmi_codec_daifmt {
unsigned int frame_clk_inv:1; unsigned int frame_clk_inv:1;
unsigned int bit_clk_master:1; unsigned int bit_clk_master:1;
unsigned int frame_clk_master:1; unsigned int frame_clk_master:1;
/* bit_fmt could be standard PCM format or
* IEC958 encoded format. ALSA IEC958 plugin will pass
* IEC958_SUBFRAME format to the underneath driver.
*/
snd_pcm_format_t bit_fmt;
}; };
/* /*

View File

@ -67,6 +67,7 @@ struct snd_jack {
char name[100]; char name[100];
unsigned int key[6]; /* Keep in sync with definitions above */ unsigned int key[6]; /* Keep in sync with definitions above */
#endif /* CONFIG_SND_JACK_INPUT_DEV */ #endif /* CONFIG_SND_JACK_INPUT_DEV */
int hw_status_cache;
void *private_data; void *private_data;
void (*private_free)(struct snd_jack *); void (*private_free)(struct snd_jack *);
}; };

View File

@ -22,6 +22,8 @@ struct rt5645_platform_data {
bool level_trigger_irq; bool level_trigger_irq;
/* Invert JD1_1 status polarity */ /* Invert JD1_1 status polarity */
bool inv_jd1_1; bool inv_jd1_1;
/* Invert HP detect status polarity */
bool inv_hp_pol;
/* Value to asign to snd_soc_card.long_name */ /* Value to asign to snd_soc_card.long_name */
const char *long_name; const char *long_name;

View File

@ -353,6 +353,12 @@ int snd_soc_component_test_bits(struct snd_soc_component *component,
unsigned int reg, unsigned int mask, unsigned int reg, unsigned int mask,
unsigned int value); unsigned int value);
unsigned int snd_soc_component_read_field(struct snd_soc_component *component,
unsigned int reg, unsigned int mask);
int snd_soc_component_write_field(struct snd_soc_component *component,
unsigned int reg, unsigned int mask,
unsigned int val);
/* component wide operations */ /* component wide operations */
int snd_soc_component_set_sysclk(struct snd_soc_component *component, int snd_soc_component_set_sysclk(struct snd_soc_component *component,
int clk_id, int source, int clk_id, int source,

View File

@ -353,9 +353,9 @@ struct snd_soc_dai_driver {
/* DAI capabilities */ /* DAI capabilities */
struct snd_soc_pcm_stream capture; struct snd_soc_pcm_stream capture;
struct snd_soc_pcm_stream playback; struct snd_soc_pcm_stream playback;
unsigned int symmetric_rates:1; unsigned int symmetric_rate:1;
unsigned int symmetric_channels:1; unsigned int symmetric_channels:1;
unsigned int symmetric_samplebits:1; unsigned int symmetric_sample_bits:1;
/* probe ordering - for components with runtime dependencies */ /* probe ordering - for components with runtime dependencies */
int probe_order; int probe_order;

View File

@ -685,9 +685,9 @@ struct snd_soc_dai_link {
unsigned int ignore_suspend:1; unsigned int ignore_suspend:1;
/* Symmetry requirements */ /* Symmetry requirements */
unsigned int symmetric_rates:1; unsigned int symmetric_rate:1;
unsigned int symmetric_channels:1; unsigned int symmetric_channels:1;
unsigned int symmetric_samplebits:1; unsigned int symmetric_sample_bits:1;
/* Do not create a PCM for this DAI link (Backend link) */ /* Do not create a PCM for this DAI link (Backend link) */
unsigned int no_pcm:1; unsigned int no_pcm:1;

View File

@ -58,9 +58,9 @@ struct sof_ext_man_header {
/* Extended manifest elements types */ /* Extended manifest elements types */
enum sof_ext_man_elem_type { enum sof_ext_man_elem_type {
SOF_EXT_MAN_ELEM_FW_VERSION = 0, SOF_EXT_MAN_ELEM_FW_VERSION = 0,
SOF_EXT_MAN_ELEM_WINDOW = SOF_IPC_EXT_WINDOW, SOF_EXT_MAN_ELEM_WINDOW = 1,
SOF_EXT_MAN_ELEM_CC_VERSION = SOF_IPC_EXT_CC_INFO, SOF_EXT_MAN_ELEM_CC_VERSION = 2,
SOF_EXT_MAN_ELEM_DBG_ABI = SOF_IPC_EXT_USER_ABI_INFO, SOF_EXT_MAN_ELEM_DBG_ABI = 4,
SOF_EXT_MAN_ELEM_CONFIG_DATA = 5, /**< ABI3.17 */ SOF_EXT_MAN_ELEM_CONFIG_DATA = 5, /**< ABI3.17 */
SOF_EXT_MAN_ELEM_PLATFORM_CONFIG_DATA = 6, SOF_EXT_MAN_ELEM_PLATFORM_CONFIG_DATA = 6,
}; };

View File

@ -273,7 +273,7 @@ static struct attribute *ac97_controller_device_attrs[] = {
NULL NULL
}; };
static struct attribute_group ac97_adapter_attr_group = { static const struct attribute_group ac97_adapter_attr_group = {
.name = "ac97_operations", .name = "ac97_operations",
.attrs = ac97_controller_device_attrs, .attrs = ac97_controller_device_attrs,
}; };

View File

@ -1013,7 +1013,7 @@ static int onyx_i2c_probe(struct i2c_client *client,
goto fail; goto fail;
} }
strlcpy(onyx->codec.name, "onyx", MAX_CODEC_NAME_LEN); strscpy(onyx->codec.name, "onyx", MAX_CODEC_NAME_LEN);
onyx->codec.owner = THIS_MODULE; onyx->codec.owner = THIS_MODULE;
onyx->codec.init = onyx_init_codec; onyx->codec.init = onyx_init_codec;
onyx->codec.exit = onyx_exit_codec; onyx->codec.exit = onyx_exit_codec;

View File

@ -894,7 +894,7 @@ static int tas_i2c_probe(struct i2c_client *client,
/* seems that half is a saner default */ /* seems that half is a saner default */
tas->drc_range = TAS3004_DRC_MAX / 2; tas->drc_range = TAS3004_DRC_MAX / 2;
strlcpy(tas->codec.name, "tas", MAX_CODEC_NAME_LEN); strscpy(tas->codec.name, "tas", MAX_CODEC_NAME_LEN);
tas->codec.owner = THIS_MODULE; tas->codec.owner = THIS_MODULE;
tas->codec.init = tas_init_codec; tas->codec.init = tas_init_codec;
tas->codec.exit = tas_exit_codec; tas->codec.exit = tas_exit_codec;

View File

@ -126,7 +126,7 @@ static int __init toonie_init(void)
if (!toonie) if (!toonie)
return -ENOMEM; return -ENOMEM;
strlcpy(toonie->codec.name, "toonie", sizeof(toonie->codec.name)); strscpy(toonie->codec.name, "toonie", sizeof(toonie->codec.name));
toonie->codec.owner = THIS_MODULE; toonie->codec.owner = THIS_MODULE;
toonie->codec.init = toonie_init_codec; toonie->codec.init = toonie_init_codec;
toonie->codec.exit = toonie_exit_codec; toonie->codec.exit = toonie_exit_codec;

View File

@ -28,10 +28,10 @@ int aoa_alsa_init(char *name, struct module *mod, struct device *dev)
return err; return err;
aoa_card = alsa_card->private_data; aoa_card = alsa_card->private_data;
aoa_card->alsa_card = alsa_card; aoa_card->alsa_card = alsa_card;
strlcpy(alsa_card->driver, "AppleOnbdAudio", sizeof(alsa_card->driver)); strscpy(alsa_card->driver, "AppleOnbdAudio", sizeof(alsa_card->driver));
strlcpy(alsa_card->shortname, name, sizeof(alsa_card->shortname)); strscpy(alsa_card->shortname, name, sizeof(alsa_card->shortname));
strlcpy(alsa_card->longname, name, sizeof(alsa_card->longname)); strscpy(alsa_card->longname, name, sizeof(alsa_card->longname));
strlcpy(alsa_card->mixername, name, sizeof(alsa_card->mixername)); strscpy(alsa_card->mixername, name, sizeof(alsa_card->mixername));
err = snd_card_register(aoa_card->alsa_card); err = snd_card_register(aoa_card->alsa_card);
if (err < 0) { if (err < 0) {
printk(KERN_ERR "snd-aoa: couldn't register alsa card\n"); printk(KERN_ERR "snd-aoa: couldn't register alsa card\n");

View File

@ -948,7 +948,7 @@ static void layout_attached_codec(struct aoa_codec *codec)
ldev->gpio.methods->set_lineout(codec->gpio, 1); ldev->gpio.methods->set_lineout(codec->gpio, 1);
ctl = snd_ctl_new1(&lineout_ctl, codec->gpio); ctl = snd_ctl_new1(&lineout_ctl, codec->gpio);
if (cc->connected & CC_LINEOUT_LABELLED_HEADPHONE) if (cc->connected & CC_LINEOUT_LABELLED_HEADPHONE)
strlcpy(ctl->id.name, strscpy(ctl->id.name,
"Headphone Switch", sizeof(ctl->id.name)); "Headphone Switch", sizeof(ctl->id.name));
ldev->lineout_ctrl = ctl; ldev->lineout_ctrl = ctl;
aoa_snd_ctl_add(ctl); aoa_snd_ctl_add(ctl);
@ -962,14 +962,14 @@ static void layout_attached_codec(struct aoa_codec *codec)
ctl = snd_ctl_new1(&lineout_detect_choice, ctl = snd_ctl_new1(&lineout_detect_choice,
ldev); ldev);
if (cc->connected & CC_LINEOUT_LABELLED_HEADPHONE) if (cc->connected & CC_LINEOUT_LABELLED_HEADPHONE)
strlcpy(ctl->id.name, strscpy(ctl->id.name,
"Headphone Detect Autoswitch", "Headphone Detect Autoswitch",
sizeof(ctl->id.name)); sizeof(ctl->id.name));
aoa_snd_ctl_add(ctl); aoa_snd_ctl_add(ctl);
ctl = snd_ctl_new1(&lineout_detected, ctl = snd_ctl_new1(&lineout_detected,
ldev); ldev);
if (cc->connected & CC_LINEOUT_LABELLED_HEADPHONE) if (cc->connected & CC_LINEOUT_LABELLED_HEADPHONE)
strlcpy(ctl->id.name, strscpy(ctl->id.name,
"Headphone Detected", "Headphone Detected",
sizeof(ctl->id.name)); sizeof(ctl->id.name));
ldev->lineout_detected_ctrl = ctl; ldev->lineout_detected_ctrl = ctl;

View File

@ -13,7 +13,7 @@ static ssize_t modalias_show(struct device *dev, struct device_attribute *attr,
int length; int length;
if (*sdev->modalias) { if (*sdev->modalias) {
strlcpy(buf, sdev->modalias, sizeof(sdev->modalias) + 1); strscpy(buf, sdev->modalias, sizeof(sdev->modalias) + 1);
strcat(buf, "\n"); strcat(buf, "\n");
length = strlen(buf); length = strlen(buf);
} else { } else {

View File

@ -890,8 +890,8 @@ static struct aaci *aaci_init_card(struct amba_device *dev)
card->private_free = aaci_free_card; card->private_free = aaci_free_card;
strlcpy(card->driver, DRIVER_NAME, sizeof(card->driver)); strscpy(card->driver, DRIVER_NAME, sizeof(card->driver));
strlcpy(card->shortname, "ARM AC'97 Interface", sizeof(card->shortname)); strscpy(card->shortname, "ARM AC'97 Interface", sizeof(card->shortname));
snprintf(card->longname, sizeof(card->longname), snprintf(card->longname, sizeof(card->longname),
"%s PL%03x rev%u at 0x%08llx, irq %d", "%s PL%03x rev%u at 0x%08llx, irq %d",
card->shortname, amba_part(dev), amba_rev(dev), card->shortname, amba_part(dev), amba_rev(dev),
@ -921,7 +921,7 @@ static int aaci_init_pcm(struct aaci *aaci)
pcm->private_data = aaci; pcm->private_data = aaci;
pcm->info_flags = 0; pcm->info_flags = 0;
strlcpy(pcm->name, DRIVER_NAME, sizeof(pcm->name)); strscpy(pcm->name, DRIVER_NAME, sizeof(pcm->name));
snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &aaci_playback_ops); snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &aaci_playback_ops);
snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &aaci_capture_ops); snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &aaci_capture_ops);

View File

@ -235,7 +235,7 @@ static int pxa2xx_ac97_probe(struct platform_device *dev)
if (ret < 0) if (ret < 0)
goto err; goto err;
strlcpy(card->driver, dev->dev.driver->name, sizeof(card->driver)); strscpy(card->driver, dev->dev.driver->name, sizeof(card->driver));
ret = pxa2xx_ac97_pcm_new(card); ret = pxa2xx_ac97_pcm_new(card);
if (ret) if (ret)

View File

@ -187,6 +187,15 @@ config SND_CTL_VALIDATION
from the driver are in the proper ranges or the check of the invalid from the driver are in the proper ranges or the check of the invalid
access at out-of-array areas. access at out-of-array areas.
config SND_JACK_INJECTION_DEBUG
bool "Sound jack injection interface via debugfs"
depends on SND_JACK && SND_DEBUG && DEBUG_FS
help
This option can be used to enable or disable sound jack
software injection.
Say Y if you are debugging via jack injection interface.
If unsure select "N".
config SND_VMASTER config SND_VMASTER
bool bool

View File

@ -1132,7 +1132,7 @@ static void snd_compress_proc_done(struct snd_compr *compr)
static inline void snd_compress_set_id(struct snd_compr *compr, const char *id) static inline void snd_compress_set_id(struct snd_compr *compr, const char *id)
{ {
strlcpy(compr->id, id, sizeof(compr->id)); strscpy(compr->id, id, sizeof(compr->id));
} }
#else #else
static inline int snd_compress_proc_init(struct snd_compr *compr) static inline int snd_compress_proc_init(struct snd_compr *compr)

View File

@ -261,7 +261,7 @@ struct snd_kcontrol *snd_ctl_new1(const struct snd_kcontrol_new *ncontrol,
kctl->id.device = ncontrol->device; kctl->id.device = ncontrol->device;
kctl->id.subdevice = ncontrol->subdevice; kctl->id.subdevice = ncontrol->subdevice;
if (ncontrol->name) { if (ncontrol->name) {
strlcpy(kctl->id.name, ncontrol->name, sizeof(kctl->id.name)); strscpy(kctl->id.name, ncontrol->name, sizeof(kctl->id.name));
if (strcmp(ncontrol->name, kctl->id.name) != 0) if (strcmp(ncontrol->name, kctl->id.name) != 0)
pr_warn("ALSA: Control name '%s' truncated to '%s'\n", pr_warn("ALSA: Control name '%s' truncated to '%s'\n",
ncontrol->name, kctl->id.name); ncontrol->name, kctl->id.name);
@ -701,12 +701,12 @@ static int snd_ctl_card_info(struct snd_card *card, struct snd_ctl_file * ctl,
return -ENOMEM; return -ENOMEM;
down_read(&snd_ioctl_rwsem); down_read(&snd_ioctl_rwsem);
info->card = card->number; info->card = card->number;
strlcpy(info->id, card->id, sizeof(info->id)); strscpy(info->id, card->id, sizeof(info->id));
strlcpy(info->driver, card->driver, sizeof(info->driver)); strscpy(info->driver, card->driver, sizeof(info->driver));
strlcpy(info->name, card->shortname, sizeof(info->name)); strscpy(info->name, card->shortname, sizeof(info->name));
strlcpy(info->longname, card->longname, sizeof(info->longname)); strscpy(info->longname, card->longname, sizeof(info->longname));
strlcpy(info->mixername, card->mixername, sizeof(info->mixername)); strscpy(info->mixername, card->mixername, sizeof(info->mixername));
strlcpy(info->components, card->components, sizeof(info->components)); strscpy(info->components, card->components, sizeof(info->components));
up_read(&snd_ioctl_rwsem); up_read(&snd_ioctl_rwsem);
if (copy_to_user(arg, info, sizeof(struct snd_ctl_card_info))) { if (copy_to_user(arg, info, sizeof(struct snd_ctl_card_info))) {
kfree(info); kfree(info);
@ -836,7 +836,7 @@ static void fill_remaining_elem_value(struct snd_ctl_elem_value *control,
{ {
size_t offset = value_sizes[info->type] * info->count; size_t offset = value_sizes[info->type] * info->count;
offset = (offset + sizeof(u32) - 1) / sizeof(u32); offset = DIV_ROUND_UP(offset, sizeof(u32));
memset32((u32 *)control->value.bytes.data + offset, pattern, memset32((u32 *)control->value.bytes.data + offset, pattern,
sizeof(control->value) / sizeof(u32) - offset); sizeof(control->value) / sizeof(u32) - offset);
} }
@ -928,7 +928,7 @@ static int sanity_check_elem_value(struct snd_card *card,
/* check whether the remaining area kept untouched */ /* check whether the remaining area kept untouched */
offset = value_sizes[info->type] * info->count; offset = value_sizes[info->type] * info->count;
offset = (offset + sizeof(u32) - 1) / sizeof(u32); offset = DIV_ROUND_UP(offset, sizeof(u32));
p = (u32 *)control->value.bytes.data + offset; p = (u32 *)control->value.bytes.data + offset;
for (; offset < sizeof(control->value) / sizeof(u32); offset++, p++) { for (; offset < sizeof(control->value) / sizeof(u32); offset++, p++) {
if (*p != pattern) { if (*p != pattern) {
@ -2137,7 +2137,7 @@ int snd_ctl_enum_info(struct snd_ctl_elem_info *info, unsigned int channels,
WARN(strlen(names[info->value.enumerated.item]) >= sizeof(info->value.enumerated.name), WARN(strlen(names[info->value.enumerated.item]) >= sizeof(info->value.enumerated.name),
"ALSA: too long item name '%s'\n", "ALSA: too long item name '%s'\n",
names[info->value.enumerated.item]); names[info->value.enumerated.item]);
strlcpy(info->value.enumerated.name, strscpy(info->value.enumerated.name,
names[info->value.enumerated.item], names[info->value.enumerated.item],
sizeof(info->value.enumerated.name)); sizeof(info->value.enumerated.name));
return 0; return 0;

View File

@ -35,7 +35,7 @@ static int get_available_index(struct snd_card *card, const char *name)
sid.index = 0; sid.index = 0;
sid.iface = SNDRV_CTL_ELEM_IFACE_CARD; sid.iface = SNDRV_CTL_ELEM_IFACE_CARD;
strlcpy(sid.name, name, sizeof(sid.name)); strscpy(sid.name, name, sizeof(sid.name));
while (snd_ctl_find_id(card, &sid)) { while (snd_ctl_find_id(card, &sid)) {
sid.index++; sid.index++;

View File

@ -177,8 +177,8 @@ static int snd_hwdep_info(struct snd_hwdep *hw,
memset(&info, 0, sizeof(info)); memset(&info, 0, sizeof(info));
info.card = hw->card->number; info.card = hw->card->number;
strlcpy(info.id, hw->id, sizeof(info.id)); strscpy(info.id, hw->id, sizeof(info.id));
strlcpy(info.name, hw->name, sizeof(info.name)); strscpy(info.name, hw->name, sizeof(info.name));
info.iface = hw->iface; info.iface = hw->iface;
if (copy_to_user(_info, &info, sizeof(info))) if (copy_to_user(_info, &info, sizeof(info)))
return -EFAULT; return -EFAULT;
@ -379,7 +379,7 @@ int snd_hwdep_new(struct snd_card *card, char *id, int device,
hwdep->card = card; hwdep->card = card;
hwdep->device = device; hwdep->device = device;
if (id) if (id)
strlcpy(hwdep->id, id, sizeof(hwdep->id)); strscpy(hwdep->id, id, sizeof(hwdep->id));
snd_device_initialize(&hwdep->dev, card); snd_device_initialize(&hwdep->dev, card);
hwdep->dev.release = release_hwdep_device; hwdep->dev.release = release_hwdep_device;

View File

@ -13,7 +13,9 @@
#include <linux/time.h> #include <linux/time.h>
#include <linux/ctype.h> #include <linux/ctype.h>
#include <linux/pm.h> #include <linux/pm.h>
#include <linux/debugfs.h>
#include <linux/completion.h> #include <linux/completion.h>
#include <linux/interrupt.h>
#include <sound/core.h> #include <sound/core.h>
#include <sound/control.h> #include <sound/control.h>
@ -161,6 +163,9 @@ int snd_card_new(struct device *parent, int idx, const char *xid,
{ {
struct snd_card *card; struct snd_card *card;
int err; int err;
#ifdef CONFIG_SND_DEBUG
char name[8];
#endif
if (snd_BUG_ON(!card_ret)) if (snd_BUG_ON(!card_ret))
return -EINVAL; return -EINVAL;
@ -174,7 +179,7 @@ int snd_card_new(struct device *parent, int idx, const char *xid,
if (extra_size > 0) if (extra_size > 0)
card->private_data = (char *)card + sizeof(struct snd_card); card->private_data = (char *)card + sizeof(struct snd_card);
if (xid) if (xid)
strlcpy(card->id, xid, sizeof(card->id)); strscpy(card->id, xid, sizeof(card->id));
err = 0; err = 0;
mutex_lock(&snd_card_mutex); mutex_lock(&snd_card_mutex);
if (idx < 0) /* first check the matching module-name slot */ if (idx < 0) /* first check the matching module-name slot */
@ -244,6 +249,12 @@ int snd_card_new(struct device *parent, int idx, const char *xid,
dev_err(parent, "unable to create card info\n"); dev_err(parent, "unable to create card info\n");
goto __error_ctl; goto __error_ctl;
} }
#ifdef CONFIG_SND_DEBUG
sprintf(name, "card%d", idx);
card->debugfs_root = debugfs_create_dir(name, sound_debugfs_root);
#endif
*card_ret = card; *card_ret = card;
return 0; return 0;
@ -416,6 +427,9 @@ int snd_card_disconnect(struct snd_card *card)
/* notify all devices that we are disconnected */ /* notify all devices that we are disconnected */
snd_device_disconnect_all(card); snd_device_disconnect_all(card);
if (card->sync_irq > 0)
synchronize_irq(card->sync_irq);
snd_info_card_disconnect(card); snd_info_card_disconnect(card);
if (card->registered) { if (card->registered) {
device_del(&card->card_dev); device_del(&card->card_dev);
@ -477,6 +491,10 @@ static int snd_card_do_free(struct snd_card *card)
dev_warn(card->dev, "unable to free card info\n"); dev_warn(card->dev, "unable to free card info\n");
/* Not fatal error */ /* Not fatal error */
} }
#ifdef CONFIG_SND_DEBUG
debugfs_remove(card->debugfs_root);
card->debugfs_root = NULL;
#endif
if (card->release_completion) if (card->release_completion)
complete(card->release_completion); complete(card->release_completion);
kfree(card); kfree(card);
@ -526,6 +544,7 @@ int snd_card_free(struct snd_card *card)
return ret; return ret;
/* wait, until all devices are ready for the free operation */ /* wait, until all devices are ready for the free operation */
wait_for_completion(&released); wait_for_completion(&released);
return 0; return 0;
} }
EXPORT_SYMBOL(snd_card_free); EXPORT_SYMBOL(snd_card_free);
@ -623,7 +642,7 @@ static void snd_card_set_id_no_lock(struct snd_card *card, const char *src,
/* last resort... */ /* last resort... */
dev_err(card->dev, "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) if (card->proc_root->name)
strlcpy(card->id, card->proc_root->name, sizeof(card->id)); strscpy(card->id, card->proc_root->name, sizeof(card->id));
} }
/** /**

View File

@ -8,6 +8,9 @@
#include <linux/input.h> #include <linux/input.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/ctype.h>
#include <linux/mm.h>
#include <linux/debugfs.h>
#include <sound/jack.h> #include <sound/jack.h>
#include <sound/core.h> #include <sound/core.h>
#include <sound/control.h> #include <sound/control.h>
@ -16,6 +19,11 @@ struct snd_jack_kctl {
struct snd_kcontrol *kctl; struct snd_kcontrol *kctl;
struct list_head list; /* list of controls belong to the same jack */ struct list_head list; /* list of controls belong to the same jack */
unsigned int mask_bits; /* only masked status bits are reported via kctl */ unsigned int mask_bits; /* only masked status bits are reported via kctl */
struct snd_jack *jack; /* pointer to struct snd_jack */
bool sw_inject_enable; /* allow to inject plug event via debugfs */
#ifdef CONFIG_SND_JACK_INJECTION_DEBUG
struct dentry *jack_debugfs_root; /* jack_kctl debugfs root */
#endif
}; };
#ifdef CONFIG_SND_JACK_INPUT_DEV #ifdef CONFIG_SND_JACK_INPUT_DEV
@ -109,12 +117,291 @@ static int snd_jack_dev_register(struct snd_device *device)
} }
#endif /* CONFIG_SND_JACK_INPUT_DEV */ #endif /* CONFIG_SND_JACK_INPUT_DEV */
#ifdef CONFIG_SND_JACK_INJECTION_DEBUG
static void snd_jack_inject_report(struct snd_jack_kctl *jack_kctl, int status)
{
struct snd_jack *jack;
#ifdef CONFIG_SND_JACK_INPUT_DEV
int i;
#endif
if (!jack_kctl)
return;
jack = jack_kctl->jack;
if (jack_kctl->sw_inject_enable)
snd_kctl_jack_report(jack->card, jack_kctl->kctl,
status & jack_kctl->mask_bits);
#ifdef CONFIG_SND_JACK_INPUT_DEV
if (!jack->input_dev)
return;
for (i = 0; i < ARRAY_SIZE(jack->key); i++) {
int testbit = ((SND_JACK_BTN_0 >> i) & jack_kctl->mask_bits);
if (jack->type & testbit)
input_report_key(jack->input_dev, jack->key[i],
status & testbit);
}
for (i = 0; i < ARRAY_SIZE(jack_switch_types); i++) {
int testbit = ((1 << i) & jack_kctl->mask_bits);
if (jack->type & testbit)
input_report_switch(jack->input_dev,
jack_switch_types[i],
status & testbit);
}
input_sync(jack->input_dev);
#endif /* CONFIG_SND_JACK_INPUT_DEV */
}
static ssize_t sw_inject_enable_read(struct file *file,
char __user *to, size_t count, loff_t *ppos)
{
struct snd_jack_kctl *jack_kctl = file->private_data;
int len, ret;
char buf[128];
len = scnprintf(buf, sizeof(buf), "%s: %s\t\t%s: %i\n", "Jack", jack_kctl->kctl->id.name,
"Inject Enabled", jack_kctl->sw_inject_enable);
ret = simple_read_from_buffer(to, count, ppos, buf, len);
return ret;
}
static ssize_t sw_inject_enable_write(struct file *file,
const char __user *from, size_t count, loff_t *ppos)
{
struct snd_jack_kctl *jack_kctl = file->private_data;
int ret, err;
unsigned long enable;
char buf[8] = { 0 };
ret = simple_write_to_buffer(buf, sizeof(buf) - 1, ppos, from, count);
err = kstrtoul(buf, 0, &enable);
if (err)
return err;
if (jack_kctl->sw_inject_enable == (!!enable))
return ret;
jack_kctl->sw_inject_enable = !!enable;
if (!jack_kctl->sw_inject_enable)
snd_jack_report(jack_kctl->jack, jack_kctl->jack->hw_status_cache);
return ret;
}
static ssize_t jackin_inject_write(struct file *file,
const char __user *from, size_t count, loff_t *ppos)
{
struct snd_jack_kctl *jack_kctl = file->private_data;
int ret, err;
unsigned long enable;
char buf[8] = { 0 };
if (!jack_kctl->sw_inject_enable)
return -EINVAL;
ret = simple_write_to_buffer(buf, sizeof(buf) - 1, ppos, from, count);
err = kstrtoul(buf, 0, &enable);
if (err)
return err;
snd_jack_inject_report(jack_kctl, !!enable ? jack_kctl->mask_bits : 0);
return ret;
}
static ssize_t jack_kctl_id_read(struct file *file,
char __user *to, size_t count, loff_t *ppos)
{
struct snd_jack_kctl *jack_kctl = file->private_data;
char buf[64];
int len, ret;
len = scnprintf(buf, sizeof(buf), "%s\n", jack_kctl->kctl->id.name);
ret = simple_read_from_buffer(to, count, ppos, buf, len);
return ret;
}
/* the bit definition is aligned with snd_jack_types in jack.h */
static const char * const jack_events_name[] = {
"HEADPHONE(0x0001)", "MICROPHONE(0x0002)", "LINEOUT(0x0004)",
"MECHANICAL(0x0008)", "VIDEOOUT(0x0010)", "LINEIN(0x0020)",
"", "", "", "BTN_5(0x0200)", "BTN_4(0x0400)", "BTN_3(0x0800)",
"BTN_2(0x1000)", "BTN_1(0x2000)", "BTN_0(0x4000)", "",
};
/* the recommended buffer size is 256 */
static int parse_mask_bits(unsigned int mask_bits, char *buf, size_t buf_size)
{
int i;
scnprintf(buf, buf_size, "0x%04x", mask_bits);
for (i = 0; i < ARRAY_SIZE(jack_events_name); i++)
if (mask_bits & (1 << i)) {
strlcat(buf, " ", buf_size);
strlcat(buf, jack_events_name[i], buf_size);
}
strlcat(buf, "\n", buf_size);
return strlen(buf);
}
static ssize_t jack_kctl_mask_bits_read(struct file *file,
char __user *to, size_t count, loff_t *ppos)
{
struct snd_jack_kctl *jack_kctl = file->private_data;
char buf[256];
int len, ret;
len = parse_mask_bits(jack_kctl->mask_bits, buf, sizeof(buf));
ret = simple_read_from_buffer(to, count, ppos, buf, len);
return ret;
}
static ssize_t jack_kctl_status_read(struct file *file,
char __user *to, size_t count, loff_t *ppos)
{
struct snd_jack_kctl *jack_kctl = file->private_data;
char buf[16];
int len, ret;
len = scnprintf(buf, sizeof(buf), "%s\n", jack_kctl->kctl->private_value ?
"Plugged" : "Unplugged");
ret = simple_read_from_buffer(to, count, ppos, buf, len);
return ret;
}
#ifdef CONFIG_SND_JACK_INPUT_DEV
static ssize_t jack_type_read(struct file *file,
char __user *to, size_t count, loff_t *ppos)
{
struct snd_jack_kctl *jack_kctl = file->private_data;
char buf[256];
int len, ret;
len = parse_mask_bits(jack_kctl->jack->type, buf, sizeof(buf));
ret = simple_read_from_buffer(to, count, ppos, buf, len);
return ret;
}
static const struct file_operations jack_type_fops = {
.open = simple_open,
.read = jack_type_read,
.llseek = default_llseek,
};
#endif
static const struct file_operations sw_inject_enable_fops = {
.open = simple_open,
.read = sw_inject_enable_read,
.write = sw_inject_enable_write,
.llseek = default_llseek,
};
static const struct file_operations jackin_inject_fops = {
.open = simple_open,
.write = jackin_inject_write,
.llseek = default_llseek,
};
static const struct file_operations jack_kctl_id_fops = {
.open = simple_open,
.read = jack_kctl_id_read,
.llseek = default_llseek,
};
static const struct file_operations jack_kctl_mask_bits_fops = {
.open = simple_open,
.read = jack_kctl_mask_bits_read,
.llseek = default_llseek,
};
static const struct file_operations jack_kctl_status_fops = {
.open = simple_open,
.read = jack_kctl_status_read,
.llseek = default_llseek,
};
static int snd_jack_debugfs_add_inject_node(struct snd_jack *jack,
struct snd_jack_kctl *jack_kctl)
{
char *tname;
int i;
/* Don't create injection interface for Phantom jacks */
if (strstr(jack_kctl->kctl->id.name, "Phantom"))
return 0;
tname = kstrdup(jack_kctl->kctl->id.name, GFP_KERNEL);
if (!tname)
return -ENOMEM;
/* replace the chars which are not suitable for folder's name with _ */
for (i = 0; tname[i]; i++)
if (!isalnum(tname[i]))
tname[i] = '_';
jack_kctl->jack_debugfs_root = debugfs_create_dir(tname, jack->card->debugfs_root);
kfree(tname);
debugfs_create_file("sw_inject_enable", 0644, jack_kctl->jack_debugfs_root, jack_kctl,
&sw_inject_enable_fops);
debugfs_create_file("jackin_inject", 0200, jack_kctl->jack_debugfs_root, jack_kctl,
&jackin_inject_fops);
debugfs_create_file("kctl_id", 0444, jack_kctl->jack_debugfs_root, jack_kctl,
&jack_kctl_id_fops);
debugfs_create_file("mask_bits", 0444, jack_kctl->jack_debugfs_root, jack_kctl,
&jack_kctl_mask_bits_fops);
debugfs_create_file("status", 0444, jack_kctl->jack_debugfs_root, jack_kctl,
&jack_kctl_status_fops);
#ifdef CONFIG_SND_JACK_INPUT_DEV
debugfs_create_file("type", 0444, jack_kctl->jack_debugfs_root, jack_kctl,
&jack_type_fops);
#endif
return 0;
}
static void snd_jack_debugfs_clear_inject_node(struct snd_jack_kctl *jack_kctl)
{
debugfs_remove(jack_kctl->jack_debugfs_root);
jack_kctl->jack_debugfs_root = NULL;
}
#else /* CONFIG_SND_JACK_INJECTION_DEBUG */
static int snd_jack_debugfs_add_inject_node(struct snd_jack *jack,
struct snd_jack_kctl *jack_kctl)
{
return 0;
}
static void snd_jack_debugfs_clear_inject_node(struct snd_jack_kctl *jack_kctl)
{
}
#endif /* CONFIG_SND_JACK_INJECTION_DEBUG */
static void snd_jack_kctl_private_free(struct snd_kcontrol *kctl) static void snd_jack_kctl_private_free(struct snd_kcontrol *kctl)
{ {
struct snd_jack_kctl *jack_kctl; struct snd_jack_kctl *jack_kctl;
jack_kctl = kctl->private_data; jack_kctl = kctl->private_data;
if (jack_kctl) { if (jack_kctl) {
snd_jack_debugfs_clear_inject_node(jack_kctl);
list_del(&jack_kctl->list); list_del(&jack_kctl->list);
kfree(jack_kctl); kfree(jack_kctl);
} }
@ -122,7 +409,9 @@ static void snd_jack_kctl_private_free(struct snd_kcontrol *kctl)
static void snd_jack_kctl_add(struct snd_jack *jack, struct snd_jack_kctl *jack_kctl) static void snd_jack_kctl_add(struct snd_jack *jack, struct snd_jack_kctl *jack_kctl)
{ {
jack_kctl->jack = jack;
list_add_tail(&jack_kctl->list, &jack->kctl_list); list_add_tail(&jack_kctl->list, &jack->kctl_list);
snd_jack_debugfs_add_inject_node(jack, jack_kctl);
} }
static struct snd_jack_kctl * snd_jack_kctl_new(struct snd_card *card, const char *name, unsigned int mask) static struct snd_jack_kctl * snd_jack_kctl_new(struct snd_card *card, const char *name, unsigned int mask)
@ -340,6 +629,7 @@ EXPORT_SYMBOL(snd_jack_set_key);
void snd_jack_report(struct snd_jack *jack, int status) void snd_jack_report(struct snd_jack *jack, int status)
{ {
struct snd_jack_kctl *jack_kctl; struct snd_jack_kctl *jack_kctl;
unsigned int mask_bits = 0;
#ifdef CONFIG_SND_JACK_INPUT_DEV #ifdef CONFIG_SND_JACK_INPUT_DEV
int i; int i;
#endif #endif
@ -347,16 +637,21 @@ void snd_jack_report(struct snd_jack *jack, int status)
if (!jack) if (!jack)
return; return;
jack->hw_status_cache = status;
list_for_each_entry(jack_kctl, &jack->kctl_list, list) list_for_each_entry(jack_kctl, &jack->kctl_list, list)
snd_kctl_jack_report(jack->card, jack_kctl->kctl, if (jack_kctl->sw_inject_enable)
status & jack_kctl->mask_bits); mask_bits |= jack_kctl->mask_bits;
else
snd_kctl_jack_report(jack->card, jack_kctl->kctl,
status & jack_kctl->mask_bits);
#ifdef CONFIG_SND_JACK_INPUT_DEV #ifdef CONFIG_SND_JACK_INPUT_DEV
if (!jack->input_dev) if (!jack->input_dev)
return; return;
for (i = 0; i < ARRAY_SIZE(jack->key); i++) { for (i = 0; i < ARRAY_SIZE(jack->key); i++) {
int testbit = SND_JACK_BTN_0 >> i; int testbit = ((SND_JACK_BTN_0 >> i) & ~mask_bits);
if (jack->type & testbit) if (jack->type & testbit)
input_report_key(jack->input_dev, jack->key[i], input_report_key(jack->input_dev, jack->key[i],
@ -364,7 +659,8 @@ void snd_jack_report(struct snd_jack *jack, int status)
} }
for (i = 0; i < ARRAY_SIZE(jack_switch_types); i++) { for (i = 0; i < ARRAY_SIZE(jack_switch_types); i++) {
int testbit = 1 << i; int testbit = ((1 << i) & ~mask_bits);
if (jack->type & testbit) if (jack->type & testbit)
input_report_switch(jack->input_dev, input_report_switch(jack->input_dev,
jack_switch_types[i], jack_switch_types[i],

View File

@ -87,8 +87,8 @@ static int snd_mixer_oss_info(struct snd_mixer_oss_file *fmixer,
struct mixer_info info; struct mixer_info info;
memset(&info, 0, sizeof(info)); memset(&info, 0, sizeof(info));
strlcpy(info.id, mixer && mixer->id[0] ? mixer->id : card->driver, sizeof(info.id)); strscpy(info.id, mixer && mixer->id[0] ? mixer->id : card->driver, sizeof(info.id));
strlcpy(info.name, mixer && mixer->name[0] ? mixer->name : card->mixername, sizeof(info.name)); strscpy(info.name, mixer && mixer->name[0] ? mixer->name : card->mixername, sizeof(info.name));
info.modify_counter = card->mixer_oss_change_count; info.modify_counter = card->mixer_oss_change_count;
if (copy_to_user(_info, &info, sizeof(info))) if (copy_to_user(_info, &info, sizeof(info)))
return -EFAULT; return -EFAULT;
@ -103,8 +103,8 @@ static int snd_mixer_oss_info_obsolete(struct snd_mixer_oss_file *fmixer,
_old_mixer_info info; _old_mixer_info info;
memset(&info, 0, sizeof(info)); memset(&info, 0, sizeof(info));
strlcpy(info.id, mixer && mixer->id[0] ? mixer->id : card->driver, sizeof(info.id)); strscpy(info.id, mixer && mixer->id[0] ? mixer->id : card->driver, sizeof(info.id));
strlcpy(info.name, mixer && mixer->name[0] ? mixer->name : card->mixername, sizeof(info.name)); strscpy(info.name, mixer && mixer->name[0] ? mixer->name : card->mixername, sizeof(info.name));
if (copy_to_user(_info, &info, sizeof(info))) if (copy_to_user(_info, &info, sizeof(info)))
return -EFAULT; return -EFAULT;
return 0; return 0;
@ -418,7 +418,7 @@ static long snd_mixer_oss_conv(long val, long omin, long omax, long nmin, long n
if (orange == 0) if (orange == 0)
return 0; return 0;
return ((nrange * (val - omin)) + (orange / 2)) / orange + nmin; return DIV_ROUND_CLOSEST(nrange * (val - omin), orange) + nmin;
} }
/* convert from alsa native to oss values (0-100) */ /* convert from alsa native to oss values (0-100) */
@ -499,7 +499,7 @@ static struct snd_kcontrol *snd_mixer_oss_test_id(struct snd_mixer_oss *mixer, c
memset(&id, 0, sizeof(id)); memset(&id, 0, sizeof(id));
id.iface = SNDRV_CTL_ELEM_IFACE_MIXER; id.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
strlcpy(id.name, name, sizeof(id.name)); strscpy(id.name, name, sizeof(id.name));
id.index = index; id.index = index;
return snd_ctl_find_id(card, &id); return snd_ctl_find_id(card, &id);
} }
@ -1355,7 +1355,7 @@ static int snd_mixer_oss_notify_handler(struct snd_card *card, int cmd)
mixer->oss_dev_alloc = 1; mixer->oss_dev_alloc = 1;
mixer->card = card; mixer->card = card;
if (*card->mixername) if (*card->mixername)
strlcpy(mixer->name, card->mixername, sizeof(mixer->name)); strscpy(mixer->name, card->mixername, sizeof(mixer->name));
else else
snprintf(mixer->name, sizeof(mixer->name), snprintf(mixer->name, sizeof(mixer->name),
"mixer%i", card->number); "mixer%i", card->number);

View File

@ -193,7 +193,7 @@ static snd_pcm_sframes_t rate_src_frames(struct snd_pcm_plugin *plugin, snd_pcm_
if (plugin->src_format.rate < plugin->dst_format.rate) { if (plugin->src_format.rate < plugin->dst_format.rate) {
res = (((frames * data->pitch) + (BITS/2)) >> SHIFT); res = (((frames * data->pitch) + (BITS/2)) >> SHIFT);
} else { } else {
res = (((frames << SHIFT) + (data->pitch / 2)) / data->pitch); res = DIV_ROUND_CLOSEST(frames << SHIFT, data->pitch);
} }
if (data->old_src_frames > 0) { if (data->old_src_frames > 0) {
snd_pcm_sframes_t frames1 = frames, res1 = data->old_dst_frames; snd_pcm_sframes_t frames1 = frames, res1 = data->old_dst_frames;
@ -224,7 +224,7 @@ static snd_pcm_sframes_t rate_dst_frames(struct snd_pcm_plugin *plugin, snd_pcm_
return 0; return 0;
data = (struct rate_priv *)plugin->extra_data; data = (struct rate_priv *)plugin->extra_data;
if (plugin->src_format.rate < plugin->dst_format.rate) { if (plugin->src_format.rate < plugin->dst_format.rate) {
res = (((frames << SHIFT) + (data->pitch / 2)) / data->pitch); res = DIV_ROUND_CLOSEST(frames << SHIFT, data->pitch);
} else { } else {
res = (((frames * data->pitch) + (BITS/2)) >> SHIFT); res = (((frames * data->pitch) + (BITS/2)) >> SHIFT);
} }

View File

@ -729,7 +729,7 @@ static int _snd_pcm_new(struct snd_card *card, const char *id, int device,
init_waitqueue_head(&pcm->open_wait); init_waitqueue_head(&pcm->open_wait);
INIT_LIST_HEAD(&pcm->list); INIT_LIST_HEAD(&pcm->list);
if (id) if (id)
strlcpy(pcm->id, id, sizeof(pcm->id)); strscpy(pcm->id, id, sizeof(pcm->id));
err = snd_pcm_new_stream(pcm, SNDRV_PCM_STREAM_PLAYBACK, err = snd_pcm_new_stream(pcm, SNDRV_PCM_STREAM_PLAYBACK,
playback_count); playback_count);
@ -1095,22 +1095,23 @@ static int snd_pcm_dev_disconnect(struct snd_device *device)
mutex_lock(&pcm->open_mutex); mutex_lock(&pcm->open_mutex);
wake_up(&pcm->open_wait); wake_up(&pcm->open_wait);
list_del_init(&pcm->list); list_del_init(&pcm->list);
for (cidx = 0; cidx < 2; cidx++) {
for (substream = pcm->streams[cidx].substream; substream; substream = substream->next) { for_each_pcm_substream(pcm, cidx, substream) {
snd_pcm_stream_lock_irq(substream); snd_pcm_stream_lock_irq(substream);
if (substream->runtime) { if (substream->runtime) {
if (snd_pcm_running(substream)) if (snd_pcm_running(substream))
snd_pcm_stop(substream, snd_pcm_stop(substream, SNDRV_PCM_STATE_DISCONNECTED);
SNDRV_PCM_STATE_DISCONNECTED); /* to be sure, set the state unconditionally */
/* to be sure, set the state unconditionally */ substream->runtime->status->state = SNDRV_PCM_STATE_DISCONNECTED;
substream->runtime->status->state = SNDRV_PCM_STATE_DISCONNECTED; wake_up(&substream->runtime->sleep);
wake_up(&substream->runtime->sleep); wake_up(&substream->runtime->tsleep);
wake_up(&substream->runtime->tsleep);
}
snd_pcm_stream_unlock_irq(substream);
} }
snd_pcm_stream_unlock_irq(substream);
} }
for_each_pcm_substream(pcm, cidx, substream)
snd_pcm_sync_stop(substream, false);
pcm_call_notify(pcm, n_disconnect); pcm_call_notify(pcm, n_disconnect);
for (cidx = 0; cidx < 2; cidx++) { for (cidx = 0; cidx < 2; cidx++) {
snd_unregister_device(&pcm->streams[cidx].dev); snd_unregister_device(&pcm->streams[cidx].dev);

View File

@ -125,6 +125,8 @@ void snd_dmaengine_pcm_set_config_from_dai_data(
} }
slave_config->slave_id = dma_data->slave_id; slave_config->slave_id = dma_data->slave_id;
slave_config->peripheral_config = dma_data->peripheral_config;
slave_config->peripheral_size = dma_data->peripheral_size;
} }
EXPORT_SYMBOL_GPL(snd_dmaengine_pcm_set_config_from_dai_data); EXPORT_SYMBOL_GPL(snd_dmaengine_pcm_set_config_from_dai_data);

View File

@ -63,6 +63,7 @@ static inline void snd_pcm_timer_done(struct snd_pcm_substream *substream) {}
void __snd_pcm_xrun(struct snd_pcm_substream *substream); void __snd_pcm_xrun(struct snd_pcm_substream *substream);
void snd_pcm_group_init(struct snd_pcm_group *group); void snd_pcm_group_init(struct snd_pcm_group *group);
void snd_pcm_sync_stop(struct snd_pcm_substream *substream, bool sync_irq);
#ifdef CONFIG_SND_DMA_SGBUF #ifdef CONFIG_SND_DMA_SGBUF
struct page *snd_pcm_sgbuf_ops_page(struct snd_pcm_substream *substream, struct page *snd_pcm_sgbuf_ops_page(struct snd_pcm_substream *substream,
@ -71,4 +72,10 @@ struct page *snd_pcm_sgbuf_ops_page(struct snd_pcm_substream *substream,
#define PCM_RUNTIME_CHECK(sub) snd_BUG_ON(!(sub) || !(sub)->runtime) #define PCM_RUNTIME_CHECK(sub) snd_BUG_ON(!(sub) || !(sub)->runtime)
/* loop over all PCM substreams */
#define for_each_pcm_substream(pcm, str, subs) \
for ((str) = 0; (str) < 2; (str)++) \
for ((subs) = (pcm)->streams[str].substream; (subs); \
(subs) = (subs)->next)
#endif /* __SOUND_CORE_PCM_LOCAL_H */ #endif /* __SOUND_CORE_PCM_LOCAL_H */

View File

@ -111,9 +111,8 @@ void snd_pcm_lib_preallocate_free_for_all(struct snd_pcm *pcm)
struct snd_pcm_substream *substream; struct snd_pcm_substream *substream;
int stream; int stream;
for (stream = 0; stream < 2; stream++) for_each_pcm_substream(pcm, stream, substream)
for (substream = pcm->streams[stream].substream; substream; substream = substream->next) snd_pcm_lib_preallocate_free(substream);
snd_pcm_lib_preallocate_free(substream);
} }
EXPORT_SYMBOL(snd_pcm_lib_preallocate_free_for_all); EXPORT_SYMBOL(snd_pcm_lib_preallocate_free_for_all);
@ -246,11 +245,8 @@ static void preallocate_pages_for_all(struct snd_pcm *pcm, int type,
struct snd_pcm_substream *substream; struct snd_pcm_substream *substream;
int stream; int stream;
for (stream = 0; stream < 2; stream++) for_each_pcm_substream(pcm, stream, substream)
for (substream = pcm->streams[stream].substream; substream; preallocate_pages(substream, type, data, size, max, managed);
substream = substream->next)
preallocate_pages(substream, type, data, size, max,
managed);
} }
/** /**

View File

@ -209,13 +209,13 @@ int snd_pcm_info(struct snd_pcm_substream *substream, struct snd_pcm_info *info)
info->device = pcm->device; info->device = pcm->device;
info->stream = substream->stream; info->stream = substream->stream;
info->subdevice = substream->number; info->subdevice = substream->number;
strlcpy(info->id, pcm->id, sizeof(info->id)); strscpy(info->id, pcm->id, sizeof(info->id));
strlcpy(info->name, pcm->name, sizeof(info->name)); strscpy(info->name, pcm->name, sizeof(info->name));
info->dev_class = pcm->dev_class; info->dev_class = pcm->dev_class;
info->dev_subclass = pcm->dev_subclass; info->dev_subclass = pcm->dev_subclass;
info->subdevices_count = pstr->substream_count; info->subdevices_count = pstr->substream_count;
info->subdevices_avail = pstr->substream_count - pstr->substream_opened; info->subdevices_avail = pstr->substream_count - pstr->substream_opened;
strlcpy(info->subname, substream->name, sizeof(info->subname)); strscpy(info->subname, substream->name, sizeof(info->subname));
return 0; return 0;
} }
@ -583,13 +583,13 @@ static inline void snd_pcm_timer_notify(struct snd_pcm_substream *substream,
#endif #endif
} }
static void snd_pcm_sync_stop(struct snd_pcm_substream *substream) void snd_pcm_sync_stop(struct snd_pcm_substream *substream, bool sync_irq)
{ {
if (substream->runtime->stop_operating) { if (substream->runtime && substream->runtime->stop_operating) {
substream->runtime->stop_operating = false; substream->runtime->stop_operating = false;
if (substream->ops->sync_stop) if (substream->ops && substream->ops->sync_stop)
substream->ops->sync_stop(substream); substream->ops->sync_stop(substream);
else if (substream->pcm->card->sync_irq > 0) else if (sync_irq && substream->pcm->card->sync_irq > 0)
synchronize_irq(substream->pcm->card->sync_irq); synchronize_irq(substream->pcm->card->sync_irq);
} }
} }
@ -686,7 +686,7 @@ static int snd_pcm_hw_params(struct snd_pcm_substream *substream,
if (atomic_read(&substream->mmap_count)) if (atomic_read(&substream->mmap_count))
return -EBADFD; return -EBADFD;
snd_pcm_sync_stop(substream); snd_pcm_sync_stop(substream, true);
params->rmask = ~0U; params->rmask = ~0U;
err = snd_pcm_hw_refine(substream, params); err = snd_pcm_hw_refine(substream, params);
@ -809,7 +809,7 @@ static int do_hw_free(struct snd_pcm_substream *substream)
{ {
int result = 0; int result = 0;
snd_pcm_sync_stop(substream); snd_pcm_sync_stop(substream, true);
if (substream->ops->hw_free) if (substream->ops->hw_free)
result = substream->ops->hw_free(substream); result = substream->ops->hw_free(substream);
if (substream->managed_buffer_alloc) if (substream->managed_buffer_alloc)
@ -1421,8 +1421,10 @@ static int snd_pcm_do_stop(struct snd_pcm_substream *substream,
snd_pcm_state_t state) snd_pcm_state_t state)
{ {
if (substream->runtime->trigger_master == substream && if (substream->runtime->trigger_master == substream &&
snd_pcm_running(substream)) snd_pcm_running(substream)) {
substream->ops->trigger(substream, SNDRV_PCM_TRIGGER_STOP); substream->ops->trigger(substream, SNDRV_PCM_TRIGGER_STOP);
substream->runtime->stop_operating = true;
}
return 0; /* unconditonally stop all substreams */ return 0; /* unconditonally stop all substreams */
} }
@ -1435,7 +1437,6 @@ static void snd_pcm_post_stop(struct snd_pcm_substream *substream,
runtime->status->state = state; runtime->status->state = state;
snd_pcm_timer_notify(substream, SNDRV_TIMER_EVENT_MSTOP); snd_pcm_timer_notify(substream, SNDRV_TIMER_EVENT_MSTOP);
} }
runtime->stop_operating = true;
wake_up(&runtime->sleep); wake_up(&runtime->sleep);
wake_up(&runtime->tsleep); wake_up(&runtime->tsleep);
} }
@ -1615,6 +1616,7 @@ static int snd_pcm_do_suspend(struct snd_pcm_substream *substream,
if (! snd_pcm_running(substream)) if (! snd_pcm_running(substream))
return 0; return 0;
substream->ops->trigger(substream, SNDRV_PCM_TRIGGER_SUSPEND); substream->ops->trigger(substream, SNDRV_PCM_TRIGGER_SUSPEND);
runtime->stop_operating = true;
return 0; /* suspend unconditionally */ return 0; /* suspend unconditionally */
} }
@ -1672,25 +1674,26 @@ int snd_pcm_suspend_all(struct snd_pcm *pcm)
if (! pcm) if (! pcm)
return 0; return 0;
for (stream = 0; stream < 2; stream++) { for_each_pcm_substream(pcm, stream, substream) {
for (substream = pcm->streams[stream].substream; /* FIXME: the open/close code should lock this as well */
substream; substream = substream->next) { if (!substream->runtime)
/* FIXME: the open/close code should lock this as well */ continue;
if (substream->runtime == NULL)
continue;
/* /*
* Skip BE dai link PCM's that are internal and may * Skip BE dai link PCM's that are internal and may
* not have their substream ops set. * not have their substream ops set.
*/ */
if (!substream->ops) if (!substream->ops)
continue; continue;
err = snd_pcm_suspend(substream); err = snd_pcm_suspend(substream);
if (err < 0 && err != -EBUSY) if (err < 0 && err != -EBUSY)
return err; return err;
}
} }
for_each_pcm_substream(pcm, stream, substream)
snd_pcm_sync_stop(substream, false);
return 0; return 0;
} }
EXPORT_SYMBOL(snd_pcm_suspend_all); EXPORT_SYMBOL(snd_pcm_suspend_all);
@ -1736,7 +1739,6 @@ static void snd_pcm_post_resume(struct snd_pcm_substream *substream,
snd_pcm_trigger_tstamp(substream); snd_pcm_trigger_tstamp(substream);
runtime->status->state = runtime->status->suspended_state; runtime->status->state = runtime->status->suspended_state;
snd_pcm_timer_notify(substream, SNDRV_TIMER_EVENT_MRESUME); snd_pcm_timer_notify(substream, SNDRV_TIMER_EVENT_MRESUME);
snd_pcm_sync_stop(substream);
} }
static const struct action_ops snd_pcm_action_resume = { static const struct action_ops snd_pcm_action_resume = {
@ -1866,7 +1868,7 @@ static int snd_pcm_do_prepare(struct snd_pcm_substream *substream,
snd_pcm_state_t state) snd_pcm_state_t state)
{ {
int err; int err;
snd_pcm_sync_stop(substream); snd_pcm_sync_stop(substream, true);
err = substream->ops->prepare(substream); err = substream->ops->prepare(substream);
if (err < 0) if (err < 0)
return err; return err;

View File

@ -1686,7 +1686,7 @@ int snd_rawmidi_new(struct snd_card *card, char *id, int device,
INIT_LIST_HEAD(&rmidi->streams[SNDRV_RAWMIDI_STREAM_OUTPUT].substreams); INIT_LIST_HEAD(&rmidi->streams[SNDRV_RAWMIDI_STREAM_OUTPUT].substreams);
if (id != NULL) if (id != NULL)
strlcpy(rmidi->id, id, sizeof(rmidi->id)); strscpy(rmidi->id, id, sizeof(rmidi->id));
snd_device_initialize(&rmidi->dev, card); snd_device_initialize(&rmidi->dev, card);
rmidi->dev.release = release_rawmidi_device; rmidi->dev.release = release_rawmidi_device;

View File

@ -173,7 +173,7 @@ snd_seq_oss_midi_check_new_port(struct snd_seq_port_info *pinfo)
snd_use_lock_init(&mdev->use_lock); snd_use_lock_init(&mdev->use_lock);
/* copy and truncate the name of synth device */ /* copy and truncate the name of synth device */
strlcpy(mdev->name, pinfo->name, sizeof(mdev->name)); strscpy(mdev->name, pinfo->name, sizeof(mdev->name));
/* create MIDI coder */ /* create MIDI coder */
if (snd_midi_event_new(MAX_MIDI_EVENT_BUF, &mdev->coder) < 0) { if (snd_midi_event_new(MAX_MIDI_EVENT_BUF, &mdev->coder) < 0) {
@ -647,7 +647,7 @@ snd_seq_oss_midi_make_info(struct seq_oss_devinfo *dp, int dev, struct midi_info
inf->device = dev; inf->device = dev;
inf->dev_type = 0; /* FIXME: ?? */ inf->dev_type = 0; /* FIXME: ?? */
inf->capabilities = 0; /* FIXME: ?? */ inf->capabilities = 0; /* FIXME: ?? */
strlcpy(inf->name, mdev->name, sizeof(inf->name)); strscpy(inf->name, mdev->name, sizeof(inf->name));
snd_use_lock_free(&mdev->use_lock); snd_use_lock_free(&mdev->use_lock);
return 0; return 0;
} }

View File

@ -107,7 +107,7 @@ snd_seq_oss_synth_probe(struct device *_dev)
snd_use_lock_init(&rec->use_lock); snd_use_lock_init(&rec->use_lock);
/* copy and truncate the name of synth device */ /* copy and truncate the name of synth device */
strlcpy(rec->name, dev->name, sizeof(rec->name)); strscpy(rec->name, dev->name, sizeof(rec->name));
/* registration */ /* registration */
spin_lock_irqsave(&register_lock, flags); spin_lock_irqsave(&register_lock, flags);
@ -617,7 +617,7 @@ snd_seq_oss_synth_make_info(struct seq_oss_devinfo *dp, int dev, struct synth_in
inf->synth_subtype = 0; inf->synth_subtype = 0;
inf->nr_voices = 16; inf->nr_voices = 16;
inf->device = dev; inf->device = dev;
strlcpy(inf->name, minf.name, sizeof(inf->name)); strscpy(inf->name, minf.name, sizeof(inf->name));
} else { } else {
if ((rec = get_synthdev(dp, dev)) == NULL) if ((rec = get_synthdev(dp, dev)) == NULL)
return -ENXIO; return -ENXIO;
@ -625,7 +625,7 @@ snd_seq_oss_synth_make_info(struct seq_oss_devinfo *dp, int dev, struct synth_in
inf->synth_subtype = rec->synth_subtype; inf->synth_subtype = rec->synth_subtype;
inf->nr_voices = rec->nr_voices; inf->nr_voices = rec->nr_voices;
inf->device = dev; inf->device = dev;
strlcpy(inf->name, rec->name, sizeof(inf->name)); strscpy(inf->name, rec->name, sizeof(inf->name));
snd_use_lock_free(&rec->use_lock); snd_use_lock_free(&rec->use_lock);
} }
return 0; return 0;

View File

@ -1584,7 +1584,7 @@ static int snd_seq_ioctl_get_queue_info(struct snd_seq_client *client,
info->queue = q->queue; info->queue = q->queue;
info->owner = q->owner; info->owner = q->owner;
info->locked = q->locked; info->locked = q->locked;
strlcpy(info->name, q->name, sizeof(info->name)); strscpy(info->name, q->name, sizeof(info->name));
queuefree(q); queuefree(q);
return 0; return 0;

View File

@ -290,7 +290,7 @@ int snd_seq_event_dup(struct snd_seq_pool *pool, struct snd_seq_event *event,
extlen = 0; extlen = 0;
if (snd_seq_ev_is_variable(event)) { if (snd_seq_ev_is_variable(event)) {
extlen = event->data.ext.len & ~SNDRV_SEQ_EXT_MASK; extlen = event->data.ext.len & ~SNDRV_SEQ_EXT_MASK;
ncells = (extlen + sizeof(struct snd_seq_event) - 1) / sizeof(struct snd_seq_event); ncells = DIV_ROUND_UP(extlen, sizeof(struct snd_seq_event));
} }
if (ncells >= pool->total_elements) if (ncells >= pool->total_elements)
return -ENOMEM; return -ENOMEM;

View File

@ -327,7 +327,7 @@ int snd_seq_set_port_info(struct snd_seq_client_port * port,
/* set port name */ /* set port name */
if (info->name[0]) if (info->name[0])
strlcpy(port->name, info->name, sizeof(port->name)); strscpy(port->name, info->name, sizeof(port->name));
/* set capabilities */ /* set capabilities */
port->capability = info->capability; port->capability = info->capability;
@ -356,7 +356,7 @@ int snd_seq_get_port_info(struct snd_seq_client_port * port,
return -EINVAL; return -EINVAL;
/* get port name */ /* get port name */
strlcpy(info->name, port->name, sizeof(info->name)); strscpy(info->name, port->name, sizeof(info->name));
/* get capabilities */ /* get capabilities */
info->capability = port->capability; info->capability = port->capability;
@ -654,7 +654,7 @@ int snd_seq_event_port_attach(int client,
/* Set up the port */ /* Set up the port */
memset(&portinfo, 0, sizeof(portinfo)); memset(&portinfo, 0, sizeof(portinfo));
portinfo.addr.client = client; portinfo.addr.client = client;
strlcpy(portinfo.name, portname ? portname : "Unnamed port", strscpy(portinfo.name, portname ? portname : "Unnamed port",
sizeof(portinfo.name)); sizeof(portinfo.name));
portinfo.capability = cap; portinfo.capability = cap;

View File

@ -9,6 +9,7 @@
#include <linux/time.h> #include <linux/time.h>
#include <linux/device.h> #include <linux/device.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/debugfs.h>
#include <sound/core.h> #include <sound/core.h>
#include <sound/minors.h> #include <sound/minors.h>
#include <sound/info.h> #include <sound/info.h>
@ -39,6 +40,11 @@ MODULE_ALIAS_CHARDEV_MAJOR(CONFIG_SND_MAJOR);
int snd_ecards_limit; int snd_ecards_limit;
EXPORT_SYMBOL(snd_ecards_limit); EXPORT_SYMBOL(snd_ecards_limit);
#ifdef CONFIG_SND_DEBUG
struct dentry *sound_debugfs_root;
EXPORT_SYMBOL_GPL(sound_debugfs_root);
#endif
static struct snd_minor *snd_minors[SNDRV_OS_MINORS]; static struct snd_minor *snd_minors[SNDRV_OS_MINORS];
static DEFINE_MUTEX(sound_mutex); static DEFINE_MUTEX(sound_mutex);
@ -337,6 +343,8 @@ static const char *snd_device_type_name(int type)
return "sequencer"; return "sequencer";
case SNDRV_DEVICE_TYPE_TIMER: case SNDRV_DEVICE_TYPE_TIMER:
return "timer"; return "timer";
case SNDRV_DEVICE_TYPE_COMPRESS:
return "compress";
default: default:
return "?"; return "?";
} }
@ -395,6 +403,10 @@ static int __init alsa_sound_init(void)
unregister_chrdev(major, "alsa"); unregister_chrdev(major, "alsa");
return -ENOMEM; return -ENOMEM;
} }
#ifdef CONFIG_SND_DEBUG
sound_debugfs_root = debugfs_create_dir("sound", NULL);
#endif
#ifndef MODULE #ifndef MODULE
pr_info("Advanced Linux Sound Architecture Driver Initialized.\n"); pr_info("Advanced Linux Sound Architecture Driver Initialized.\n");
#endif #endif
@ -403,6 +415,9 @@ static int __init alsa_sound_init(void)
static void __exit alsa_sound_exit(void) static void __exit alsa_sound_exit(void)
{ {
#ifdef CONFIG_SND_DEBUG
debugfs_remove(sound_debugfs_root);
#endif
snd_info_done(); snd_info_done();
unregister_chrdev(major, "alsa"); unregister_chrdev(major, "alsa");
} }

View File

@ -959,7 +959,7 @@ int snd_timer_new(struct snd_card *card, char *id, struct snd_timer_id *tid,
timer->tmr_device = tid->device; timer->tmr_device = tid->device;
timer->tmr_subdevice = tid->subdevice; timer->tmr_subdevice = tid->subdevice;
if (id) if (id)
strlcpy(timer->id, id, sizeof(timer->id)); strscpy(timer->id, id, sizeof(timer->id));
timer->sticks = 1; timer->sticks = 1;
INIT_LIST_HEAD(&timer->device_list); INIT_LIST_HEAD(&timer->device_list);
INIT_LIST_HEAD(&timer->open_list_head); INIT_LIST_HEAD(&timer->open_list_head);
@ -1659,8 +1659,8 @@ static int snd_timer_user_ginfo(struct file *file,
ginfo->card = t->card ? t->card->number : -1; ginfo->card = t->card ? t->card->number : -1;
if (t->hw.flags & SNDRV_TIMER_HW_SLAVE) if (t->hw.flags & SNDRV_TIMER_HW_SLAVE)
ginfo->flags |= SNDRV_TIMER_FLG_SLAVE; ginfo->flags |= SNDRV_TIMER_FLG_SLAVE;
strlcpy(ginfo->id, t->id, sizeof(ginfo->id)); strscpy(ginfo->id, t->id, sizeof(ginfo->id));
strlcpy(ginfo->name, t->name, sizeof(ginfo->name)); strscpy(ginfo->name, t->name, sizeof(ginfo->name));
ginfo->resolution = t->hw.resolution; ginfo->resolution = t->hw.resolution;
if (t->hw.resolution_min > 0) { if (t->hw.resolution_min > 0) {
ginfo->resolution_min = t->hw.resolution_min; ginfo->resolution_min = t->hw.resolution_min;
@ -1814,8 +1814,8 @@ static int snd_timer_user_info(struct file *file,
info->card = t->card ? t->card->number : -1; info->card = t->card ? t->card->number : -1;
if (t->hw.flags & SNDRV_TIMER_HW_SLAVE) if (t->hw.flags & SNDRV_TIMER_HW_SLAVE)
info->flags |= SNDRV_TIMER_FLG_SLAVE; info->flags |= SNDRV_TIMER_FLG_SLAVE;
strlcpy(info->id, t->id, sizeof(info->id)); strscpy(info->id, t->id, sizeof(info->id));
strlcpy(info->name, t->name, sizeof(info->name)); strscpy(info->name, t->name, sizeof(info->name));
info->resolution = t->hw.resolution; info->resolution = t->hw.resolution;
if (copy_to_user(_info, info, sizeof(*_info))) if (copy_to_user(_info, info, sizeof(*_info)))
err = -EFAULT; err = -EFAULT;

View File

@ -61,8 +61,8 @@ static int snd_timer_user_info_compat(struct file *file,
info.card = t->card ? t->card->number : -1; info.card = t->card ? t->card->number : -1;
if (t->hw.flags & SNDRV_TIMER_HW_SLAVE) if (t->hw.flags & SNDRV_TIMER_HW_SLAVE)
info.flags |= SNDRV_TIMER_FLG_SLAVE; info.flags |= SNDRV_TIMER_FLG_SLAVE;
strlcpy(info.id, t->id, sizeof(info.id)); strscpy(info.id, t->id, sizeof(info.id));
strlcpy(info.name, t->name, sizeof(info.name)); strscpy(info.name, t->name, sizeof(info.name));
info.resolution = t->hw.resolution; info.resolution = t->hw.resolution;
if (copy_to_user(_info, &info, sizeof(*_info))) if (copy_to_user(_info, &info, sizeof(*_info)))
return -EFAULT; return -EFAULT;

View File

@ -219,7 +219,7 @@ static int loopback_jiffies_timer_start(struct loopback_pcm *dpcm)
dpcm->period_update_pending = 1; dpcm->period_update_pending = 1;
} }
tick = dpcm->period_size_frac - dpcm->irq_pos; tick = dpcm->period_size_frac - dpcm->irq_pos;
tick = (tick + dpcm->pcm_bps - 1) / dpcm->pcm_bps; tick = DIV_ROUND_UP(tick, dpcm->pcm_bps);
mod_timer(&dpcm->timer, jiffies + tick); mod_timer(&dpcm->timer, jiffies + tick);
return 0; return 0;

View File

@ -236,7 +236,7 @@ struct dummy_systimer_pcm {
static void dummy_systimer_rearm(struct dummy_systimer_pcm *dpcm) static void dummy_systimer_rearm(struct dummy_systimer_pcm *dpcm)
{ {
mod_timer(&dpcm->timer, jiffies + mod_timer(&dpcm->timer, jiffies +
(dpcm->frac_period_rest + dpcm->rate - 1) / dpcm->rate); DIV_ROUND_UP(dpcm->frac_period_rest, dpcm->rate));
} }
static void dummy_systimer_update(struct dummy_systimer_pcm *dpcm) static void dummy_systimer_update(struct dummy_systimer_pcm *dpcm)

View File

@ -97,7 +97,7 @@ void snd_opl3_init_seq_oss(struct snd_opl3 *opl3, char *name)
return; return;
opl3->oss_seq_dev = dev; opl3->oss_seq_dev = dev;
strlcpy(dev->name, name, sizeof(dev->name)); strscpy(dev->name, name, sizeof(dev->name));
arg = SNDRV_SEQ_DEVICE_ARGPTR(dev); arg = SNDRV_SEQ_DEVICE_ARGPTR(dev);
arg->type = SYNTH_TYPE_FM; arg->type = SYNTH_TYPE_FM;
if (opl3->hardware < OPL3_HW_OPL3) { if (opl3->hardware < OPL3_HW_OPL3) {

View File

@ -290,7 +290,7 @@ int snd_opl3_load_patch(struct snd_opl3 *opl3,
} }
if (name) if (name)
strlcpy(patch->name, name, sizeof(patch->name)); strscpy(patch->name, name, sizeof(patch->name));
return 0; return 0;
} }

View File

@ -1154,8 +1154,7 @@ static int vx_init_audio_io(struct vx_core *chip)
chip->ibl.size = 0; chip->ibl.size = 0;
vx_set_ibl(chip, &chip->ibl); /* query the info */ vx_set_ibl(chip, &chip->ibl); /* query the info */
if (preferred > 0) { if (preferred > 0) {
chip->ibl.size = ((preferred + chip->ibl.granularity - 1) / chip->ibl.size = roundup(preferred, chip->ibl.granularity);
chip->ibl.granularity) * chip->ibl.granularity;
if (chip->ibl.size > chip->ibl.max_size) if (chip->ibl.size > chip->ibl.max_size)
chip->ibl.size = chip->ibl.max_size; chip->ibl.size = chip->ibl.max_size;
} else } else

View File

@ -37,11 +37,9 @@ hwdep_read(struct snd_hwdep *hwdep, char __user *buf, long count,
memset(&event, 0, sizeof(event)); memset(&event, 0, sizeof(event));
count = min_t(long, count, sizeof(event.lock_status)); count = min_t(long, count, sizeof(event.lock_status));
if (bebob->dev_lock_changed) { event.lock_status.type = SNDRV_FIREWIRE_EVENT_LOCK_STATUS;
event.lock_status.type = SNDRV_FIREWIRE_EVENT_LOCK_STATUS; event.lock_status.status = (bebob->dev_lock_count > 0);
event.lock_status.status = (bebob->dev_lock_count > 0); bebob->dev_lock_changed = false;
bebob->dev_lock_changed = false;
}
spin_unlock_irq(&bebob->lock); spin_unlock_irq(&bebob->lock);
@ -80,7 +78,7 @@ hwdep_get_info(struct snd_bebob *bebob, void __user *arg)
info.card = dev->card->index; info.card = dev->card->index;
*(__be32 *)&info.guid[0] = cpu_to_be32(dev->config_rom[3]); *(__be32 *)&info.guid[0] = cpu_to_be32(dev->config_rom[3]);
*(__be32 *)&info.guid[4] = cpu_to_be32(dev->config_rom[4]); *(__be32 *)&info.guid[4] = cpu_to_be32(dev->config_rom[4]);
strlcpy(info.device_name, dev_name(&dev->device), strscpy(info.device_name, dev_name(&dev->device),
sizeof(info.device_name)); sizeof(info.device_name));
if (copy_to_user(arg, &info, sizeof(info))) if (copy_to_user(arg, &info, sizeof(info)))

View File

@ -1,5 +1,6 @@
# SPDX-License-Identifier: GPL-2.0-only # SPDX-License-Identifier: GPL-2.0-only
snd-dice-objs := dice-transaction.o dice-stream.o dice-proc.o dice-midi.o \ snd-dice-objs := dice-transaction.o dice-stream.o dice-proc.o dice-midi.o \
dice-pcm.o dice-hwdep.o dice.o dice-tcelectronic.o \ dice-pcm.o dice-hwdep.o dice.o dice-tcelectronic.o \
dice-alesis.o dice-extension.o dice-mytek.o dice-presonus.o dice-alesis.o dice-extension.o dice-mytek.o dice-presonus.o \
dice-harman.o
obj-$(CONFIG_SND_DICE) += snd-dice.o obj-$(CONFIG_SND_DICE) += snd-dice.o

View File

@ -0,0 +1,26 @@
// SPDX-License-Identifier: GPL-2.0
// dice-harman.c - a part of driver for DICE based devices
//
// Copyright (c) 2021 Takashi Sakamoto
//
// Licensed under the terms of the GNU General Public License, version 2.
#include "dice.h"
int snd_dice_detect_harman_formats(struct snd_dice *dice)
{
int i;
// Lexicon I-ONYX FW810s supports sampling transfer frequency up to
// 96.0 kHz, 12 PCM channels and 1 MIDI channel in its first tx stream
// , 10 PCM channels and 1 MIDI channel in its first rx stream for all
// of the frequencies.
for (i = 0; i < 2; ++i) {
dice->tx_pcm_chs[0][i] = 12;
dice->tx_midi_ports[0] = 1;
dice->rx_pcm_chs[0][i] = 10;
dice->rx_midi_ports[0] = 1;
}
return 0;
}

View File

@ -79,7 +79,7 @@ static int hwdep_get_info(struct snd_dice *dice, void __user *arg)
info.card = dev->card->index; info.card = dev->card->index;
*(__be32 *)&info.guid[0] = cpu_to_be32(dev->config_rom[3]); *(__be32 *)&info.guid[0] = cpu_to_be32(dev->config_rom[3]);
*(__be32 *)&info.guid[4] = cpu_to_be32(dev->config_rom[4]); *(__be32 *)&info.guid[4] = cpu_to_be32(dev->config_rom[4]);
strlcpy(info.device_name, dev_name(&dev->device), strscpy(info.device_name, dev_name(&dev->device),
sizeof(info.device_name)); sizeof(info.device_name));
if (copy_to_user(arg, &info, sizeof(info))) if (copy_to_user(arg, &info, sizeof(info)))

View File

@ -20,10 +20,12 @@ MODULE_LICENSE("GPL v2");
#define OUI_MYTEK 0x001ee8 #define OUI_MYTEK 0x001ee8
#define OUI_SSL 0x0050c2 // Actually ID reserved by IEEE. #define OUI_SSL 0x0050c2 // Actually ID reserved by IEEE.
#define OUI_PRESONUS 0x000a92 #define OUI_PRESONUS 0x000a92
#define OUI_HARMAN 0x000fd7
#define DICE_CATEGORY_ID 0x04 #define DICE_CATEGORY_ID 0x04
#define WEISS_CATEGORY_ID 0x00 #define WEISS_CATEGORY_ID 0x00
#define LOUD_CATEGORY_ID 0x10 #define LOUD_CATEGORY_ID 0x10
#define HARMAN_CATEGORY_ID 0x20
#define MODEL_ALESIS_IO_BOTH 0x000001 #define MODEL_ALESIS_IO_BOTH 0x000001
@ -56,6 +58,8 @@ static int check_dice_category(struct fw_unit *unit)
category = WEISS_CATEGORY_ID; category = WEISS_CATEGORY_ID;
else if (vendor == OUI_LOUD) else if (vendor == OUI_LOUD)
category = LOUD_CATEGORY_ID; category = LOUD_CATEGORY_ID;
else if (vendor == OUI_HARMAN)
category = HARMAN_CATEGORY_ID;
else else
category = DICE_CATEGORY_ID; category = DICE_CATEGORY_ID;
if (device->config_rom[3] != ((vendor << 8) | category) || if (device->config_rom[3] != ((vendor << 8) | category) ||
@ -388,6 +392,14 @@ static const struct ieee1394_device_id dice_id_table[] = {
.model_id = 0x000008, .model_id = 0x000008,
.driver_data = (kernel_ulong_t)snd_dice_detect_presonus_formats, .driver_data = (kernel_ulong_t)snd_dice_detect_presonus_formats,
}, },
// Lexicon I-ONYX FW810S.
{
.match_flags = IEEE1394_MATCH_VENDOR_ID |
IEEE1394_MATCH_MODEL_ID,
.vendor_id = OUI_HARMAN,
.model_id = 0x000001,
.driver_data = (kernel_ulong_t)snd_dice_detect_harman_formats,
},
{ {
.match_flags = IEEE1394_MATCH_VERSION, .match_flags = IEEE1394_MATCH_VERSION,
.version = DICE_INTERFACE, .version = DICE_INTERFACE,

View File

@ -233,5 +233,6 @@ int snd_dice_detect_alesis_mastercontrol_formats(struct snd_dice *dice);
int snd_dice_detect_extension_formats(struct snd_dice *dice); int snd_dice_detect_extension_formats(struct snd_dice *dice);
int snd_dice_detect_mytek_formats(struct snd_dice *dice); int snd_dice_detect_mytek_formats(struct snd_dice *dice);
int snd_dice_detect_presonus_formats(struct snd_dice *dice); int snd_dice_detect_presonus_formats(struct snd_dice *dice);
int snd_dice_detect_harman_formats(struct snd_dice *dice);
#endif #endif

View File

@ -87,7 +87,7 @@ static int hwdep_get_info(struct snd_dg00x *dg00x, void __user *arg)
info.card = dev->card->index; info.card = dev->card->index;
*(__be32 *)&info.guid[0] = cpu_to_be32(dev->config_rom[3]); *(__be32 *)&info.guid[0] = cpu_to_be32(dev->config_rom[3]);
*(__be32 *)&info.guid[4] = cpu_to_be32(dev->config_rom[4]); *(__be32 *)&info.guid[4] = cpu_to_be32(dev->config_rom[4]);
strlcpy(info.device_name, dev_name(&dev->device), strscpy(info.device_name, dev_name(&dev->device),
sizeof(info.device_name)); sizeof(info.device_name));
if (copy_to_user(arg, &info, sizeof(info))) if (copy_to_user(arg, &info, sizeof(info)))

Some files were not shown because too many files have changed in this diff Show More