Commit 378d590c authored by Mark Brown's avatar Mark Brown

Merge branch 'asoc-5.2' into asoc-next

parents 7f5a466f 1587a061
ADI AXI-I2S controller
The core can be generated with transmit (playback), only receive
(capture) or both directions enabled.
Required properties:
- compatible : Must be "adi,axi-i2s-1.00.a"
- reg : Must contain I2S core's registers location and length
......@@ -9,8 +12,8 @@ Required properties:
- clock-names : "axi" for the clock to the AXI interface, "ref" for the sample
rate reference clock.
- dmas: Pairs of phandle and specifier for the DMA channels that are used by
the core. The core expects two dma channels, one for transmit and one for
receive.
the core. The core expects two dma channels if both transmit and receive are
enabled, one channel otherwise.
- dma-names : "tx" for the transmit channel, "rx" for the receive channel.
For more details on the 'dma', 'dma-names', 'clock' and 'clock-names' properties
......
......@@ -2,7 +2,9 @@
Required properties:
- compatible: 'amlogic,axg-toddr' or
'amlogic,axg-frddr'
'amlogic,axg-toddr' or
'amlogic,g12a-frddr' or
'amlogic,g12a-toddr'
- reg: physical base address of the controller and length of memory
mapped region.
- interrupts: interrupt specifier for the fifo.
......
* Amlogic Audio PDM input
Required properties:
- compatible: 'amlogic,axg-pdm'
- compatible: 'amlogic,axg-pdm' or
'amlogic,g12a-pdm'
- reg: physical base address of the controller and length of memory
mapped region.
- clocks: list of clock phandle, one for each entry clock-names.
......
* Amlogic Audio SPDIF Input
Required properties:
- compatible: 'amlogic,axg-spdifin'
- compatible: 'amlogic,axg-spdifin' or
'amlogic,g12a-spdifin'
- interrupts: interrupt specifier for the spdif input.
- clocks: list of clock phandle, one for each entry clock-names.
- clock-names: should contain the following:
......
* Amlogic Audio SPDIF Output
Required properties:
- compatible: 'amlogic,axg-spdifout'
- compatible: 'amlogic,axg-spdifout' or
'amlogic,g12a-spdifout'
- clocks: list of clock phandle, one for each entry clock-names.
- clock-names: should contain the following:
* "pclk" : peripheral clock.
......
......@@ -2,7 +2,9 @@
Required properties:
- compatible: 'amlogic,axg-tdmin' or
'amlogic,axg-tdmout'
'amlogic,axg-tdmout' or
'amlogic,g12a-tdmin' or
'amlogic,g12a-tdmout'
- reg: physical base address of the controller and length of memory
mapped region.
- clocks: list of clock phandle, one for each entry clock-names.
......
Cirrus Logic Lochnagar Audio Development Board
Lochnagar is an evaluation and development board for Cirrus Logic
Smart CODEC and Amp devices. It allows the connection of most Cirrus
Logic devices on mini-cards, as well as allowing connection of
various application processor systems to provide a full evaluation
platform. Audio system topology, clocking and power can all be
controlled through the Lochnagar, allowing the device under test
to be used in a variety of possible use cases.
This binding document describes the binding for the audio portion
of the driver.
This binding must be part of the Lochnagar MFD binding:
[4] ../mfd/cirrus,lochnagar.txt
Required properties:
- compatible : One of the following strings:
"cirrus,lochnagar2-soundcard"
- #sound-dai-cells : Must be set to 1.
- clocks : Contains an entry for each entry in clock-names.
- clock-names : Must include the following clocks:
"mclk" Master clock source for the sound card, should normally
be set to LOCHNAGAR_SOUNDCARD_MCLK provided by the Lochnagar
clock driver.
Example:
lochnagar-sc {
compatible = "cirrus,lochnagar2-soundcard";
#sound-dai-cells = <1>;
clocks = <&lochnagar_clk LOCHNAGAR_SOUNDCARD_MCLK>;
clock-names = "mclk";
};
CS42L51 audio CODEC
Required properties:
- compatible : "cirrus,cs42l51"
- reg : the I2C address of the device for I2C.
Optional properties:
- VL-supply, VD-supply, VA-supply, VAHP-supply: power supplies for the device,
as covered in Documentation/devicetree/bindings/regulator/regulator.txt.
- reset-gpios : GPIO specification for the reset pin. If specified, it will be
deasserted before starting the communication with the codec.
- clocks : a list of phandles + clock-specifiers, one for each entry in
clock-names
......@@ -14,4 +25,9 @@ cs42l51: cs42l51@4a {
reg = <0x4a>;
clocks = <&mclk_prov>;
clock-names = "MCLK";
VL-supply = <&reg_audio>;
VD-supply = <&reg_audio>;
VA-supply = <&reg_audio>;
VAHP-supply = <&reg_audio>;
reset-gpios = <&gpiog 9 GPIO_ACTIVE_LOW>;
};
......@@ -23,8 +23,8 @@ Optional properties:
interrupt is to be used to wake system, otherwise "irq" should be used.
- wakeup-source: Flag to indicate this device can wake system (suspend/resume).
- #clock-cells : Should be set to '<0>', only one clock source provided;
- clock-output-names : Name given for DAI clocks output;
- #clock-cells : Should be set to '<1>', two clock sources provided;
- clock-output-names : Names given for DAI clock outputs (WCLK & BCLK);
- clocks : phandle and clock specifier for codec MCLK.
- clock-names : Clock name string for 'clocks' attribute, should be "mclk".
......@@ -84,8 +84,8 @@ Example:
VDDMIC-supply = <&reg_audio>;
VDDIO-supply = <&reg_audio>;
#clock-cells = <0>;
clock-output-names = "dai-clks";
#clock-cells = <1>;
clock-output-names = "dai-wclk", "dai-bclk";
clocks = <&clks 201>;
clock-names = "mclk";
......
NXP Audio Mixer (AUDMIX).
The Audio Mixer is a on-chip functional module that allows mixing of two
audio streams into a single audio stream. Audio Mixer has two input serial
audio interfaces. These are driven by two Synchronous Audio interface
modules (SAI). Each input serial interface carries 8 audio channels in its
frame in TDM manner. Mixer mixes audio samples of corresponding channels
from two interfaces into a single sample. Before mixing, audio samples of
two inputs can be attenuated based on configuration. The output of the
Audio Mixer is also a serial audio interface. Like input interfaces it has
the same TDM frame format. This output is used to drive the serial DAC TDM
interface of audio codec and also sent to the external pins along with the
receive path of normal audio SAI module for readback by the CPU.
The output of Audio Mixer can be selected from any of the three streams
- serial audio input 1
- serial audio input 2
- mixed audio
Mixing operation is independent of audio sample rate but the two audio
input streams must have same audio sample rate with same number of channels
in TDM frame to be eligible for mixing.
Device driver required properties:
=================================
- compatible : Compatible list, contains "fsl,imx8qm-audmix"
- reg : Offset and length of the register set for the device.
- clocks : Must contain an entry for each entry in clock-names.
- clock-names : Must include the "ipg" for register access.
- power-domains : Must contain the phandle to AUDMIX power domain node
- dais : Must contain a list of phandles to AUDMIX connected
DAIs. The current implementation requires two phandles
to SAI interfaces to be provided, the first SAI in the
list being used to route the AUDMIX output.
Device driver configuration example:
======================================
audmix: audmix@59840000 {
compatible = "fsl,imx8qm-audmix";
reg = <0x0 0x59840000 0x0 0x10000>;
clocks = <&clk IMX8QXP_AUD_AUDMIX_IPG>;
clock-names = "ipg";
power-domains = <&pd_audmix>;
dais = <&sai4>, <&sai5>;
};
* Microchip I2S Multi-Channel Controller
Required properties:
- compatible: Should be "microchip,sam9x60-i2smcc".
- reg: Should be the physical base address of the controller and the
length of memory mapped region.
- interrupts: Should contain the interrupt for the controller.
- dmas: Should be one per channel name listed in the dma-names property,
as described in atmel-dma.txt and dma.txt files.
- dma-names: Identifier string for each DMA request line in the dmas property.
Two dmas have to be defined, "tx" and "rx".
- clocks: Must contain an entry for each entry in clock-names.
Please refer to clock-bindings.txt.
- clock-names: Should be one of each entry matching the clocks phandles list:
- "pclk" (peripheral clock) Required.
- "gclk" (generated clock) Optional (1).
Optional properties:
- pinctrl-0: Should specify pin control groups used for this controller.
- princtrl-names: Should contain only one value - "default".
(1) : Only the peripheral clock is required. The generated clock is optional
and should be set mostly when Master Mode is required.
Example:
i2s@f001c000 {
compatible = "microchip,sam9x60-i2smcc";
reg = <0xf001c000 0x100>;
interrupts = <34 IRQ_TYPE_LEVEL_HIGH 7>;
dmas = <&dma0
(AT91_XDMAC_DT_MEM_IF(0) | AT91_XDMAC_DT_PER_IF(1) |
AT91_XDMAC_DT_PERID(36))>,
<&dma0
(AT91_XDMAC_DT_MEM_IF(0) | AT91_XDMAC_DT_PER_IF(1) |
AT91_XDMAC_DT_PERID(37))>;
dma-names = "tx", "rx";
clocks = <&i2s_clk>, <&i2s_gclk>;
clock-names = "pclk", "gclk";
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_i2s_default>;
};
MT8183 with MT6358, DA7219 and MAX98357 CODECS
Required properties:
- compatible : "mediatek,mt8183_da7219_max98357"
- mediatek,headset-codec: the phandles of da7219 codecs
- mediatek,platform: the phandle of MT8183 ASoC platform
Example:
sound {
compatible = "mediatek,mt8183_da7219_max98357";
mediatek,headset-codec = <&da7219>;
mediatek,platform = <&afe>;
};
MT8183 with MT6358, TS3A227 and MAX98357 CODECS
Required properties:
- compatible : "mediatek,mt8183_mt6358_ts3a227_max98357"
- mediatek,headset-codec: the phandles of ts3a227 codecs
- mediatek,platform: the phandle of MT8183 ASoC platform
Example:
sound {
compatible = "mediatek,mt8183_mt6358_ts3a227_max98357";
mediatek,headset-codec = <&ts3a227>;
mediatek,platform = <&afe>;
};
......@@ -266,6 +266,7 @@ Required properties:
- "renesas,rcar_sound-r8a7743" (RZ/G1M)
- "renesas,rcar_sound-r8a7744" (RZ/G1N)
- "renesas,rcar_sound-r8a7745" (RZ/G1E)
- "renesas,rcar_sound-r8a77470" (RZ/G1C)
- "renesas,rcar_sound-r8a774a1" (RZ/G2M)
- "renesas,rcar_sound-r8a774c0" (RZ/G2E)
- "renesas,rcar_sound-r8a7778" (R-Car M1A)
......@@ -282,7 +283,12 @@ Required properties:
- reg : Should contain the register physical address.
required register is
SRU/ADG/SSI if generation1
SRU/ADG/SSIU/SSI if generation2
SRU/ADG/SSIU/SSI/AUDIO-DMAC-periperi if generation2/generation3
Select extended AUDIO-DMAC-periperi address if SoC has it,
otherwise select normal AUDIO-DMAC-periperi address.
- reg-names : Should contain the register names.
scu/adg/ssi if generation1
scu/adg/ssiu/ssi/audmapp if generation2/generation3
- rcar_sound,ssi : Should contain SSI feature.
The number of SSI subnode should be same as HW.
see below for detail.
......
......@@ -3,6 +3,9 @@
Required properties:
- compatible: "rockchip,pdm"
- "rockchip,px30-pdm"
- "rockchip,rk1808-pdm"
- "rockchip,rk3308-pdm"
- reg: physical base address of the controller and length of memory mapped
region.
- dmas: DMA specifiers for rx dma. See the DMA client binding,
......@@ -12,6 +15,8 @@ Required properties:
- clock-names: should contain following:
- "pdm_hclk": clock for PDM BUS
- "pdm_clk" : clock for PDM controller
- resets: a list of phandle + reset-specifer paris, one for each entry in reset-names.
- reset-names: reset names, should include "pdm-m".
- pinctrl-names: Must contain a "default" entry.
- pinctrl-N: One property must exist for each entry in
pinctrl-names. See ../pinctrl/pinctrl-bindings.txt
......
......@@ -22,6 +22,11 @@ Optional properties:
2: Use JD1_2 pin for jack-detect
3: Use JD2 pin for jack-detect
- realtek,jack-detect-not-inverted
bool. Normal jack-detect switches give an inverted (active-low) signal,
set this bool in the rare case you've a jack-detect switch which is not
inverted.
- realtek,over-current-threshold-microamp
u32, micbias over-current detection threshold in µA, valid values are
600, 1500 and 2000µA.
......
......@@ -2,9 +2,9 @@ Simple Amplifier Audio Driver
Required properties:
- compatible : "dioo,dio2125" or "simple-audio-amplifier"
- enable-gpios : the gpio connected to the enable pin of the simple amplifier
Optional properties:
- enable-gpios : the gpio connected to the enable pin of the simple amplifier
- VCC-supply : power supply for the device, as covered
in Documentation/devicetree/bindings/regulator/regulator.txt
......
......@@ -24,6 +24,8 @@ Optional properties:
a microphone is attached.
- simple-audio-card,aux-devs : List of phandles pointing to auxiliary devices, such
as amplifiers, to be added to the sound card.
- simple-audio-card,pin-switches : List of strings containing the widget names for
which pin switches must be created.
Optional subnodes:
......
Spreadtrum Multi-Channel Data Transfer Binding
The Multi-channel data transfer controller is used for sound stream
transmission between audio subsystem and other AP/CP subsystem. It
supports 10 DAC channel and 10 ADC channel, and each channel can be
configured with DMA mode or interrupt mode.
Required properties:
- compatible: Should be "sprd,sc9860-mcdt".
- reg: Should contain registers address and length.
- interrupts: Should contain one interrupt shared by all channel.
Example:
mcdt@41490000 {
compatible = "sprd,sc9860-mcdt";
reg = <0 0x41490000 0 0x170>;
interrupts = <GIC_SPI 48 IRQ_TYPE_LEVEL_HIGH>;
};
......@@ -3801,6 +3801,7 @@ F: drivers/clk/clk-lochnagar.c
F: drivers/mfd/lochnagar-i2c.c
F: drivers/pinctrl/cirrus/pinctrl-lochnagar.c
F: drivers/regulator/lochnagar-regulator.c
F: sound/soc/codecs/lochnagar-sc.c
F: include/dt-bindings/clk/lochnagar.h
F: include/dt-bindings/pinctrl/lochnagar.h
F: include/linux/mfd/lochnagar*
......@@ -3808,6 +3809,7 @@ F: Documentation/devicetree/bindings/mfd/cirrus,lochnagar.txt
F: Documentation/devicetree/bindings/clock/cirrus,lochnagar.txt
F: Documentation/devicetree/bindings/pinctrl/cirrus,lochnagar.txt
F: Documentation/devicetree/bindings/regulator/cirrus,lochnagar.txt
F: Documentation/devicetree/bindings/sound/cirrus,lochnagar.txt
CISCO FCOE HBA DRIVER
M: Satish Kharat <satishkh@cisco.com>
......
......@@ -739,6 +739,7 @@ EXPORT_SYMBOL(acpi_dev_found);
struct acpi_dev_match_info {
const char *dev_name;
struct acpi_device *adev;
struct acpi_device_id hid[2];
const char *uid;
s64 hrv;
......@@ -759,6 +760,7 @@ static int acpi_dev_match_cb(struct device *dev, void *data)
return 0;
match->dev_name = acpi_dev_name(adev);
match->adev = adev;
if (match->hrv == -1)
return 1;
......@@ -806,18 +808,20 @@ bool acpi_dev_present(const char *hid, const char *uid, s64 hrv)
EXPORT_SYMBOL(acpi_dev_present);
/**
* acpi_dev_get_first_match_name - Return name of first match of ACPI device
* acpi_dev_get_first_match_dev - Return the first match of ACPI device
* @hid: Hardware ID of the device.
* @uid: Unique ID of the device, pass NULL to not check _UID
* @hrv: Hardware Revision of the device, pass -1 to not check _HRV
*
* Return device name if a matching device was present
* Return the first match of ACPI device if a matching device was present
* at the moment of invocation, or NULL otherwise.
*
* The caller is responsible to call put_device() on the returned device.
*
* See additional information in acpi_dev_present() as well.
*/
const char *
acpi_dev_get_first_match_name(const char *hid, const char *uid, s64 hrv)
struct acpi_device *
acpi_dev_get_first_match_dev(const char *hid, const char *uid, s64 hrv)
{
struct acpi_dev_match_info match = {};
struct device *dev;
......@@ -827,9 +831,9 @@ acpi_dev_get_first_match_name(const char *hid, const char *uid, s64 hrv)
match.hrv = hrv;
dev = bus_find_device(&acpi_bus_type, NULL, &match, acpi_dev_match_cb);
return dev ? match.dev_name : NULL;
return dev ? match.adev : NULL;
}
EXPORT_SYMBOL(acpi_dev_get_first_match_name);
EXPORT_SYMBOL(acpi_dev_get_first_match_dev);
/*
* acpi_backlight= handling, this is done here rather then in video_detect.c
......
......@@ -333,7 +333,7 @@ static int axp288_extcon_probe(struct platform_device *pdev)
struct axp288_extcon_info *info;
struct axp20x_dev *axp20x = dev_get_drvdata(pdev->dev.parent);
struct device *dev = &pdev->dev;
const char *name;
struct acpi_device *adev;
int ret, i, pirq;
info = devm_kzalloc(&pdev->dev, sizeof(*info), GFP_KERNEL);
......@@ -357,9 +357,10 @@ static int axp288_extcon_probe(struct platform_device *pdev)
if (ret)
return ret;
name = acpi_dev_get_first_match_name("INT3496", NULL, -1);
if (name) {
info->id_extcon = extcon_get_extcon_dev(name);
adev = acpi_dev_get_first_match_dev("INT3496", NULL, -1);
if (adev) {
info->id_extcon = extcon_get_extcon_dev(acpi_dev_name(adev));
put_device(&adev->dev);
if (!info->id_extcon)
return -EPROBE_DEFER;
......
......@@ -377,10 +377,20 @@ static void mrfld_irq_init_hw(struct mrfld_gpio *priv)
}
}
static const char *mrfld_gpio_get_pinctrl_dev_name(void)
static const char *mrfld_gpio_get_pinctrl_dev_name(struct mrfld_gpio *priv)
{
const char *dev_name = acpi_dev_get_first_match_name("INTC1002", NULL, -1);
return dev_name ? dev_name : "pinctrl-merrifield";
struct acpi_device *adev;
const char *name;
adev = acpi_dev_get_first_match_dev("INTC1002", NULL, -1);
if (adev) {
name = devm_kstrdup(priv->dev, acpi_dev_name(adev), GFP_KERNEL);
put_device(&adev->dev);
} else {
name = "pinctrl-merrifield";
}
return name;
}
static int mrfld_gpio_probe(struct pci_dev *pdev, const struct pci_device_id *id)
......@@ -441,7 +451,7 @@ static int mrfld_gpio_probe(struct pci_dev *pdev, const struct pci_device_id *id
return retval;
}
pinctrl_dev_name = mrfld_gpio_get_pinctrl_dev_name();
pinctrl_dev_name = mrfld_gpio_get_pinctrl_dev_name(priv);
for (i = 0; i < ARRAY_SIZE(mrfld_gpio_ranges); i++) {
range = &mrfld_gpio_ranges[i];
retval = gpiochip_add_pin_range(&priv->chip,
......
......@@ -91,8 +91,8 @@ acpi_evaluate_dsm_typed(acpi_handle handle, const guid_t *guid, u64 rev,
bool acpi_dev_found(const char *hid);
bool acpi_dev_present(const char *hid, const char *uid, s64 hrv);
const char *
acpi_dev_get_first_match_name(const char *hid, const char *uid, s64 hrv);
struct acpi_device *
acpi_dev_get_first_match_dev(const char *hid, const char *uid, s64 hrv);
#ifdef CONFIG_ACPI
......
......@@ -669,8 +669,8 @@ static inline bool acpi_dev_present(const char *hid, const char *uid, s64 hrv)
return false;
}
static inline const char *
acpi_dev_get_first_match_name(const char *hid, const char *uid, s64 hrv)
static inline struct acpi_device *
acpi_dev_get_first_match_dev(const char *hid, const char *uid, s64 hrv)
{
return NULL;
}
......
......@@ -33,10 +33,16 @@ enum da7219_mic_amp_in_sel {
struct da7219_aad_pdata;
enum da7219_dai_clks {
DA7219_DAI_WCLK_IDX = 0,
DA7219_DAI_BCLK_IDX,
DA7219_DAI_NUM_CLKS,
};
struct da7219_pdata {
bool wakeup_source;
const char *dai_clks_name;
const char *dai_clk_names[DA7219_DAI_NUM_CLKS];
/* Mic */
enum da7219_micbias_voltage micbias_lvl;
......
......@@ -10,10 +10,10 @@
#include <sound/soc.h>
#define asoc_simple_card_init_hp(card, sjack, prefix) \
asoc_simple_card_init_jack(card, sjack, 1, prefix)
#define asoc_simple_card_init_mic(card, sjack, prefix) \
asoc_simple_card_init_jack(card, sjack, 0, prefix)
#define asoc_simple_init_hp(card, sjack, prefix) \
asoc_simple_init_jack(card, sjack, 1, prefix)
#define asoc_simple_init_mic(card, sjack, prefix) \
asoc_simple_init_jack(card, sjack, 0, prefix)
struct asoc_simple_dai {
const char *name;
......@@ -26,7 +26,7 @@ struct asoc_simple_dai {
struct clk *clk;
};
struct asoc_simple_card_data {
struct asoc_simple_data {
u32 convert_rate;
u32 convert_channels;
};
......@@ -37,96 +37,180 @@ struct asoc_simple_jack {
struct snd_soc_jack_gpio gpio;
};
int asoc_simple_card_parse_daifmt(struct device *dev,
struct asoc_simple_priv {
struct snd_soc_card snd_card;
struct simple_dai_props {
struct asoc_simple_dai *cpu_dai;
struct asoc_simple_dai *codec_dai;
struct snd_soc_dai_link_component codecs; /* single codec */
struct snd_soc_dai_link_component platforms;
struct asoc_simple_data adata;
struct snd_soc_codec_conf *codec_conf;
unsigned int mclk_fs;
} *dai_props;
struct asoc_simple_jack hp_jack;
struct asoc_simple_jack mic_jack;
struct snd_soc_dai_link *dai_link;
struct asoc_simple_dai *dais;
struct snd_soc_codec_conf *codec_conf;
struct gpio_desc *pa_gpio;
};
#define simple_priv_to_card(priv) (&(priv)->snd_card)
#define simple_priv_to_props(priv, i) ((priv)->dai_props + (i))
#define simple_priv_to_dev(priv) (simple_priv_to_card(priv)->dev)
#define simple_priv_to_link(priv, i) (simple_priv_to_card(priv)->dai_link + (i))
struct link_info {
int dais; /* number of dai */
int link; /* number of link */
int conf; /* number of codec_conf */
int cpu; /* turn for CPU / Codec */
};
int asoc_simple_parse_daifmt(struct device *dev,
struct device_node *node,
struct device_node *codec,
char *prefix,
unsigned int *retfmt);
__printf(3, 4)
int asoc_simple_card_set_dailink_name(struct device *dev,
int asoc_simple_set_dailink_name(struct device *dev,
struct snd_soc_dai_link *dai_link,
const char *fmt, ...);
int asoc_simple_card_parse_card_name(struct snd_soc_card *card,
int asoc_simple_parse_card_name(struct snd_soc_card *card,
char *prefix);
#define asoc_simple_card_parse_clk_cpu(dev, node, dai_link, simple_dai) \
asoc_simple_card_parse_clk(dev, node, dai_link->cpu_of_node, simple_dai, \
#define asoc_simple_parse_clk_cpu(dev, node, dai_link, simple_dai) \
asoc_simple_parse_clk(dev, node, dai_link->cpu_of_node, simple_dai, \
dai_link->cpu_dai_name, NULL)
#define asoc_simple_card_parse_clk_codec(dev, node, dai_link, simple_dai) \
asoc_simple_card_parse_clk(dev, node, dai_link->codec_of_node, simple_dai,\
#define asoc_simple_parse_clk_codec(dev, node, dai_link, simple_dai) \
asoc_simple_parse_clk(dev, node, dai_link->codec_of_node, simple_dai,\
dai_link->codec_dai_name, dai_link->codecs)
int asoc_simple_card_parse_clk(struct device *dev,
int asoc_simple_parse_clk(struct device *dev,
struct device_node *node,
struct device_node *dai_of_node,
struct asoc_simple_dai *simple_dai,
const char *dai_name,
struct snd_soc_dai_link_component *dlc);
int asoc_simple_card_clk_enable(struct asoc_simple_dai *dai);
void asoc_simple_card_clk_disable(struct asoc_simple_dai *dai);
int asoc_simple_startup(struct snd_pcm_substream *substream);
void asoc_simple_shutdown(struct snd_pcm_substream *substream);
int asoc_simple_hw_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params);
int asoc_simple_dai_init(struct snd_soc_pcm_runtime *rtd);
int asoc_simple_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
struct snd_pcm_hw_params *params);
#define asoc_simple_card_parse_cpu(node, dai_link, \
list_name, cells_name, is_single_link) \
asoc_simple_card_parse_dai(node, NULL, \
#define asoc_simple_parse_cpu(node, dai_link, is_single_link) \
asoc_simple_parse_dai(node, NULL, \
&dai_link->cpu_of_node, \
&dai_link->cpu_dai_name, list_name, cells_name, is_single_link)
#define asoc_simple_card_parse_codec(node, dai_link, list_name, cells_name) \
asoc_simple_card_parse_dai(node, dai_link->codecs, \
&dai_link->cpu_dai_name, is_single_link)
#define asoc_simple_parse_codec(node, dai_link) \
asoc_simple_parse_dai(node, dai_link->codecs, \
&dai_link->codec_of_node, \
&dai_link->codec_dai_name, \
list_name, cells_name, NULL)
#define asoc_simple_card_parse_platform(node, dai_link, list_name, cells_name) \
asoc_simple_card_parse_dai(node, dai_link->platforms, \
&dai_link->platform_of_node, \
NULL, list_name, cells_name, NULL)
int asoc_simple_card_parse_dai(struct device_node *node,
struct snd_soc_dai_link_component *dlc,
struct device_node **endpoint_np,
const char **dai_name,
const char *list_name,
const char *cells_name,
int *is_single_links);
#define asoc_simple_card_parse_graph_cpu(ep, dai_link) \
asoc_simple_card_parse_graph_dai(ep, NULL, \
&dai_link->cpu_of_node, \
&dai_link->cpu_dai_name)
#define asoc_simple_card_parse_graph_codec(ep, dai_link) \
asoc_simple_card_parse_graph_dai(ep, dai_link->codecs, \
&dai_link->codec_of_node, \
&dai_link->codec_dai_name)
int asoc_simple_card_parse_graph_dai(struct device_node *ep,
struct snd_soc_dai_link_component *dlc,
struct device_node **endpoint_np,
const char **dai_name);
&dai_link->codec_dai_name, NULL)
#define asoc_simple_parse_platform(node, dai_link) \
asoc_simple_parse_dai(node, dai_link->platforms, \
&dai_link->platform_of_node, NULL, NULL)
#define asoc_simple_card_of_parse_tdm(np, dai) \
#define asoc_simple_parse_tdm(np, dai) \
snd_soc_of_parse_tdm_slot(np, &(dai)->tx_slot_mask, \
&(dai)->rx_slot_mask, \
&(dai)->slots, \
&(dai)->slot_width);
int asoc_simple_card_init_dai(struct snd_soc_dai *dai,
struct asoc_simple_dai *simple_dai);
void asoc_simple_card_canonicalize_platform(struct snd_soc_dai_link *dai_link);
void asoc_simple_card_canonicalize_cpu(struct snd_soc_dai_link *dai_link,
void asoc_simple_canonicalize_platform(struct snd_soc_dai_link *dai_link);
void asoc_simple_canonicalize_cpu(struct snd_soc_dai_link *dai_link,
int is_single_links);
int asoc_simple_card_clean_reference(struct snd_soc_card *card);
int asoc_simple_clean_reference(struct snd_soc_card *card);
void asoc_simple_card_convert_fixup(struct asoc_simple_card_data *data,
void asoc_simple_convert_fixup(struct asoc_simple_data *data,
struct snd_pcm_hw_params *params);
void asoc_simple_card_parse_convert(struct device *dev,
void asoc_simple_parse_convert(struct device *dev,
struct device_node *np, char *prefix,
struct asoc_simple_card_data *data);
struct asoc_simple_data *data);
int asoc_simple_card_of_parse_routing(struct snd_soc_card *card,
int asoc_simple_parse_routing(struct snd_soc_card *card,
char *prefix);
int asoc_simple_parse_widgets(struct snd_soc_card *card,
char *prefix);
int asoc_simple_card_of_parse_widgets(struct snd_soc_card *card,
int asoc_simple_parse_pin_switches(struct snd_soc_card *card,
char *prefix);
int asoc_simple_card_init_jack(struct snd_soc_card *card,
int asoc_simple_init_jack(struct snd_soc_card *card,
struct asoc_simple_jack *sjack,
int is_hp, char *prefix);
int asoc_simple_init_priv(struct asoc_simple_priv *priv,
struct link_info *li);
#ifdef DEBUG
inline void asoc_simple_debug_dai(struct asoc_simple_priv *priv,
char *name,
struct asoc_simple_dai *dai)
{
struct device *dev = simple_priv_to_dev(priv);
if (dai->name)
dev_dbg(dev, "%s dai name = %s\n",
name, dai->name);
if (dai->sysclk)
dev_dbg(dev, "%s sysclk = %d\n",
name, dai->sysclk);
dev_dbg(dev, "%s direction = %s\n",
name, dai->clk_direction ? "OUT" : "IN");
if (dai->slots)
dev_dbg(dev, "%s slots = %d\n", name, dai->slots);
if (dai->slot_width)
dev_dbg(dev, "%s slot width = %d\n", name, dai->slot_width);
if (dai->tx_slot_mask)
dev_dbg(dev, "%s tx slot mask = %d\n", name, dai->tx_slot_mask);
if (dai->rx_slot_mask)
dev_dbg(dev, "%s rx slot mask = %d\n", name, dai->rx_slot_mask);
if (dai->clk)
dev_dbg(dev, "%s clk %luHz\n", name, clk_get_rate(dai->clk));
}
inline void asoc_simple_debug_info(struct asoc_simple_priv *priv)
{
struct snd_soc_card *card = simple_priv_to_card(priv);
struct device *dev = simple_priv_to_dev(priv);
int i;
if (card->name)
dev_dbg(dev, "Card Name: %s\n", card->name);
for (i = 0; i < card->num_links; i++) {
struct simple_dai_props *props = simple_priv_to_props(priv, i);
struct snd_soc_dai_link *link = simple_priv_to_link(priv, i);
dev_dbg(dev, "DAI%d\n", i);
asoc_simple_debug_dai(priv, "cpu", props->cpu_dai);
asoc_simple_debug_dai(priv, "codec", props->codec_dai);
if (link->name)
dev_dbg(dev, "dai name = %s\n", link->name);
dev_dbg(dev, "dai format = %04x\n", link->dai_fmt);
if (props->adata.convert_rate)
dev_dbg(dev, "convert_rate = %d\n",
props->adata.convert_rate);
if (props->adata.convert_channels)
dev_dbg(dev, "convert_channels = %d\n",
props->adata.convert_channels);
if (props->codec_conf && props->codec_conf->name_prefix)
dev_dbg(dev, "name prefix = %s\n",
props->codec_conf->name_prefix);
if (props->mclk_fs)
dev_dbg(dev, "mclk-fs = %d\n",
props->mclk_fs);
}
}
#else
#define asoc_simple_debug_info(priv)
#endif /* DEBUG */
#endif /* __SIMPLE_CARD_UTILS_H */
/* SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) */
/*
* This file is provided under a dual BSD/GPLv2 license. When using or
* redistributing this file, you may do so under either license.
*
* Copyright(c) 2018 Intel Corporation. All rights reserved.
*
* Author: Liam Girdwood <liam.r.girdwood@linux.intel.com>
*/
#ifndef __INCLUDE_SOUND_SOF_H
#define __INCLUDE_SOUND_SOF_H
#include <linux/pci.h>
#include <sound/soc.h>
#include <sound/soc-acpi.h>
struct snd_sof_dsp_ops;
/*
* SOF Platform data.
*/
struct snd_sof_pdata {
const struct firmware *fw;
const char *drv_name;
const char *name;
const char *platform;
struct device *dev;
/*
* notification callback used if the hardware initialization
* can take time or is handled in a workqueue. This callback
* can be used by the caller to e.g. enable runtime_pm
* or limit functionality until all low-level inits are
* complete.
*/
void (*sof_probe_complete)(struct device *dev);
/* descriptor */
const struct sof_dev_desc *desc;
/* firmware and topology filenames */
const char *fw_filename_prefix;
const char *fw_filename;
const char *tplg_filename_prefix;
const char *tplg_filename;
/* machine */
struct platform_device *pdev_mach;
const struct snd_soc_acpi_mach *machine;
void *hw_pdata;
};
/*
* Descriptor used for setting up SOF platform data. This is used when
* ACPI/PCI data is missing or mapped differently.
*/
struct sof_dev_desc {
/* list of machines using this configuration */
struct snd_soc_acpi_mach *machines;
/* Platform resource indexes in BAR / ACPI resources. */
/* Must set to -1 if not used - add new items to end */
int resindex_lpe_base;
int resindex_pcicfg_base;
int resindex_imr_base;
int irqindex_host_ipc;
int resindex_dma_base;
/* DMA only valid when resindex_dma_base != -1*/
int dma_engine;
int dma_size;
/* IPC timeouts in ms */
int ipc_timeout;
int boot_timeout;
/* chip information for dsp */
const void *chip_info;
/* defaults for no codec mode */
const char *nocodec_fw_filename;
const char *nocodec_tplg_filename;
/* defaults paths for firmware and topology files */
const char *default_fw_path;
const char *default_tplg_path;
const struct snd_sof_dsp_ops *ops;
const struct sof_arch_ops *arch_ops;
};
int sof_nocodec_setup(struct device *dev,
struct snd_sof_pdata *sof_pdata,
struct snd_soc_acpi_mach *mach,
const struct sof_dev_desc *desc,
const struct snd_sof_dsp_ops *ops);
#endif
/* SPDX-License-Identifier: ((GPL-2.0 WITH Linux-syscall-note) OR BSD-3-Clause) */
/*
* This file is provided under a dual BSD/GPLv2 license. When using or
* redistributing this file, you may do so under either license.
*
* Copyright(c) 2018 Intel Corporation. All rights reserved.
*/
#ifndef __INCLUDE_SOUND_SOF_CONTROL_H__
#define __INCLUDE_SOUND_SOF_CONTROL_H__
#include <uapi/sound/sof/header.h>
#include <sound/sof/header.h>
/*
* Component Mixers and Controls
*/
/* channel positions - uses same values as ALSA */
enum sof_ipc_chmap {
SOF_CHMAP_UNKNOWN = 0,
SOF_CHMAP_NA, /**< N/A, silent */
SOF_CHMAP_MONO, /**< mono stream */
SOF_CHMAP_FL, /**< front left */
SOF_CHMAP_FR, /**< front right */
SOF_CHMAP_RL, /**< rear left */
SOF_CHMAP_RR, /**< rear right */
SOF_CHMAP_FC, /**< front centre */
SOF_CHMAP_LFE, /**< LFE */
SOF_CHMAP_SL, /**< side left */
SOF_CHMAP_SR, /**< side right */
SOF_CHMAP_RC, /**< rear centre */
SOF_CHMAP_FLC, /**< front left centre */
SOF_CHMAP_FRC, /**< front right centre */
SOF_CHMAP_RLC, /**< rear left centre */
SOF_CHMAP_RRC, /**< rear right centre */
SOF_CHMAP_FLW, /**< front left wide */
SOF_CHMAP_FRW, /**< front right wide */
SOF_CHMAP_FLH, /**< front left high */
SOF_CHMAP_FCH, /**< front centre high */
SOF_CHMAP_FRH, /**< front right high */
SOF_CHMAP_TC, /**< top centre */
SOF_CHMAP_TFL, /**< top front left */
SOF_CHMAP_TFR, /**< top front right */
SOF_CHMAP_TFC, /**< top front centre */
SOF_CHMAP_TRL, /**< top rear left */
SOF_CHMAP_TRR, /**< top rear right */
SOF_CHMAP_TRC, /**< top rear centre */
SOF_CHMAP_TFLC, /**< top front left centre */
SOF_CHMAP_TFRC, /**< top front right centre */
SOF_CHMAP_TSL, /**< top side left */
SOF_CHMAP_TSR, /**< top side right */
SOF_CHMAP_LLFE, /**< left LFE */
SOF_CHMAP_RLFE, /**< right LFE */
SOF_CHMAP_BC, /**< bottom centre */
SOF_CHMAP_BLC, /**< bottom left centre */
SOF_CHMAP_BRC, /**< bottom right centre */
SOF_CHMAP_LAST = SOF_CHMAP_BRC,
};
/* control data type and direction */
enum sof_ipc_ctrl_type {
/* per channel data - uses struct sof_ipc_ctrl_value_chan */
SOF_CTRL_TYPE_VALUE_CHAN_GET = 0,
SOF_CTRL_TYPE_VALUE_CHAN_SET,
/* component data - uses struct sof_ipc_ctrl_value_comp */
SOF_CTRL_TYPE_VALUE_COMP_GET,
SOF_CTRL_TYPE_VALUE_COMP_SET,
/* bespoke data - uses struct sof_abi_hdr */
SOF_CTRL_TYPE_DATA_GET,
SOF_CTRL_TYPE_DATA_SET,
};
/* control command type */
enum sof_ipc_ctrl_cmd {
SOF_CTRL_CMD_VOLUME = 0, /**< maps to ALSA volume style controls */
SOF_CTRL_CMD_ENUM, /**< maps to ALSA enum style controls */
SOF_CTRL_CMD_SWITCH, /**< maps to ALSA switch style controls */
SOF_CTRL_CMD_BINARY, /**< maps to ALSA binary style controls */
};
/* generic channel mapped value data */
struct sof_ipc_ctrl_value_chan {
uint32_t channel; /**< channel map - enum sof_ipc_chmap */
uint32_t value;
} __packed;
/* generic component mapped value data */
struct sof_ipc_ctrl_value_comp {
uint32_t index; /**< component source/sink/control index in control */
union {
uint32_t uvalue;
int32_t svalue;
};
} __packed;
/* generic control data */
struct sof_ipc_ctrl_data {
struct sof_ipc_reply rhdr;
uint32_t comp_id;
/* control access and data type */
uint32_t type; /**< enum sof_ipc_ctrl_type */
uint32_t cmd; /**< enum sof_ipc_ctrl_cmd */
uint32_t index; /**< control index for comps > 1 control */
/* control data - can either be appended or DMAed from host */
struct sof_ipc_host_buffer buffer;
uint32_t num_elems; /**< in array elems or bytes for data type */
uint32_t elems_remaining; /**< elems remaining if sent in parts */
uint32_t msg_index; /**< for large messages sent in parts */
/* reserved for future use */
uint32_t reserved[6];
/* control data - add new types if needed */
union {
/* channel values can be used by volume type controls */
struct sof_ipc_ctrl_value_chan chanv[0];
/* component values used by routing controls like mux, mixer */
struct sof_ipc_ctrl_value_comp compv[0];
/* data can be used by binary controls */
struct sof_abi_hdr data[0];
};
} __packed;
/** Event type */
enum sof_ipc_ctrl_event_type {
SOF_CTRL_EVENT_GENERIC = 0, /**< generic event */
SOF_CTRL_EVENT_GENERIC_METADATA, /**< generic event with metadata */
SOF_CTRL_EVENT_KD, /**< keyword detection event */
SOF_CTRL_EVENT_VAD, /**< voice activity detection event */
};
/**
* Generic notification data.
*/
struct sof_ipc_comp_event {
struct sof_ipc_reply rhdr;
uint16_t src_comp_type; /**< COMP_TYPE_ */
uint32_t src_comp_id; /**< source component id */
uint32_t event_type; /**< event type - SOF_CTRL_EVENT_* */
uint32_t num_elems; /**< in array elems or bytes for data type */
/* reserved for future use */
uint32_t reserved[8];
/* control data - add new types if needed */
union {
/* data can be used by binary controls */
struct sof_abi_hdr data[0];
/* event specific values */
uint32_t event_value;
};
} __packed;
#endif
/* SPDX-License-Identifier: ((GPL-2.0 WITH Linux-syscall-note) OR BSD-3-Clause) */
/*
* This file is provided under a dual BSD/GPLv2 license. When using or
* redistributing this file, you may do so under either license.
*
* Copyright(c) 2018 Intel Corporation. All rights reserved.
*/
#ifndef __INCLUDE_SOUND_SOF_DAI_INTEL_H__
#define __INCLUDE_SOUND_SOF_DAI_INTEL_H__
#include <sound/sof/header.h>
/* ssc1: TINTE */
#define SOF_DAI_INTEL_SSP_QUIRK_TINTE (1 << 0)
/* ssc1: PINTE */
#define SOF_DAI_INTEL_SSP_QUIRK_PINTE (1 << 1)
/* ssc2: SMTATF */
#define SOF_DAI_INTEL_SSP_QUIRK_SMTATF (1 << 2)
/* ssc2: MMRATF */
#define SOF_DAI_INTEL_SSP_QUIRK_MMRATF (1 << 3)
/* ssc2: PSPSTWFDFD */
#define SOF_DAI_INTEL_SSP_QUIRK_PSPSTWFDFD (1 << 4)
/* ssc2: PSPSRWFDFD */
#define SOF_DAI_INTEL_SSP_QUIRK_PSPSRWFDFD (1 << 5)
/* ssc1: LBM */
#define SOF_DAI_INTEL_SSP_QUIRK_LBM (1 << 6)
/* here is the possibility to define others aux macros */
#define SOF_DAI_INTEL_SSP_FRAME_PULSE_WIDTH_MAX 38
#define SOF_DAI_INTEL_SSP_SLOT_PADDING_MAX 31
/* SSP clocks control settings
*
* Macros for clks_control field in sof_ipc_dai_ssp_params struct.
*/
/* mclk 0 disable */
#define SOF_DAI_INTEL_SSP_MCLK_0_DISABLE BIT(0)
/* mclk 1 disable */
#define SOF_DAI_INTEL_SSP_MCLK_1_DISABLE BIT(1)
/* mclk keep active */
#define SOF_DAI_INTEL_SSP_CLKCTRL_MCLK_KA BIT(2)
/* bclk keep active */
#define SOF_DAI_INTEL_SSP_CLKCTRL_BCLK_KA BIT(3)
/* fs keep active */
#define SOF_DAI_INTEL_SSP_CLKCTRL_FS_KA BIT(4)
/* bclk idle */
#define SOF_DAI_INTEL_SSP_CLKCTRL_BCLK_IDLE_HIGH BIT(5)
/* SSP Configuration Request - SOF_IPC_DAI_SSP_CONFIG */
struct sof_ipc_dai_ssp_params {
struct sof_ipc_hdr hdr;
uint16_t reserved1;
uint16_t mclk_id;
uint32_t mclk_rate; /* mclk frequency in Hz */
uint32_t fsync_rate; /* fsync frequency in Hz */
uint32_t bclk_rate; /* bclk frequency in Hz */
/* TDM */
uint32_t tdm_slots;
uint32_t rx_slots;
uint32_t tx_slots;
/* data */
uint32_t sample_valid_bits;
uint16_t tdm_slot_width;
uint16_t reserved2; /* alignment */
/* MCLK */
uint32_t mclk_direction;
uint16_t frame_pulse_width;
uint16_t tdm_per_slot_padding_flag;
uint32_t clks_control;
uint32_t quirks;
} __packed;
/* HDA Configuration Request - SOF_IPC_DAI_HDA_CONFIG */
struct sof_ipc_dai_hda_params {
struct sof_ipc_hdr hdr;
uint32_t link_dma_ch;
} __packed;
/* DMIC Configuration Request - SOF_IPC_DAI_DMIC_CONFIG */
/* This struct is defined per 2ch PDM controller available in the platform.
* Normally it is sufficient to set the used microphone specific enables to 1
* and keep other parameters as zero. The customizations are:
*
* 1. If a device mixes different microphones types with different polarity
* and/or the absolute polarity matters the PCM signal from a microphone
* can be inverted with the controls.
*
* 2. If the microphones in a stereo pair do not appear in captured stream
* in desired order due to board schematics choises they can be swapped with
* the clk_edge parameter.
*
* 3. If PDM bit errors are seen in capture (poor quality) the skew parameter
* that delays the sampling time of data by half cycles of DMIC source clock
* can be tried for improvement. However there is no guarantee for this to fix
* data integrity problems.
*/
struct sof_ipc_dai_dmic_pdm_ctrl {
struct sof_ipc_hdr hdr;
uint16_t id; /**< PDM controller ID */
uint16_t enable_mic_a; /**< Use A (left) channel mic (0 or 1)*/
uint16_t enable_mic_b; /**< Use B (right) channel mic (0 or 1)*/
uint16_t polarity_mic_a; /**< Optionally invert mic A signal (0 or 1) */
uint16_t polarity_mic_b; /**< Optionally invert mic B signal (0 or 1) */
uint16_t clk_edge; /**< Optionally swap data clock edge (0 or 1) */
uint16_t skew; /**< Adjust PDM data sampling vs. clock (0..15) */
uint16_t reserved[3]; /**< Make sure the total size is 4 bytes aligned */
} __packed;
/* This struct contains the global settings for all 2ch PDM controllers. The
* version number used in configuration data is checked vs. version used by
* device driver src/drivers/dmic.c need to match. It is incremented from
* initial value 1 if updates done for the to driver would alter the operation
* of the microhone.
*
* Note: The microphone clock (pdmclk_min, pdmclk_max, duty_min, duty_max)
* parameters need to be set as defined in microphone data sheet. E.g. clock
* range 1.0 - 3.2 MHz is usually supported microphones. Some microphones are
* multi-mode capable and there may be denied mic clock frequencies between
* the modes. In such case set the clock range limits of the desired mode to
* avoid the driver to set clock to an illegal rate.
*
* The duty cycle could be set to 48-52% if not known. Generally these
* parameters can be altered within data sheet specified limits to match
* required audio application performance power.
*
* The microphone clock needs to be usually about 50-80 times the used audio
* sample rate. With highest sample rates above 48 kHz this can relaxed
* somewhat.
*
* The parameter wake_up_time describes how long time the microphone needs
* for the data line to produce valid output from mic clock start. The driver
* will mute the captured audio for the given time. The min_clock_on_time
* parameter is used to prevent too short clock bursts to happen. The driver
* will keep the clock active after capture stop if this time is not yet
* met. The unit for both is microseconds (us). Exceed of 100 ms will be
* treated as an error.
*/
struct sof_ipc_dai_dmic_params {
struct sof_ipc_hdr hdr;
uint32_t driver_ipc_version; /**< Version (1..N) */
uint32_t pdmclk_min; /**< Minimum microphone clock in Hz (100000..N) */
uint32_t pdmclk_max; /**< Maximum microphone clock in Hz (min...N) */
uint32_t fifo_fs; /**< FIFO sample rate in Hz (8000..96000) */
uint32_t reserved_1; /**< Reserved */
uint16_t fifo_bits; /**< FIFO word length (16 or 32) */
uint16_t reserved_2; /**< Reserved */
uint16_t duty_min; /**< Min. mic clock duty cycle in % (20..80) */
uint16_t duty_max; /**< Max. mic clock duty cycle in % (min..80) */
uint32_t num_pdm_active; /**< Number of active pdm controllers */
uint32_t wake_up_time; /**< Time from clock start to data (us) */
uint32_t min_clock_on_time; /**< Min. time that clk is kept on (us) */
/* reserved for future use */
uint32_t reserved[6];
/**< variable number of pdm controller config */
struct sof_ipc_dai_dmic_pdm_ctrl pdm[0];
} __packed;
#endif
/* SPDX-License-Identifier: ((GPL-2.0 WITH Linux-syscall-note) OR BSD-3-Clause) */
/*
* This file is provided under a dual BSD/GPLv2 license. When using or
* redistributing this file, you may do so under either license.
*
* Copyright(c) 2018 Intel Corporation. All rights reserved.
*/
#ifndef __INCLUDE_SOUND_SOF_DAI_H__
#define __INCLUDE_SOUND_SOF_DAI_H__
#include <sound/sof/header.h>
#include <sound/sof/dai-intel.h>
/*
* DAI Configuration.
*
* Each different DAI type will have it's own structure and IPC cmd.
*/
#define SOF_DAI_FMT_I2S 1 /**< I2S mode */
#define SOF_DAI_FMT_RIGHT_J 2 /**< Right Justified mode */
#define SOF_DAI_FMT_LEFT_J 3 /**< Left Justified mode */
#define SOF_DAI_FMT_DSP_A 4 /**< L data MSB after FRM LRC */
#define SOF_DAI_FMT_DSP_B 5 /**< L data MSB during FRM LRC */
#define SOF_DAI_FMT_PDM 6 /**< Pulse density modulation */
#define SOF_DAI_FMT_CONT (1 << 4) /**< continuous clock */
#define SOF_DAI_FMT_GATED (0 << 4) /**< clock is gated */
#define SOF_DAI_FMT_NB_NF (0 << 8) /**< normal bit clock + frame */
#define SOF_DAI_FMT_NB_IF (2 << 8) /**< normal BCLK + inv FRM */
#define SOF_DAI_FMT_IB_NF (3 << 8) /**< invert BCLK + nor FRM */
#define SOF_DAI_FMT_IB_IF (4 << 8) /**< invert BCLK + FRM */
#define SOF_DAI_FMT_CBM_CFM (0 << 12) /**< codec clk & FRM master */
#define SOF_DAI_FMT_CBS_CFM (2 << 12) /**< codec clk slave & FRM master */
#define SOF_DAI_FMT_CBM_CFS (3 << 12) /**< codec clk master & frame slave */
#define SOF_DAI_FMT_CBS_CFS (4 << 12) /**< codec clk & FRM slave */
#define SOF_DAI_FMT_FORMAT_MASK 0x000f
#define SOF_DAI_FMT_CLOCK_MASK 0x00f0
#define SOF_DAI_FMT_INV_MASK 0x0f00
#define SOF_DAI_FMT_MASTER_MASK 0xf000
/** \brief Types of DAI */
enum sof_ipc_dai_type {
SOF_DAI_INTEL_NONE = 0, /**< None */
SOF_DAI_INTEL_SSP, /**< Intel SSP */
SOF_DAI_INTEL_DMIC, /**< Intel DMIC */
SOF_DAI_INTEL_HDA, /**< Intel HD/A */
};
/* general purpose DAI configuration */
struct sof_ipc_dai_config {
struct sof_ipc_cmd_hdr hdr;
uint32_t type; /**< DAI type - enum sof_ipc_dai_type */
uint32_t dai_index; /**< index of this type dai */
/* physical protocol and clocking */
uint16_t format; /**< SOF_DAI_FMT_ */
uint16_t reserved16; /**< alignment */
/* reserved for future use */
uint32_t reserved[8];
/* HW specific data */
union {
struct sof_ipc_dai_ssp_params ssp;
struct sof_ipc_dai_dmic_params dmic;
struct sof_ipc_dai_hda_params hda;
};
} __packed;
#endif
/* SPDX-License-Identifier: ((GPL-2.0 WITH Linux-syscall-note) OR BSD-3-Clause) */
/*
* This file is provided under a dual BSD/GPLv2 license. When using or
* redistributing this file, you may do so under either license.
*
* Copyright(c) 2018 Intel Corporation. All rights reserved.
*/
#ifndef __INCLUDE_SOUND_SOF_HEADER_H__
#define __INCLUDE_SOUND_SOF_HEADER_H__
#include <uapi/sound/sof/abi.h>
/** \addtogroup sof_uapi uAPI
* SOF uAPI specification.
* @{
*/
/*
* IPC messages have a prefixed 32 bit identifier made up as follows :-
*
* 0xGCCCNNNN where
* G is global cmd type (4 bits)
* C is command type (12 bits)
* I is the ID number (16 bits) - monotonic and overflows
*
* This is sent at the start of the IPM message in the mailbox. Messages should
* not be sent in the doorbell (special exceptions for firmware .
*/
/* Global Message - Generic */
#define SOF_GLB_TYPE_SHIFT 28
#define SOF_GLB_TYPE_MASK (0xf << SOF_GLB_TYPE_SHIFT)
#define SOF_GLB_TYPE(x) ((x) << SOF_GLB_TYPE_SHIFT)
/* Command Message - Generic */
#define SOF_CMD_TYPE_SHIFT 16
#define SOF_CMD_TYPE_MASK (0xfff << SOF_CMD_TYPE_SHIFT)
#define SOF_CMD_TYPE(x) ((x) << SOF_CMD_TYPE_SHIFT)
/* Global Message Types */
#define SOF_IPC_GLB_REPLY SOF_GLB_TYPE(0x1U)
#define SOF_IPC_GLB_COMPOUND SOF_GLB_TYPE(0x2U)
#define SOF_IPC_GLB_TPLG_MSG SOF_GLB_TYPE(0x3U)
#define SOF_IPC_GLB_PM_MSG SOF_GLB_TYPE(0x4U)
#define SOF_IPC_GLB_COMP_MSG SOF_GLB_TYPE(0x5U)
#define SOF_IPC_GLB_STREAM_MSG SOF_GLB_TYPE(0x6U)
#define SOF_IPC_FW_READY SOF_GLB_TYPE(0x7U)
#define SOF_IPC_GLB_DAI_MSG SOF_GLB_TYPE(0x8U)
#define SOF_IPC_GLB_TRACE_MSG SOF_GLB_TYPE(0x9U)
/*
* DSP Command Message Types
*/
/* topology */
#define SOF_IPC_TPLG_COMP_NEW SOF_CMD_TYPE(0x001)
#define SOF_IPC_TPLG_COMP_FREE SOF_CMD_TYPE(0x002)
#define SOF_IPC_TPLG_COMP_CONNECT SOF_CMD_TYPE(0x003)
#define SOF_IPC_TPLG_PIPE_NEW SOF_CMD_TYPE(0x010)
#define SOF_IPC_TPLG_PIPE_FREE SOF_CMD_TYPE(0x011)
#define SOF_IPC_TPLG_PIPE_CONNECT SOF_CMD_TYPE(0x012)
#define SOF_IPC_TPLG_PIPE_COMPLETE SOF_CMD_TYPE(0x013)
#define SOF_IPC_TPLG_BUFFER_NEW SOF_CMD_TYPE(0x020)
#define SOF_IPC_TPLG_BUFFER_FREE SOF_CMD_TYPE(0x021)
/* PM */
#define SOF_IPC_PM_CTX_SAVE SOF_CMD_TYPE(0x001)
#define SOF_IPC_PM_CTX_RESTORE SOF_CMD_TYPE(0x002)
#define SOF_IPC_PM_CTX_SIZE SOF_CMD_TYPE(0x003)
#define SOF_IPC_PM_CLK_SET SOF_CMD_TYPE(0x004)
#define SOF_IPC_PM_CLK_GET SOF_CMD_TYPE(0x005)
#define SOF_IPC_PM_CLK_REQ SOF_CMD_TYPE(0x006)
#define SOF_IPC_PM_CORE_ENABLE SOF_CMD_TYPE(0x007)
/* component runtime config - multiple different types */
#define SOF_IPC_COMP_SET_VALUE SOF_CMD_TYPE(0x001)
#define SOF_IPC_COMP_GET_VALUE SOF_CMD_TYPE(0x002)
#define SOF_IPC_COMP_SET_DATA SOF_CMD_TYPE(0x003)
#define SOF_IPC_COMP_GET_DATA SOF_CMD_TYPE(0x004)
/* DAI messages */
#define SOF_IPC_DAI_CONFIG SOF_CMD_TYPE(0x001)
#define SOF_IPC_DAI_LOOPBACK SOF_CMD_TYPE(0x002)
/* stream */
#define SOF_IPC_STREAM_PCM_PARAMS SOF_CMD_TYPE(0x001)
#define SOF_IPC_STREAM_PCM_PARAMS_REPLY SOF_CMD_TYPE(0x002)
#define SOF_IPC_STREAM_PCM_FREE SOF_CMD_TYPE(0x003)
#define SOF_IPC_STREAM_TRIG_START SOF_CMD_TYPE(0x004)
#define SOF_IPC_STREAM_TRIG_STOP SOF_CMD_TYPE(0x005)
#define SOF_IPC_STREAM_TRIG_PAUSE SOF_CMD_TYPE(0x006)
#define SOF_IPC_STREAM_TRIG_RELEASE SOF_CMD_TYPE(0x007)
#define SOF_IPC_STREAM_TRIG_DRAIN SOF_CMD_TYPE(0x008)
#define SOF_IPC_STREAM_TRIG_XRUN SOF_CMD_TYPE(0x009)
#define SOF_IPC_STREAM_POSITION SOF_CMD_TYPE(0x00a)
#define SOF_IPC_STREAM_VORBIS_PARAMS SOF_CMD_TYPE(0x010)
#define SOF_IPC_STREAM_VORBIS_FREE SOF_CMD_TYPE(0x011)
/* trace and debug */
#define SOF_IPC_TRACE_DMA_PARAMS SOF_CMD_TYPE(0x001)
#define SOF_IPC_TRACE_DMA_POSITION SOF_CMD_TYPE(0x002)
/* Get message component id */
#define SOF_IPC_MESSAGE_ID(x) ((x) & 0xffff)
/* maximum message size for mailbox Tx/Rx */
#define SOF_IPC_MSG_MAX_SIZE 384
/*
* Structure Header - Header for all IPC structures except command structs.
* The size can be greater than the structure size and that means there is
* extended bespoke data beyond the end of the structure including variable
* arrays.
*/
struct sof_ipc_hdr {
uint32_t size; /**< size of structure */
} __packed;
/*
* Command Header - Header for all IPC commands. Identifies IPC message.
* The size can be greater than the structure size and that means there is
* extended bespoke data beyond the end of the structure including variable
* arrays.
*/
struct sof_ipc_cmd_hdr {
uint32_t size; /**< size of structure */
uint32_t cmd; /**< SOF_IPC_GLB_ + cmd */
} __packed;
/*
* Generic reply message. Some commands override this with their own reply
* types that must include this at start.
*/
struct sof_ipc_reply {
struct sof_ipc_cmd_hdr hdr;
int32_t error; /**< negative error numbers */
} __packed;
/*
* Compound commands - SOF_IPC_GLB_COMPOUND.
*
* Compound commands are sent to the DSP as a single IPC operation. The
* commands are split into blocks and each block has a header. This header
* identifies the command type and the number of commands before the next
* header.
*/
struct sof_ipc_compound_hdr {
struct sof_ipc_cmd_hdr hdr;
uint32_t count; /**< count of 0 means end of compound sequence */
} __packed;
/** @}*/
#endif
/* SPDX-License-Identifier: ((GPL-2.0 WITH Linux-syscall-note) OR BSD-3-Clause) */
/*
* This file is provided under a dual BSD/GPLv2 license. When using or
* redistributing this file, you may do so under either license.
*
* Copyright(c) 2018 Intel Corporation. All rights reserved.
*/
#ifndef __INCLUDE_SOUND_SOF_INFO_H__
#define __INCLUDE_SOUND_SOF_INFO_H__
#include <sound/sof/header.h>
#include <sound/sof/stream.h>
/*
* Firmware boot and version
*/
#define SOF_IPC_MAX_ELEMS 16
/* extended data types that can be appended onto end of sof_ipc_fw_ready */
enum sof_ipc_ext_data {
SOF_IPC_EXT_DMA_BUFFER = 0,
SOF_IPC_EXT_WINDOW,
};
/* FW version - SOF_IPC_GLB_VERSION */
struct sof_ipc_fw_version {
struct sof_ipc_hdr hdr;
uint16_t major;
uint16_t minor;
uint16_t micro;
uint16_t build;
uint8_t date[12];
uint8_t time[10];
uint8_t tag[6];
uint32_t abi_version;
/* reserved for future use */
uint32_t reserved[4];
} __packed;
/* FW ready Message - sent by firmware when boot has completed */
struct sof_ipc_fw_ready {
struct sof_ipc_cmd_hdr hdr;
uint32_t dspbox_offset; /* dsp initiated IPC mailbox */
uint32_t hostbox_offset; /* host initiated IPC mailbox */
uint32_t dspbox_size;
uint32_t hostbox_size;
struct sof_ipc_fw_version version;
/* Miscellaneous debug flags showing build/debug features enabled */
union {
uint64_t reserved;
struct {
uint64_t build:1;
uint64_t locks:1;
uint64_t locks_verbose:1;
uint64_t gdb:1;
} bits;
} debug;
/* reserved for future use */
uint32_t reserved[4];
} __packed;
/*
* Extended Firmware data. All optional, depends on platform/arch.
*/
enum sof_ipc_region {
SOF_IPC_REGION_DOWNBOX = 0,
SOF_IPC_REGION_UPBOX,
SOF_IPC_REGION_TRACE,
SOF_IPC_REGION_DEBUG,
SOF_IPC_REGION_STREAM,
SOF_IPC_REGION_REGS,
SOF_IPC_REGION_EXCEPTION,
};
struct sof_ipc_ext_data_hdr {
struct sof_ipc_cmd_hdr hdr;
uint32_t type; /**< SOF_IPC_EXT_ */
} __packed;
struct sof_ipc_dma_buffer_elem {
struct sof_ipc_hdr hdr;
uint32_t type; /**< SOF_IPC_REGION_ */
uint32_t id; /**< platform specific - used to map to host memory */
struct sof_ipc_host_buffer buffer;
} __packed;
/* extended data DMA buffers for IPC, trace and debug */
struct sof_ipc_dma_buffer_data {
struct sof_ipc_ext_data_hdr ext_hdr;
uint32_t num_buffers;
/* host files in buffer[n].buffer */
struct sof_ipc_dma_buffer_elem buffer[];
} __packed;
struct sof_ipc_window_elem {
struct sof_ipc_hdr hdr;
uint32_t type; /**< SOF_IPC_REGION_ */
uint32_t id; /**< platform specific - used to map to host memory */
uint32_t flags; /**< R, W, RW, etc - to define */
uint32_t size; /**< size of region in bytes */
/* offset in window region as windows can be partitioned */
uint32_t offset;
} __packed;
/* extended data memory windows for IPC, trace and debug */
struct sof_ipc_window {
struct sof_ipc_ext_data_hdr ext_hdr;
uint32_t num_windows;
struct sof_ipc_window_elem window[];
} __packed;
#endif
/* SPDX-License-Identifier: ((GPL-2.0 WITH Linux-syscall-note) OR BSD-3-Clause) */
/*
* This file is provided under a dual BSD/GPLv2 license. When using or
* redistributing this file, you may do so under either license.
*
* Copyright(c) 2018 Intel Corporation. All rights reserved.
*/
#ifndef __INCLUDE_SOUND_SOF_PM_H__
#define __INCLUDE_SOUND_SOF_PM_H__
#include <sound/sof/header.h>
/*
* PM
*/
/* PM context element */
struct sof_ipc_pm_ctx_elem {
struct sof_ipc_hdr hdr;
uint32_t type;
uint32_t size;
uint64_t addr;
} __packed;
/*
* PM context - SOF_IPC_PM_CTX_SAVE, SOF_IPC_PM_CTX_RESTORE,
* SOF_IPC_PM_CTX_SIZE
*/
struct sof_ipc_pm_ctx {
struct sof_ipc_cmd_hdr hdr;
struct sof_ipc_host_buffer buffer;
uint32_t num_elems;
uint32_t size;
/* reserved for future use */
uint32_t reserved[8];
struct sof_ipc_pm_ctx_elem elems[];
} __packed;
/* enable or disable cores - SOF_IPC_PM_CORE_ENABLE */
struct sof_ipc_pm_core_config {
struct sof_ipc_cmd_hdr hdr;
uint32_t enable_mask;
} __packed;
#endif
/* SPDX-License-Identifier: ((GPL-2.0 WITH Linux-syscall-note) OR BSD-3-Clause) */
/*
* This file is provided under a dual BSD/GPLv2 license. When using or
* redistributing this file, you may do so under either license.
*
* Copyright(c) 2018 Intel Corporation. All rights reserved.
*/
#ifndef __INCLUDE_SOUND_SOF_STREAM_H__
#define __INCLUDE_SOUND_SOF_STREAM_H__
#include <sound/sof/header.h>
/*
* Stream configuration.
*/
#define SOF_IPC_MAX_CHANNELS 8
/* common sample rates for use in masks */
#define SOF_RATE_8000 (1 << 0) /**< 8000Hz */
#define SOF_RATE_11025 (1 << 1) /**< 11025Hz */
#define SOF_RATE_12000 (1 << 2) /**< 12000Hz */
#define SOF_RATE_16000 (1 << 3) /**< 16000Hz */
#define SOF_RATE_22050 (1 << 4) /**< 22050Hz */
#define SOF_RATE_24000 (1 << 5) /**< 24000Hz */
#define SOF_RATE_32000 (1 << 6) /**< 32000Hz */
#define SOF_RATE_44100 (1 << 7) /**< 44100Hz */
#define SOF_RATE_48000 (1 << 8) /**< 48000Hz */
#define SOF_RATE_64000 (1 << 9) /**< 64000Hz */
#define SOF_RATE_88200 (1 << 10) /**< 88200Hz */
#define SOF_RATE_96000 (1 << 11) /**< 96000Hz */
#define SOF_RATE_176400 (1 << 12) /**< 176400Hz */
#define SOF_RATE_192000 (1 << 13) /**< 192000Hz */
/* continuous and non-standard rates for flexibility */
#define SOF_RATE_CONTINUOUS (1 << 30) /**< range */
#define SOF_RATE_KNOT (1 << 31) /**< non-continuous */
/* generic PCM flags for runtime settings */
#define SOF_PCM_FLAG_XRUN_STOP (1 << 0) /**< Stop on any XRUN */
/* stream PCM frame format */
enum sof_ipc_frame {
SOF_IPC_FRAME_S16_LE = 0,
SOF_IPC_FRAME_S24_4LE,
SOF_IPC_FRAME_S32_LE,
SOF_IPC_FRAME_FLOAT,
/* other formats here */
};
/* stream buffer format */
enum sof_ipc_buffer_format {
SOF_IPC_BUFFER_INTERLEAVED,
SOF_IPC_BUFFER_NONINTERLEAVED,
/* other formats here */
};
/* stream direction */
enum sof_ipc_stream_direction {
SOF_IPC_STREAM_PLAYBACK = 0,
SOF_IPC_STREAM_CAPTURE,
};
/* stream ring info */
struct sof_ipc_host_buffer {
struct sof_ipc_hdr hdr;
uint32_t phy_addr;
uint32_t pages;
uint32_t size;
uint32_t reserved[3];
} __packed;
struct sof_ipc_stream_params {
struct sof_ipc_hdr hdr;
struct sof_ipc_host_buffer buffer;
uint32_t direction; /**< enum sof_ipc_stream_direction */
uint32_t frame_fmt; /**< enum sof_ipc_frame */
uint32_t buffer_fmt; /**< enum sof_ipc_buffer_format */
uint32_t rate;
uint16_t stream_tag;
uint16_t channels;
uint16_t sample_valid_bytes;
uint16_t sample_container_bytes;
/* for notifying host period has completed - 0 means no period IRQ */
uint32_t host_period_bytes;
uint32_t reserved[2];
uint16_t chmap[SOF_IPC_MAX_CHANNELS]; /**< channel map - SOF_CHMAP_ */
} __packed;
/* PCM params info - SOF_IPC_STREAM_PCM_PARAMS */
struct sof_ipc_pcm_params {
struct sof_ipc_cmd_hdr hdr;
uint32_t comp_id;
uint32_t flags; /**< generic PCM flags - SOF_PCM_FLAG_ */
uint32_t reserved[2];
struct sof_ipc_stream_params params;
} __packed;
/* PCM params info reply - SOF_IPC_STREAM_PCM_PARAMS_REPLY */
struct sof_ipc_pcm_params_reply {
struct sof_ipc_reply rhdr;
uint32_t comp_id;
uint32_t posn_offset;
} __packed;
/* free stream - SOF_IPC_STREAM_PCM_PARAMS */
struct sof_ipc_stream {
struct sof_ipc_cmd_hdr hdr;
uint32_t comp_id;
} __packed;
/* flags indicating which time stamps are in sync with each other */
#define SOF_TIME_HOST_SYNC (1 << 0)
#define SOF_TIME_DAI_SYNC (1 << 1)
#define SOF_TIME_WALL_SYNC (1 << 2)
#define SOF_TIME_STAMP_SYNC (1 << 3)
/* flags indicating which time stamps are valid */
#define SOF_TIME_HOST_VALID (1 << 8)
#define SOF_TIME_DAI_VALID (1 << 9)
#define SOF_TIME_WALL_VALID (1 << 10)
#define SOF_TIME_STAMP_VALID (1 << 11)
/* flags indicating time stamps are 64bit else 3use low 32bit */
#define SOF_TIME_HOST_64 (1 << 16)
#define SOF_TIME_DAI_64 (1 << 17)
#define SOF_TIME_WALL_64 (1 << 18)
#define SOF_TIME_STAMP_64 (1 << 19)
struct sof_ipc_stream_posn {
struct sof_ipc_reply rhdr;
uint32_t comp_id; /**< host component ID */
uint32_t flags; /**< SOF_TIME_ */
uint32_t wallclock_hz; /**< frequency of wallclock in Hz */
uint32_t timestamp_ns; /**< resolution of timestamp in ns */
uint64_t host_posn; /**< host DMA position in bytes */
uint64_t dai_posn; /**< DAI DMA position in bytes */
uint64_t comp_posn; /**< comp position in bytes */
uint64_t wallclock; /**< audio wall clock */
uint64_t timestamp; /**< system time stamp */
uint32_t xrun_comp_id; /**< comp ID of XRUN component */
int32_t xrun_size; /**< XRUN size in bytes */
} __packed;
#endif
/* SPDX-License-Identifier: ((GPL-2.0 WITH Linux-syscall-note) OR BSD-3-Clause) */
/*
* This file is provided under a dual BSD/GPLv2 license. When using or
* redistributing this file, you may do so under either license.
*
* Copyright(c) 2018 Intel Corporation. All rights reserved.
*/
#ifndef __INCLUDE_SOUND_SOF_TOPOLOGY_H__
#define __INCLUDE_SOUND_SOF_TOPOLOGY_H__
#include <sound/sof/header.h>
/*
* Component
*/
/* types of component */
enum sof_comp_type {
SOF_COMP_NONE = 0,
SOF_COMP_HOST,
SOF_COMP_DAI,
SOF_COMP_SG_HOST, /**< scatter gather variant */
SOF_COMP_SG_DAI, /**< scatter gather variant */
SOF_COMP_VOLUME,
SOF_COMP_MIXER,
SOF_COMP_MUX,
SOF_COMP_SRC,
SOF_COMP_SPLITTER,
SOF_COMP_TONE,
SOF_COMP_SWITCH,
SOF_COMP_BUFFER,
SOF_COMP_EQ_IIR,
SOF_COMP_EQ_FIR,
SOF_COMP_KEYWORD_DETECT,
SOF_COMP_KPB, /* A key phrase buffer component */
SOF_COMP_SELECTOR, /**< channel selector component */
/* keep FILEREAD/FILEWRITE as the last ones */
SOF_COMP_FILEREAD = 10000, /**< host test based file IO */
SOF_COMP_FILEWRITE = 10001, /**< host test based file IO */
};
/* XRUN action for component */
#define SOF_XRUN_STOP 1 /**< stop stream */
#define SOF_XRUN_UNDER_ZERO 2 /**< send 0s to sink */
#define SOF_XRUN_OVER_NULL 4 /**< send data to NULL */
/* create new generic component - SOF_IPC_TPLG_COMP_NEW */
struct sof_ipc_comp {
struct sof_ipc_cmd_hdr hdr;
uint32_t id;
enum sof_comp_type type;
uint32_t pipeline_id;
/* reserved for future use */
uint32_t reserved[2];
} __packed;
/*
* Component Buffers
*/
/*
* SOF memory capabilities, add new ones at the end
*/
#define SOF_MEM_CAPS_RAM (1 << 0)
#define SOF_MEM_CAPS_ROM (1 << 1)
#define SOF_MEM_CAPS_EXT (1 << 2) /**< external */
#define SOF_MEM_CAPS_LP (1 << 3) /**< low power */
#define SOF_MEM_CAPS_HP (1 << 4) /**< high performance */
#define SOF_MEM_CAPS_DMA (1 << 5) /**< DMA'able */
#define SOF_MEM_CAPS_CACHE (1 << 6) /**< cacheable */
#define SOF_MEM_CAPS_EXEC (1 << 7) /**< executable */
/* create new component buffer - SOF_IPC_TPLG_BUFFER_NEW */
struct sof_ipc_buffer {
struct sof_ipc_comp comp;
uint32_t size; /**< buffer size in bytes */
uint32_t caps; /**< SOF_MEM_CAPS_ */
} __packed;
/* generic component config data - must always be after struct sof_ipc_comp */
struct sof_ipc_comp_config {
struct sof_ipc_cmd_hdr hdr;
uint32_t periods_sink; /**< 0 means variable */
uint32_t periods_source; /**< 0 means variable */
uint32_t reserved1; /**< reserved */
uint32_t frame_fmt; /**< SOF_IPC_FRAME_ */
uint32_t xrun_action;
/* reserved for future use */
uint32_t reserved[2];
} __packed;
/* generic host component */
struct sof_ipc_comp_host {
struct sof_ipc_comp comp;
struct sof_ipc_comp_config config;
uint32_t direction; /**< SOF_IPC_STREAM_ */
uint32_t no_irq; /**< don't send periodic IRQ to host/DSP */
uint32_t dmac_config; /**< DMA engine specific */
} __packed;
/* generic DAI component */
struct sof_ipc_comp_dai {
struct sof_ipc_comp comp;
struct sof_ipc_comp_config config;
uint32_t direction; /**< SOF_IPC_STREAM_ */
uint32_t dai_index; /**< index of this type dai */
uint32_t type; /**< DAI type - SOF_DAI_ */
uint32_t reserved; /**< reserved */
} __packed;
/* generic mixer component */
struct sof_ipc_comp_mixer {
struct sof_ipc_comp comp;
struct sof_ipc_comp_config config;
} __packed;
/* volume ramping types */
enum sof_volume_ramp {
SOF_VOLUME_LINEAR = 0,
SOF_VOLUME_LOG,
SOF_VOLUME_LINEAR_ZC,
SOF_VOLUME_LOG_ZC,
};
/* generic volume component */
struct sof_ipc_comp_volume {
struct sof_ipc_comp comp;
struct sof_ipc_comp_config config;
uint32_t channels;
uint32_t min_value;
uint32_t max_value;
uint32_t ramp; /**< SOF_VOLUME_ */
uint32_t initial_ramp; /**< ramp space in ms */
} __packed;
/* generic SRC component */
struct sof_ipc_comp_src {
struct sof_ipc_comp comp;
struct sof_ipc_comp_config config;
/* either source or sink rate must be non zero */
uint32_t source_rate; /**< source rate or 0 for variable */
uint32_t sink_rate; /**< sink rate or 0 for variable */
uint32_t rate_mask; /**< SOF_RATE_ supported rates */
} __packed;
/* generic MUX component */
struct sof_ipc_comp_mux {
struct sof_ipc_comp comp;
struct sof_ipc_comp_config config;
} __packed;
/* generic tone generator component */
struct sof_ipc_comp_tone {
struct sof_ipc_comp comp;
struct sof_ipc_comp_config config;
int32_t sample_rate;
int32_t frequency;
int32_t amplitude;
int32_t freq_mult;
int32_t ampl_mult;
int32_t length;
int32_t period;
int32_t repeats;
int32_t ramp_step;
} __packed;
/** \brief Types of processing components */
enum sof_ipc_process_type {
SOF_PROCESS_NONE = 0, /**< None */
SOF_PROCESS_EQFIR, /**< Intel FIR */
SOF_PROCESS_EQIIR, /**< Intel IIR */
SOF_PROCESS_KEYWORD_DETECT, /**< Keyword Detection */
SOF_PROCESS_KPB, /**< KeyPhrase Buffer Manager */
SOF_PROCESS_CHAN_SELECTOR, /**< Channel Selector */
};
/* generic "effect", "codec" or proprietary processing component */
struct sof_ipc_comp_process {
struct sof_ipc_comp comp;
struct sof_ipc_comp_config config;
uint32_t size; /**< size of bespoke data section in bytes */
uint32_t type; /**< sof_ipc_process_type */
/* reserved for future use */
uint32_t reserved[7];
unsigned char data[0];
} __packed;
/* frees components, buffers and pipelines
* SOF_IPC_TPLG_COMP_FREE, SOF_IPC_TPLG_PIPE_FREE, SOF_IPC_TPLG_BUFFER_FREE
*/
struct sof_ipc_free {
struct sof_ipc_cmd_hdr hdr;
uint32_t id;
} __packed;
struct sof_ipc_comp_reply {
struct sof_ipc_reply rhdr;
uint32_t id;
uint32_t offset;
} __packed;
/*
* Pipeline
*/
/** \brief Types of pipeline scheduling time domains */
enum sof_ipc_pipe_sched_time_domain {
SOF_TIME_DOMAIN_DMA = 0, /**< DMA interrupt */
SOF_TIME_DOMAIN_TIMER, /**< Timer interrupt */
};
/* new pipeline - SOF_IPC_TPLG_PIPE_NEW */
struct sof_ipc_pipe_new {
struct sof_ipc_cmd_hdr hdr;
uint32_t comp_id; /**< component id for pipeline */
uint32_t pipeline_id; /**< pipeline id */
uint32_t sched_id; /**< Scheduling component id */
uint32_t core; /**< core we run on */
uint32_t period; /**< execution period in us*/
uint32_t priority; /**< priority level 0 (low) to 10 (max) */
uint32_t period_mips; /**< worst case instruction count per period */
uint32_t frames_per_sched;/**< output frames of pipeline, 0 is variable */
uint32_t xrun_limit_usecs; /**< report xruns greater than limit */
uint32_t time_domain; /**< scheduling time domain */
} __packed;
/* pipeline construction complete - SOF_IPC_TPLG_PIPE_COMPLETE */
struct sof_ipc_pipe_ready {
struct sof_ipc_cmd_hdr hdr;
uint32_t comp_id;
} __packed;
struct sof_ipc_pipe_free {
struct sof_ipc_cmd_hdr hdr;
uint32_t comp_id;
} __packed;
/* connect two components in pipeline - SOF_IPC_TPLG_COMP_CONNECT */
struct sof_ipc_pipe_comp_connect {
struct sof_ipc_cmd_hdr hdr;
uint32_t source_id;
uint32_t sink_id;
} __packed;
/* external events */
enum sof_event_types {
SOF_EVENT_NONE = 0,
SOF_KEYWORD_DETECT_DAPM_EVENT,
};
#endif
/* SPDX-License-Identifier: ((GPL-2.0 WITH Linux-syscall-note) OR BSD-3-Clause) */
/*
* This file is provided under a dual BSD/GPLv2 license. When using or
* redistributing this file, you may do so under either license.
*
* Copyright(c) 2018 Intel Corporation. All rights reserved.
*/
#ifndef __INCLUDE_SOUND_SOF_TRACE_H__
#define __INCLUDE_SOUND_SOF_TRACE_H__
#include <sound/sof/header.h>
#include <sound/sof/stream.h>
/*
* DMA for Trace
*/
#define SOF_TRACE_FILENAME_SIZE 32
/* DMA for Trace params info - SOF_IPC_DEBUG_DMA_PARAMS */
struct sof_ipc_dma_trace_params {
struct sof_ipc_cmd_hdr hdr;
struct sof_ipc_host_buffer buffer;
uint32_t stream_tag;
} __packed;
/* DMA for Trace params info - SOF_IPC_DEBUG_DMA_PARAMS */
struct sof_ipc_dma_trace_posn {
struct sof_ipc_reply rhdr;
uint32_t host_offset; /* Offset of DMA host buffer */
uint32_t overflow; /* overflow bytes if any */
uint32_t messages; /* total trace messages */
} __packed;
/*
* Commom debug
*/
/*
* SOF panic codes
*/
#define SOF_IPC_PANIC_MAGIC 0x0dead000
#define SOF_IPC_PANIC_MAGIC_MASK 0x0ffff000
#define SOF_IPC_PANIC_CODE_MASK 0x00000fff
#define SOF_IPC_PANIC_MEM (SOF_IPC_PANIC_MAGIC | 0x0)
#define SOF_IPC_PANIC_WORK (SOF_IPC_PANIC_MAGIC | 0x1)
#define SOF_IPC_PANIC_IPC (SOF_IPC_PANIC_MAGIC | 0x2)
#define SOF_IPC_PANIC_ARCH (SOF_IPC_PANIC_MAGIC | 0x3)
#define SOF_IPC_PANIC_PLATFORM (SOF_IPC_PANIC_MAGIC | 0x4)
#define SOF_IPC_PANIC_TASK (SOF_IPC_PANIC_MAGIC | 0x5)
#define SOF_IPC_PANIC_EXCEPTION (SOF_IPC_PANIC_MAGIC | 0x6)
#define SOF_IPC_PANIC_DEADLOCK (SOF_IPC_PANIC_MAGIC | 0x7)
#define SOF_IPC_PANIC_STACK (SOF_IPC_PANIC_MAGIC | 0x8)
#define SOF_IPC_PANIC_IDLE (SOF_IPC_PANIC_MAGIC | 0x9)
#define SOF_IPC_PANIC_WFI (SOF_IPC_PANIC_MAGIC | 0xa)
#define SOF_IPC_PANIC_ASSERT (SOF_IPC_PANIC_MAGIC | 0xb)
/* panic info include filename and line number */
struct sof_ipc_panic_info {
struct sof_ipc_hdr hdr;
uint32_t code; /* SOF_IPC_PANIC_ */
char filename[SOF_TRACE_FILENAME_SIZE];
uint32_t linenum;
} __packed;
#endif
/* SPDX-License-Identifier: ((GPL-2.0 WITH Linux-syscall-note) OR BSD-3-Clause) */
/*
* This file is provided under a dual BSD/GPLv2 license. When using or
* redistributing this file, you may do so under either license.
*
* Copyright(c) 2018 Intel Corporation. All rights reserved.
*/
#ifndef __INCLUDE_SOUND_SOF_XTENSA_H__
#define __INCLUDE_SOUND_SOF_XTENSA_H__
#include <sound/sof/header.h>
/*
* Architecture specific debug
*/
/* Xtensa Firmware Oops data */
struct sof_ipc_dsp_oops_xtensa {
struct sof_ipc_hdr hdr;
uint32_t exccause;
uint32_t excvaddr;
uint32_t ps;
uint32_t epc1;
uint32_t epc2;
uint32_t epc3;
uint32_t epc4;
uint32_t epc5;
uint32_t epc6;
uint32_t epc7;
uint32_t eps2;
uint32_t eps3;
uint32_t eps4;
uint32_t eps5;
uint32_t eps6;
uint32_t eps7;
uint32_t depc;
uint32_t intenable;
uint32_t interrupt;
uint32_t sar;
uint32_t stack;
} __packed;
#endif
/* SPDX-License-Identifier: ((GPL-2.0 WITH Linux-syscall-note) OR BSD-3-Clause) */
/*
* This file is provided under a dual BSD/GPLv2 license. When using or
* redistributing this file, you may do so under either license.
*
* Copyright(c) 2018 Intel Corporation. All rights reserved.
*/
/**
* SOF ABI versioning is based on Semantic Versioning where we have a given
* MAJOR.MINOR.PATCH version number. See https://semver.org/
*
* Rules for incrementing or changing version :-
*
* 1) Increment MAJOR version if you make incompatible API changes. MINOR and
* PATCH should be reset to 0.
*
* 2) Increment MINOR version if you add backwards compatible features or
* changes. PATCH should be reset to 0.
*
* 3) Increment PATCH version if you add backwards compatible bug fixes.
*/
#ifndef __INCLUDE_UAPI_SOUND_SOF_ABI_H__
#define __INCLUDE_UAPI_SOUND_SOF_ABI_H__
/* SOF ABI version major, minor and patch numbers */
#define SOF_ABI_MAJOR 3
#define SOF_ABI_MINOR 4
#define SOF_ABI_PATCH 0
/* SOF ABI version number. Format within 32bit word is MMmmmppp */
#define SOF_ABI_MAJOR_SHIFT 24
#define SOF_ABI_MAJOR_MASK 0xff
#define SOF_ABI_MINOR_SHIFT 12
#define SOF_ABI_MINOR_MASK 0xfff
#define SOF_ABI_PATCH_SHIFT 0
#define SOF_ABI_PATCH_MASK 0xfff
#define SOF_ABI_VER(major, minor, patch) \
(((major) << SOF_ABI_MAJOR_SHIFT) | \
((minor) << SOF_ABI_MINOR_SHIFT) | \
((patch) << SOF_ABI_PATCH_SHIFT))
#define SOF_ABI_VERSION_MAJOR(version) \
(((version) >> SOF_ABI_MAJOR_SHIFT) & SOF_ABI_MAJOR_MASK)
#define SOF_ABI_VERSION_MINOR(version) \
(((version) >> SOF_ABI_MINOR_SHIFT) & SOF_ABI_MINOR_MASK)
#define SOF_ABI_VERSION_PATCH(version) \
(((version) >> SOF_ABI_PATCH_SHIFT) & SOF_ABI_PATCH_MASK)
#define SOF_ABI_VERSION_INCOMPATIBLE(sof_ver, client_ver) \
(SOF_ABI_VERSION_MAJOR((sof_ver)) != \
SOF_ABI_VERSION_MAJOR((client_ver)) \
)
#define SOF_ABI_VERSION SOF_ABI_VER(SOF_ABI_MAJOR, SOF_ABI_MINOR, SOF_ABI_PATCH)
/* SOF ABI magic number "SOF\0". */
#define SOF_ABI_MAGIC 0x00464F53
#endif
/* SPDX-License-Identifier: ((GPL-2.0 WITH Linux-syscall-note) OR BSD-3-Clause) */
/*
* This file is provided under a dual BSD/GPLv2 license. When using or
* redistributing this file, you may do so under either license.
*
* Copyright(c) 2018 Intel Corporation. All rights reserved.
*/
#ifndef __INCLUDE_UAPI_SOUND_SOF_USER_EQ_H__
#define __INCLUDE_UAPI_SOUND_SOF_USER_EQ_H__
/* FIR EQ type */
#define SOF_EQ_FIR_IDX_SWITCH 0
#define SOF_EQ_FIR_MAX_SIZE 4096 /* Max size allowed for coef data in bytes */
#define SOF_EQ_FIR_MAX_LENGTH 192 /* Max length for individual filter */
#define SOF_EQ_FIR_MAX_RESPONSES 8 /* A blob can define max 8 FIR EQs */
/*
* eq_fir_configuration data structure contains this information
* uint32_t size
* This is the number of bytes need to store the received EQ
* configuration.
* uint16_t channels_in_config
* This describes the number of channels in this EQ config data. It
* can be different from PLATFORM_MAX_CHANNELS.
* uint16_t number_of_responses
* 0=no responses, 1=one response defined, 2=two responses defined, etc.
* int16_t data[]
* assign_response[channels_in_config]
* 0 = use first response, 1 = use 2nd response, etc.
* E.g. {0, 0, 0, 0, 1, 1, 1, 1} would apply to channels 0-3 the
* same first defined response and for to channels 4-7 the second.
* coef_data[]
* Repeated data
* { filter_length, output_shift, h[] }
* for every EQ response defined where vector h has filter_length
* number of coefficients. Coefficients in h[] are in Q1.15 format.
* E.g. 16384 (Q1.15) = 0.5. The shifts are number of right shifts.
*
* NOTE: The channels_in_config must be even to have coef_data aligned to
* 32 bit word in RAM. Therefore a mono EQ assign must be duplicated to 2ch
* even if it would never used. Similarly a 5ch EQ assign must be increased
* to 6ch. EQ init will return an error if this is not met.
*
* NOTE: The filter_length must be multiple of four. Therefore the filter must
* be padded from the end with zeros have this condition met.
*/
struct sof_eq_fir_config {
uint32_t size;
uint16_t channels_in_config;
uint16_t number_of_responses;
/* reserved */
uint32_t reserved[4];
int16_t data[];
} __packed;
struct sof_eq_fir_coef_data {
int16_t length; /* Number of FIR taps */
int16_t out_shift; /* Amount of right shifts at output */
/* reserved */
uint32_t reserved[4];
int16_t coef[]; /* FIR coefficients */
} __packed;
/* In the struct above there's two 16 bit words (length, shift) and four
* reserved 32 bit words before the actual FIR coefficients. This information
* is used in parsing of the configuration blob.
*/
#define SOF_EQ_FIR_COEF_NHEADER \
(sizeof(struct sof_eq_fir_coef_data) / sizeof(int16_t))
/* IIR EQ type */
#define SOF_EQ_IIR_IDX_SWITCH 0
#define SOF_EQ_IIR_MAX_SIZE 1024 /* Max size allowed for coef data in bytes */
#define SOF_EQ_IIR_MAX_RESPONSES 8 /* A blob can define max 8 IIR EQs */
/* eq_iir_configuration
* uint32_t channels_in_config
* This describes the number of channels in this EQ config data. It
* can be different from PLATFORM_MAX_CHANNELS.
* uint32_t number_of_responses_defined
* 0=no responses, 1=one response defined, 2=two responses defined, etc.
* int32_t data[]
* Data consist of two parts. First is the response assign vector that
* has length of channels_in_config. The latter part is coefficient
* data.
* uint32_t assign_response[channels_in_config]
* -1 = not defined, 0 = use first response, 1 = use 2nd, etc.
* E.g. {0, 0, 0, 0, -1, -1, -1, -1} would apply to channels 0-3 the
* same first defined response and leave channels 4-7 unequalized.
* coefficient_data[]
* <1st EQ>
* uint32_t num_biquads
* uint32_t num_biquads_in_series
* <1st biquad>
* int32_t coef_a2 Q2.30 format
* int32_t coef_a1 Q2.30 format
* int32_t coef_b2 Q2.30 format
* int32_t coef_b1 Q2.30 format
* int32_t coef_b0 Q2.30 format
* int32_t output_shift number of shifts right, shift left is negative
* int32_t output_gain Q2.14 format
* <2nd biquad>
* ...
* <2nd EQ>
*
* Note: A flat response biquad can be made with a section set to
* b0 = 1.0, gain = 1.0, and other parameters set to 0
* {0, 0, 0, 0, 1073741824, 0, 16484}
*/
struct sof_eq_iir_config {
uint32_t size;
uint32_t channels_in_config;
uint32_t number_of_responses;
/* reserved */
uint32_t reserved[4];
int32_t data[]; /* eq_assign[channels], eq 0, eq 1, ... */
} __packed;
struct sof_eq_iir_header_df2t {
uint32_t num_sections;
uint32_t num_sections_in_series;
/* reserved */
uint32_t reserved[4];
int32_t biquads[]; /* Repeated biquad coefficients */
} __packed;
struct sof_eq_iir_biquad_df2t {
int32_t a2; /* Q2.30 */
int32_t a1; /* Q2.30 */
int32_t b2; /* Q2.30 */
int32_t b1; /* Q2.30 */
int32_t b0; /* Q2.30 */
int32_t output_shift; /* Number of right shifts */
int32_t output_gain; /* Q2.14 */
} __packed;
/* A full 22th order equalizer with 11 biquads cover octave bands 1-11 in
* in the 0 - 20 kHz bandwidth.
*/
#define SOF_EQ_IIR_DF2T_BIQUADS_MAX 11
/* The number of int32_t words in sof_eq_iir_header_df2t:
* num_sections, num_sections_in_series, reserved[4]
*/
#define SOF_EQ_IIR_NHEADER_DF2T \
(sizeof(struct sof_eq_iir_header_df2t) / sizeof(int32_t))
/* The number of int32_t words in sof_eq_iir_biquad_df2t:
* a2, a1, b2, b1, b0, output_shift, output_gain
*/
#define SOF_EQ_IIR_NBIQUAD_DF2T \
(sizeof(struct sof_eq_iir_biquad_df2t) / sizeof(int32_t))
#endif
/* SPDX-License-Identifier: ((GPL-2.0 WITH Linux-syscall-note) OR BSD-3-Clause) */
/*
* This file is provided under a dual BSD/GPLv2 license. When using or
* redistributing this file, you may do so under either license.
*
* Copyright(c) 2018 Intel Corporation. All rights reserved.
*/
/*
* Firmware file format .
*/
#ifndef __INCLUDE_UAPI_SOF_FW_H__
#define __INCLUDE_UAPI_SOF_FW_H__
#define SND_SOF_FW_SIG_SIZE 4
#define SND_SOF_FW_ABI 1
#define SND_SOF_FW_SIG "Reef"
/*
* Firmware module is made up of 1 . N blocks of different types. The
* Block header is used to determine where and how block is to be copied in the
* DSP/host memory space.
*/
enum snd_sof_fw_blk_type {
SOF_FW_BLK_TYPE_INVALID = -1,
SOF_FW_BLK_TYPE_START = 0,
SOF_FW_BLK_TYPE_RSRVD0 = SOF_FW_BLK_TYPE_START,
SOF_FW_BLK_TYPE_IRAM = 1, /* local instruction RAM */
SOF_FW_BLK_TYPE_DRAM = 2, /* local data RAM */
SOF_FW_BLK_TYPE_SRAM = 3, /* system RAM */
SOF_FW_BLK_TYPE_ROM = 4,
SOF_FW_BLK_TYPE_IMR = 5,
SOF_FW_BLK_TYPE_RSRVD6 = 6,
SOF_FW_BLK_TYPE_RSRVD7 = 7,
SOF_FW_BLK_TYPE_RSRVD8 = 8,
SOF_FW_BLK_TYPE_RSRVD9 = 9,
SOF_FW_BLK_TYPE_RSRVD10 = 10,
SOF_FW_BLK_TYPE_RSRVD11 = 11,
SOF_FW_BLK_TYPE_RSRVD12 = 12,
SOF_FW_BLK_TYPE_RSRVD13 = 13,
SOF_FW_BLK_TYPE_RSRVD14 = 14,
/* use SOF_FW_BLK_TYPE_RSVRDX for new block types */
SOF_FW_BLK_TYPE_NUM
};
struct snd_sof_blk_hdr {
enum snd_sof_fw_blk_type type;
uint32_t size; /* bytes minus this header */
uint32_t offset; /* offset from base */
} __packed;
/*
* Firmware file is made up of 1 .. N different modules types. The module
* type is used to determine how to load and parse the module.
*/
enum snd_sof_fw_mod_type {
SOF_FW_BASE = 0, /* base firmware image */
SOF_FW_MODULE = 1, /* firmware module */
};
struct snd_sof_mod_hdr {
enum snd_sof_fw_mod_type type;
uint32_t size; /* bytes minus this header */
uint32_t num_blocks; /* number of blocks */
} __packed;
/*
* Firmware file header.
*/
struct snd_sof_fw_header {
unsigned char sig[SND_SOF_FW_SIG_SIZE]; /* "Reef" */
uint32_t file_size; /* size of file minus this header */
uint32_t num_modules; /* number of modules */
uint32_t abi; /* version of header format */
} __packed;
#endif
/* SPDX-License-Identifier: ((GPL-2.0 WITH Linux-syscall-note) OR BSD-3-Clause) */
/*
* This file is provided under a dual BSD/GPLv2 license. When using or
* redistributing this file, you may do so under either license.
*
* Copyright(c) 2018 Intel Corporation. All rights reserved.
*/
#ifndef __INCLUDE_UAPI_SOUND_SOF_USER_HEADER_H__
#define __INCLUDE_UAPI_SOUND_SOF_USER_HEADER_H__
/*
* Header for all non IPC ABI data.
*
* Identifies data type, size and ABI.
* Used by any bespoke component data structures or binary blobs.
*/
struct sof_abi_hdr {
uint32_t magic; /**< 'S', 'O', 'F', '\0' */
uint32_t type; /**< component specific type */
uint32_t size; /**< size in bytes of data excl. this struct */
uint32_t abi; /**< SOF ABI version */
uint32_t reserved[4]; /**< reserved for future use */
uint32_t data[0]; /**< Component data - opaque to core */
} __packed;
#endif
/* SPDX-License-Identifier: ((GPL-2.0 WITH Linux-syscall-note) OR BSD-3-Clause) */
/*
* This file is provided under a dual BSD/GPLv2 license. When using or
* redistributing this file, you may do so under either license.
*
* Copyright(c) 2018 Intel Corporation. All rights reserved.
*/
#ifndef __INCLUDE_UAPI_SOUND_SOF_USER_MANIFEST_H__
#define __INCLUDE_UAPI_SOUND_SOF_USER_MANIFEST_H__
/* start offset for base FW module */
#define SOF_MAN_ELF_TEXT_OFFSET 0x2000
/* FW Extended Manifest Header id = $AE1 */
#define SOF_MAN_EXT_HEADER_MAGIC 0x31454124
/* module type load type */
#define SOF_MAN_MOD_TYPE_BUILTIN 0
#define SOF_MAN_MOD_TYPE_MODULE 1
struct sof_man_module_type {
uint32_t load_type:4; /* SOF_MAN_MOD_TYPE_ */
uint32_t auto_start:1;
uint32_t domain_ll:1;
uint32_t domain_dp:1;
uint32_t rsvd_:25;
};
/* segment flags.type */
#define SOF_MAN_SEGMENT_TEXT 0
#define SOF_MAN_SEGMENT_RODATA 1
#define SOF_MAN_SEGMENT_DATA 1
#define SOF_MAN_SEGMENT_BSS 2
#define SOF_MAN_SEGMENT_EMPTY 15
union sof_man_segment_flags {
uint32_t ul;
struct {
uint32_t contents:1;
uint32_t alloc:1;
uint32_t load:1;
uint32_t readonly:1;
uint32_t code:1;
uint32_t data:1;
uint32_t _rsvd0:2;
uint32_t type:4; /* MAN_SEGMENT_ */
uint32_t _rsvd1:4;
uint32_t length:16; /* of segment in pages */
} r;
} __packed;
/*
* Module segment descriptor. Used by ROM - Immutable.
*/
struct sof_man_segment_desc {
union sof_man_segment_flags flags;
uint32_t v_base_addr;
uint32_t file_offset;
} __packed;
/*
* The firmware binary can be split into several modules.
*/
#define SOF_MAN_MOD_ID_LEN 4
#define SOF_MAN_MOD_NAME_LEN 8
#define SOF_MAN_MOD_SHA256_LEN 32
#define SOF_MAN_MOD_ID {'$', 'A', 'M', 'E'}
/*
* Each module has an entry in the FW header. Used by ROM - Immutable.
*/
struct sof_man_module {
uint8_t struct_id[SOF_MAN_MOD_ID_LEN]; /* SOF_MAN_MOD_ID */
uint8_t name[SOF_MAN_MOD_NAME_LEN];
uint8_t uuid[16];
struct sof_man_module_type type;
uint8_t hash[SOF_MAN_MOD_SHA256_LEN];
uint32_t entry_point;
uint16_t cfg_offset;
uint16_t cfg_count;
uint32_t affinity_mask;
uint16_t instance_max_count; /* max number of instances */
uint16_t instance_bss_size; /* instance (pages) */
struct sof_man_segment_desc segment[3];
} __packed;
/*
* Each module has a configuration in the FW header. Used by ROM - Immutable.
*/
struct sof_man_mod_config {
uint32_t par[4]; /* module parameters */
uint32_t is_pages; /* actual size of instance .bss (pages) */
uint32_t cps; /* cycles per second */
uint32_t ibs; /* input buffer size (bytes) */
uint32_t obs; /* output buffer size (bytes) */
uint32_t module_flags; /* flags, reserved for future use */
uint32_t cpc; /* cycles per single run */
uint32_t obls; /* output block size, reserved for future use */
} __packed;
/*
* FW Manifest Header
*/
#define SOF_MAN_FW_HDR_FW_NAME_LEN 8
#define SOF_MAN_FW_HDR_ID {'$', 'A', 'M', '1'}
#define SOF_MAN_FW_HDR_NAME "ADSPFW"
#define SOF_MAN_FW_HDR_FLAGS 0x0
#define SOF_MAN_FW_HDR_FEATURES 0xff
/*
* The firmware has a standard header that is checked by the ROM on firmware
* loading. preload_page_count is used by DMA code loader and is entire
* image size on CNL. i.e. CNL: total size of the binary’s .text and .rodata
* Used by ROM - Immutable.
*/
struct sof_man_fw_header {
uint8_t header_id[4];
uint32_t header_len;
uint8_t name[SOF_MAN_FW_HDR_FW_NAME_LEN];
/* number of pages of preloaded image loaded by driver */
uint32_t preload_page_count;
uint32_t fw_image_flags;
uint32_t feature_mask;
uint16_t major_version;
uint16_t minor_version;
uint16_t hotfix_version;
uint16_t build_version;
uint32_t num_module_entries;
uint32_t hw_buf_base_addr;
uint32_t hw_buf_length;
/* target address for binary loading as offset in IMR - must be == base offset */
uint32_t load_offset;
} __packed;
/*
* Firmware manifest descriptor. This can contain N modules and N module
* configs. Used by ROM - Immutable.
*/
struct sof_man_fw_desc {
struct sof_man_fw_header header;
/* Warning - hack for module arrays. For some unknown reason the we
* have a variable size array of struct man_module followed by a
* variable size array of struct mod_config. These should have been
* merged into a variable array of a parent structure. We have to hack
* around this in many places....
*
* struct sof_man_module man_module[];
* struct sof_man_mod_config mod_config[];
*/
} __packed;
/*
* Component Descriptor. Used by ROM - Immutable.
*/
struct sof_man_component_desc {
uint32_t reserved[2]; /* all 0 */
uint32_t version;
uint8_t hash[SOF_MAN_MOD_SHA256_LEN];
uint32_t base_offset;
uint32_t limit_offset;
uint32_t attributes[4];
} __packed;
/*
* Audio DSP extended metadata. Used by ROM - Immutable.
*/
struct sof_man_adsp_meta_file_ext {
uint32_t ext_type; /* always 17 for ADSP extension */
uint32_t ext_len;
uint32_t imr_type;
uint8_t reserved[16]; /* all 0 */
struct sof_man_component_desc comp_desc[1];
} __packed;
/*
* Module Manifest for rimage module metadata. Not used by ROM.
*/
struct sof_man_module_manifest {
struct sof_man_module module;
uint32_t text_size;
} __packed;
#endif
/* SPDX-License-Identifier: ((GPL-2.0 WITH Linux-syscall-note) OR BSD-3-Clause) */
/*
* This file is provided under a dual BSD/GPLv2 license. When using or
* redistributing this file, you may do so under either license.
*
* Copyright(c) 2018 Intel Corporation. All rights reserved.
* Author: Liam Girdwood <liam.r.girdwood@linux.intel.com>
* Keyon Jie <yang.jie@linux.intel.com>
*/
/*
* Topology IDs and tokens.
*
* ** MUST BE ALIGNED WITH TOPOLOGY CONFIGURATION TOKEN VALUES **
*/
#ifndef __INCLUDE_UAPI_SOF_TOPOLOGY_H__
#define __INCLUDE_UAPI_SOF_TOPOLOGY_H__
/*
* Kcontrol IDs
*/
#define SOF_TPLG_KCTL_VOL_ID 256
#define SOF_TPLG_KCTL_ENUM_ID 257
#define SOF_TPLG_KCTL_BYTES_ID 258
#define SOF_TPLG_KCTL_SWITCH_ID 259
/*
* Tokens - must match values in topology configurations
*/
/* buffers */
#define SOF_TKN_BUF_SIZE 100
#define SOF_TKN_BUF_CAPS 101
/* DAI */
/* Token retired with ABI 3.2, do not use for new capabilities
* #define SOF_TKN_DAI_DMAC_CONFIG 153
*/
#define SOF_TKN_DAI_TYPE 154
#define SOF_TKN_DAI_INDEX 155
#define SOF_TKN_DAI_DIRECTION 156
/* scheduling */
#define SOF_TKN_SCHED_PERIOD 200
#define SOF_TKN_SCHED_PRIORITY 201
#define SOF_TKN_SCHED_MIPS 202
#define SOF_TKN_SCHED_CORE 203
#define SOF_TKN_SCHED_FRAMES 204
#define SOF_TKN_SCHED_TIME_DOMAIN 205
/* volume */
#define SOF_TKN_VOLUME_RAMP_STEP_TYPE 250
#define SOF_TKN_VOLUME_RAMP_STEP_MS 251
/* SRC */
#define SOF_TKN_SRC_RATE_IN 300
#define SOF_TKN_SRC_RATE_OUT 301
/* PCM */
#define SOF_TKN_PCM_DMAC_CONFIG 353
/* Generic components */
#define SOF_TKN_COMP_PERIOD_SINK_COUNT 400
#define SOF_TKN_COMP_PERIOD_SOURCE_COUNT 401
#define SOF_TKN_COMP_FORMAT 402
/* Token retired with ABI 3.2, do not use for new capabilities
* #define SOF_TKN_COMP_PRELOAD_COUNT 403
*/
/* SSP */
#define SOF_TKN_INTEL_SSP_CLKS_CONTROL 500
#define SOF_TKN_INTEL_SSP_MCLK_ID 501
#define SOF_TKN_INTEL_SSP_SAMPLE_BITS 502
#define SOF_TKN_INTEL_SSP_FRAME_PULSE_WIDTH 503
#define SOF_TKN_INTEL_SSP_QUIRKS 504
#define SOF_TKN_INTEL_SSP_TDM_PADDING_PER_SLOT 505
/* DMIC */
#define SOF_TKN_INTEL_DMIC_DRIVER_VERSION 600
#define SOF_TKN_INTEL_DMIC_CLK_MIN 601
#define SOF_TKN_INTEL_DMIC_CLK_MAX 602
#define SOF_TKN_INTEL_DMIC_DUTY_MIN 603
#define SOF_TKN_INTEL_DMIC_DUTY_MAX 604
#define SOF_TKN_INTEL_DMIC_NUM_PDM_ACTIVE 605
#define SOF_TKN_INTEL_DMIC_SAMPLE_RATE 608
#define SOF_TKN_INTEL_DMIC_FIFO_WORD_LENGTH 609
/* DMIC PDM */
#define SOF_TKN_INTEL_DMIC_PDM_CTRL_ID 700
#define SOF_TKN_INTEL_DMIC_PDM_MIC_A_Enable 701
#define SOF_TKN_INTEL_DMIC_PDM_MIC_B_Enable 702
#define SOF_TKN_INTEL_DMIC_PDM_POLARITY_A 703
#define SOF_TKN_INTEL_DMIC_PDM_POLARITY_B 704
#define SOF_TKN_INTEL_DMIC_PDM_CLK_EDGE 705
#define SOF_TKN_INTEL_DMIC_PDM_SKEW 706
/* Tone */
#define SOF_TKN_TONE_SAMPLE_RATE 800
/* Processing Components */
#define SOF_TKN_PROCESS_TYPE 900
/* for backward compatibility */
#define SOF_TKN_EFFECT_TYPE SOF_TKN_PROCESS_TYPE
#endif
/* SPDX-License-Identifier: ((GPL-2.0 WITH Linux-syscall-note) OR BSD-3-Clause) */
/*
* This file is provided under a dual BSD/GPLv2 license. When using or
* redistributing this file, you may do so under either license.
*
* Copyright(c) 2018 Intel Corporation. All rights reserved.
*/
#ifndef __INCLUDE_UAPI_SOUND_SOF_USER_TONE_H__
#define __INCLUDE_UAPI_SOUND_SOF_USER_TONE_H__
#define SOF_TONE_IDX_FREQUENCY 0
#define SOF_TONE_IDX_AMPLITUDE 1
#define SOF_TONE_IDX_FREQ_MULT 2
#define SOF_TONE_IDX_AMPL_MULT 3
#define SOF_TONE_IDX_LENGTH 4
#define SOF_TONE_IDX_PERIOD 5
#define SOF_TONE_IDX_REPEATS 6
#define SOF_TONE_IDX_LIN_RAMP_STEP 7
#endif
/* SPDX-License-Identifier: ((GPL-2.0 WITH Linux-syscall-note) OR BSD-3-Clause) */
/*
* This file is provided under a dual BSD/GPLv2 license. When using or
* redistributing this file, you may do so under either license.
*
* Copyright(c) 2018 Intel Corporation. All rights reserved.
*/
#ifndef __INCLUDE_UAPI_SOUND_SOF_USER_TRACE_H__
#define __INCLUDE_UAPI_SOUND_SOF_USER_TRACE_H__
/*
* Host system time.
*
* This property is used by the driver to pass down information about
* current system time. It is expressed in us.
* FW translates timestamps (in log entries, probe pockets) to this time
* domain.
*
* (cavs: SystemTime).
*/
struct system_time {
uint32_t val_l; /* Lower dword of current host time value */
uint32_t val_u; /* Upper dword of current host time value */
} __packed;
#define LOG_ENABLE 1 /* Enable logging */
#define LOG_DISABLE 0 /* Disable logging */
#define LOG_LEVEL_CRITICAL 1 /* (FDK fatal) */
#define LOG_LEVEL_VERBOSE 2
/*
* Layout of a log fifo.
*/
struct log_buffer_layout {
uint32_t read_ptr; /*read pointer */
uint32_t write_ptr; /* write pointer */
uint32_t buffer[0]; /* buffer */
} __packed;
/*
* Log buffer status reported by FW.
*/
struct log_buffer_status {
uint32_t core_id; /* ID of core that logged to other half */
} __packed;
#define TRACE_ID_LENGTH 12
/*
* Log entry header.
*
* The header is followed by an array of arguments (uint32_t[]).
* Number of arguments is specified by the params_num field of log_entry
*/
struct log_entry_header {
uint32_t id_0 : TRACE_ID_LENGTH; /* e.g. Pipeline ID */
uint32_t id_1 : TRACE_ID_LENGTH; /* e.g. Component ID */
uint32_t core_id : 8; /* Reporting core's id */
uint64_t timestamp; /* Timestamp (in dsp ticks) */
uint32_t log_entry_address; /* Address of log entry in ELF */
} __packed;
#endif
......@@ -63,6 +63,7 @@ source "sound/soc/rockchip/Kconfig"
source "sound/soc/samsung/Kconfig"
source "sound/soc/sh/Kconfig"
source "sound/soc/sirf/Kconfig"
source "sound/soc/sof/Kconfig"
source "sound/soc/spear/Kconfig"
source "sound/soc/sprd/Kconfig"
source "sound/soc/sti/Kconfig"
......
......@@ -47,6 +47,7 @@ obj-$(CONFIG_SND_SOC) += rockchip/
obj-$(CONFIG_SND_SOC) += samsung/
obj-$(CONFIG_SND_SOC) += sh/
obj-$(CONFIG_SND_SOC) += sirf/
obj-$(CONFIG_SND_SOC) += sof/
obj-$(CONFIG_SND_SOC) += spear/
obj-$(CONFIG_SND_SOC) += sprd/
obj-$(CONFIG_SND_SOC) += sti/
......
......@@ -43,6 +43,9 @@ struct axi_i2s {
struct clk *clk;
struct clk *clk_ref;
bool has_capture;
bool has_playback;
struct snd_soc_dai_driver dai_driver;
struct snd_dmaengine_dai_dma_data capture_dma_data;
......@@ -136,8 +139,10 @@ static int axi_i2s_dai_probe(struct snd_soc_dai *dai)
{
struct axi_i2s *i2s = snd_soc_dai_get_drvdata(dai);
snd_soc_dai_init_dma_data(dai, &i2s->playback_dma_data,
&i2s->capture_dma_data);
snd_soc_dai_init_dma_data(
dai,
i2s->has_playback ? &i2s->playback_dma_data : NULL,
i2s->has_capture ? &i2s->capture_dma_data : NULL);
return 0;
}
......@@ -151,18 +156,6 @@ static const struct snd_soc_dai_ops axi_i2s_dai_ops = {
static struct snd_soc_dai_driver axi_i2s_dai = {
.probe = axi_i2s_dai_probe,
.playback = {
.channels_min = 2,
.channels_max = 2,
.rates = SNDRV_PCM_RATE_KNOT,
.formats = SNDRV_PCM_FMTBIT_S32_LE | SNDRV_PCM_FMTBIT_U32_LE,
},
.capture = {
.channels_min = 2,
.channels_max = 2,
.rates = SNDRV_PCM_RATE_KNOT,
.formats = SNDRV_PCM_FMTBIT_S32_LE | SNDRV_PCM_FMTBIT_U32_LE,
},
.ops = &axi_i2s_dai_ops,
.symmetric_rates = 1,
};
......@@ -178,6 +171,19 @@ static const struct regmap_config axi_i2s_regmap_config = {
.max_register = AXI_I2S_REG_STATUS,
};
static void axi_i2s_parse_of(struct axi_i2s *i2s, const struct device_node *np)
{
struct property *dma_names;
const char *dma_name;
of_property_for_each_string(np, "dma-names", dma_names, dma_name) {
if (strcmp(dma_name, "rx") == 0)
i2s->has_capture = true;
if (strcmp(dma_name, "tx") == 0)
i2s->has_playback = true;
}
}
static int axi_i2s_probe(struct platform_device *pdev)
{
struct resource *res;
......@@ -191,6 +197,8 @@ static int axi_i2s_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, i2s);
axi_i2s_parse_of(i2s, pdev->dev.of_node);
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
base = devm_ioremap_resource(&pdev->dev, res);
if (IS_ERR(base))
......@@ -213,13 +221,29 @@ static int axi_i2s_probe(struct platform_device *pdev)
if (ret)
return ret;
if (i2s->has_playback) {
axi_i2s_dai.playback.channels_min = 2;
axi_i2s_dai.playback.channels_max = 2;
axi_i2s_dai.playback.rates = SNDRV_PCM_RATE_KNOT;
axi_i2s_dai.playback.formats =
SNDRV_PCM_FMTBIT_S32_LE | SNDRV_PCM_FMTBIT_U32_LE;
i2s->playback_dma_data.addr = res->start + AXI_I2S_REG_TX_FIFO;
i2s->playback_dma_data.addr_width = 4;
i2s->playback_dma_data.maxburst = 1;
}
if (i2s->has_capture) {
axi_i2s_dai.capture.channels_min = 2;
axi_i2s_dai.capture.channels_max = 2;
axi_i2s_dai.capture.rates = SNDRV_PCM_RATE_KNOT;
axi_i2s_dai.capture.formats =
SNDRV_PCM_FMTBIT_S32_LE | SNDRV_PCM_FMTBIT_U32_LE;
i2s->capture_dma_data.addr = res->start + AXI_I2S_REG_RX_FIFO;
i2s->capture_dma_data.addr_width = 4;
i2s->capture_dma_data.maxburst = 1;
}
i2s->ratnum.num = clk_get_rate(i2s->clk_ref) / 2 / AXI_I2S_BITS_PER_FRAME;
i2s->ratnum.den_step = 1;
......@@ -240,6 +264,10 @@ static int axi_i2s_probe(struct platform_device *pdev)
if (ret)
goto err_clk_disable;
dev_info(&pdev->dev, "probed, capture %s, playback %s\n",
i2s->has_capture ? "enabled" : "disabled",
i2s->has_playback ? "enabled" : "disabled");
return 0;
err_clk_disable:
......
......@@ -46,8 +46,9 @@
#define DUAL_CHANNEL 2
static struct snd_soc_jack cz_jack;
static struct clk *da7219_dai_clk;
extern int bt_uart_enable;
static struct clk *da7219_dai_wclk;
static struct clk *da7219_dai_bclk;
extern bool bt_uart_enable;
static int cz_da7219_init(struct snd_soc_pcm_runtime *rtd)
{
......@@ -72,7 +73,8 @@ static int cz_da7219_init(struct snd_soc_pcm_runtime *rtd)
return ret;
}
da7219_dai_clk = clk_get(component->dev, "da7219-dai-clks");
da7219_dai_wclk = clk_get(component->dev, "da7219-dai-wclk");
da7219_dai_bclk = clk_get(component->dev, "da7219-dai-bclk");
ret = snd_soc_card_jack_new(card, "Headset Jack",
SND_JACK_HEADSET | SND_JACK_LINEOUT |
......@@ -94,12 +96,15 @@ static int cz_da7219_init(struct snd_soc_pcm_runtime *rtd)
return 0;
}
static int da7219_clk_enable(struct snd_pcm_substream *substream)
static int da7219_clk_enable(struct snd_pcm_substream *substream,
int wclk_rate, int bclk_rate)
{
int ret = 0;
struct snd_soc_pcm_runtime *rtd = substream->private_data;
ret = clk_prepare_enable(da7219_dai_clk);
clk_set_rate(da7219_dai_wclk, wclk_rate);
clk_set_rate(da7219_dai_bclk, bclk_rate);
ret = clk_prepare_enable(da7219_dai_bclk);
if (ret < 0) {
dev_err(rtd->dev, "can't enable master clock %d\n", ret);
return ret;
......@@ -110,7 +115,7 @@ static int da7219_clk_enable(struct snd_pcm_substream *substream)
static void da7219_clk_disable(void)
{
clk_disable_unprepare(da7219_dai_clk);
clk_disable_unprepare(da7219_dai_bclk);
}
static const unsigned int channels[] = {
......@@ -151,7 +156,7 @@ static int cz_da7219_play_startup(struct snd_pcm_substream *substream)
&constraints_rates);
machine->play_i2s_instance = I2S_SP_INSTANCE;
return da7219_clk_enable(substream);
return 0;
}
static int cz_da7219_cap_startup(struct snd_pcm_substream *substream)
......@@ -173,12 +178,7 @@ static int cz_da7219_cap_startup(struct snd_pcm_substream *substream)
machine->cap_i2s_instance = I2S_SP_INSTANCE;
machine->capture_channel = CAP_CHANNEL1;
return da7219_clk_enable(substream);
}
static void cz_da7219_shutdown(struct snd_pcm_substream *substream)
{
da7219_clk_disable();
return 0;
}
static int cz_max_startup(struct snd_pcm_substream *substream)
......@@ -199,12 +199,7 @@ static int cz_max_startup(struct snd_pcm_substream *substream)
&constraints_rates);
machine->play_i2s_instance = I2S_BT_INSTANCE;
return da7219_clk_enable(substream);
}
static void cz_max_shutdown(struct snd_pcm_substream *substream)
{
da7219_clk_disable();
return 0;
}
static int cz_dmic0_startup(struct snd_pcm_substream *substream)
......@@ -225,7 +220,7 @@ static int cz_dmic0_startup(struct snd_pcm_substream *substream)
&constraints_rates);
machine->cap_i2s_instance = I2S_BT_INSTANCE;
return da7219_clk_enable(substream);
return 0;
}
static int cz_dmic1_startup(struct snd_pcm_substream *substream)
......@@ -247,10 +242,28 @@ static int cz_dmic1_startup(struct snd_pcm_substream *substream)
machine->cap_i2s_instance = I2S_SP_INSTANCE;
machine->capture_channel = CAP_CHANNEL0;
return da7219_clk_enable(substream);
return 0;
}
static void cz_dmic_shutdown(struct snd_pcm_substream *substream)
static int cz_da7219_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params)
{
int wclk, bclk;
wclk = params_rate(params);
bclk = wclk * params_channels(params) *
snd_pcm_format_width(params_format(params));
/* ADAU7002 spec: "The ADAU7002 requires a BCLK rate
* that is minimum of 64x the LRCLK sample rate."
* DA7219 is the only clk source so for all codecs
* we have to limit bclk to 64X lrclk.
*/
if (bclk < (wclk * 64))
bclk = wclk * 64;
return da7219_clk_enable(substream, wclk, bclk);
}
static void cz_da7219_shutdown(struct snd_pcm_substream *substream)
{
da7219_clk_disable();
}
......@@ -258,26 +271,31 @@ static void cz_dmic_shutdown(struct snd_pcm_substream *substream)
static const struct snd_soc_ops cz_da7219_play_ops = {
.startup = cz_da7219_play_startup,
.shutdown = cz_da7219_shutdown,
.hw_params = cz_da7219_params,
};
static const struct snd_soc_ops cz_da7219_cap_ops = {
.startup = cz_da7219_cap_startup,
.shutdown = cz_da7219_shutdown,
.hw_params = cz_da7219_params,
};
static const struct snd_soc_ops cz_max_play_ops = {
.startup = cz_max_startup,
.shutdown = cz_max_shutdown,
.shutdown = cz_da7219_shutdown,
.hw_params = cz_da7219_params,
};
static const struct snd_soc_ops cz_dmic0_cap_ops = {
.startup = cz_dmic0_startup,
.shutdown = cz_dmic_shutdown,
.shutdown = cz_da7219_shutdown,
.hw_params = cz_da7219_params,
};
static const struct snd_soc_ops cz_dmic1_cap_ops = {
.startup = cz_dmic1_startup,
.shutdown = cz_dmic_shutdown,
.shutdown = cz_da7219_shutdown,
.hw_params = cz_da7219_params,
};
static struct snd_soc_dai_link cz_dai_7219_98357[] = {
......
......@@ -558,7 +558,7 @@ static int acp3x_dai_i2s_trigger(struct snd_pcm_substream *substream,
return ret;
}
struct snd_soc_dai_ops acp3x_dai_i2s_ops = {
static struct snd_soc_dai_ops acp3x_dai_i2s_ops = {
.hw_params = acp3x_dai_i2s_hwparams,
.trigger = acp3x_dai_i2s_trigger,
.set_fmt = acp3x_dai_i2s_set_fmt,
......
......@@ -109,4 +109,18 @@ config SND_SOC_MIKROE_PROTO
using I2C over SDA (MPU Data Input) and SCL (MPU Clock Input) pins.
Both playback and capture are supported.
config SND_MCHP_SOC_I2S_MCC
tristate "Microchip ASoC driver for boards using I2S MCC"
depends on OF && (ARCH_AT91 || COMPILE_TEST)
select SND_SOC_GENERIC_DMAENGINE_PCM
select REGMAP_MMIO
help
Say Y or M if you want to add support for I2S Multi-Channel ASoC
driver on the following Microchip platforms:
- sam9x60
The I2SMCC complies with the Inter-IC Sound (I2S) bus specification
and supports a Time Division Multiplexed (TDM) interface with
external multi-channel audio codecs.
endif
......@@ -4,11 +4,13 @@ snd-soc-atmel-pcm-pdc-objs := atmel-pcm-pdc.o
snd-soc-atmel-pcm-dma-objs := atmel-pcm-dma.o
snd-soc-atmel_ssc_dai-objs := atmel_ssc_dai.o
snd-soc-atmel-i2s-objs := atmel-i2s.o
snd-soc-mchp-i2s-mcc-objs := mchp-i2s-mcc.o
obj-$(CONFIG_SND_ATMEL_SOC_PDC) += snd-soc-atmel-pcm-pdc.o
obj-$(CONFIG_SND_ATMEL_SOC_DMA) += snd-soc-atmel-pcm-dma.o
obj-$(CONFIG_SND_ATMEL_SOC_SSC) += snd-soc-atmel_ssc_dai.o
obj-$(CONFIG_SND_ATMEL_SOC_I2S) += snd-soc-atmel-i2s.o
obj-$(CONFIG_SND_MCHP_SOC_I2S_MCC) += snd-soc-mchp-i2s-mcc.o
# AT91 Machine Support
snd-soc-sam9g20-wm8731-objs := sam9g20_wm8731.o
......
This diff is collapsed.
......@@ -117,7 +117,7 @@ static int tse850_put_mux2(struct snd_kcontrol *kctrl,
return snd_soc_dapm_put_enum_double(kctrl, ucontrol);
}
int tse850_get_mix(struct snd_kcontrol *kctrl,
static int tse850_get_mix(struct snd_kcontrol *kctrl,
struct snd_ctl_elem_value *ucontrol)
{
struct snd_soc_dapm_context *dapm = snd_soc_dapm_kcontrol_dapm(kctrl);
......@@ -129,7 +129,7 @@ int tse850_get_mix(struct snd_kcontrol *kctrl,
return 0;
}
int tse850_put_mix(struct snd_kcontrol *kctrl,
static int tse850_put_mix(struct snd_kcontrol *kctrl,
struct snd_ctl_elem_value *ucontrol)
{
struct snd_soc_dapm_context *dapm = snd_soc_dapm_kcontrol_dapm(kctrl);
......@@ -151,7 +151,7 @@ int tse850_put_mix(struct snd_kcontrol *kctrl,
return 1;
}
int tse850_get_ana(struct snd_kcontrol *kctrl,
static int tse850_get_ana(struct snd_kcontrol *kctrl,
struct snd_ctl_elem_value *ucontrol)
{
struct snd_soc_dapm_context *dapm = snd_soc_dapm_kcontrol_dapm(kctrl);
......@@ -184,7 +184,7 @@ int tse850_get_ana(struct snd_kcontrol *kctrl,
return 0;
}
int tse850_put_ana(struct snd_kcontrol *kctrl,
static int tse850_put_ana(struct snd_kcontrol *kctrl,
struct snd_ctl_elem_value *ucontrol)
{
struct snd_soc_dapm_context *dapm = snd_soc_dapm_kcontrol_dapm(kctrl);
......
......@@ -94,6 +94,7 @@ config SND_SOC_ALL_CODECS
select SND_SOC_JZ4725B_CODEC
select SND_SOC_LM4857 if I2C
select SND_SOC_LM49453 if I2C
select SND_SOC_LOCHNAGAR_SC if MFD_LOCHNAGAR
select SND_SOC_MAX98088 if I2C
select SND_SOC_MAX98090 if I2C
select SND_SOC_MAX98095 if I2C
......@@ -179,8 +180,8 @@ config SND_SOC_ALL_CODECS
select SND_SOC_TLV320AIC23_SPI if SPI_MASTER
select SND_SOC_TLV320AIC26 if SPI_MASTER
select SND_SOC_TLV320AIC31XX if I2C
select SND_SOC_TLV320AIC32X4_I2C if I2C
select SND_SOC_TLV320AIC32X4_SPI if SPI_MASTER
select SND_SOC_TLV320AIC32X4_I2C if I2C && COMMON_CLK
select SND_SOC_TLV320AIC32X4_SPI if SPI_MASTER && COMMON_CLK
select SND_SOC_TLV320AIC3X if I2C
select SND_SOC_TPA6130A2 if I2C
select SND_SOC_TLV320DAC33 if I2C
......@@ -688,6 +689,13 @@ config SND_SOC_ISABELLE
config SND_SOC_LM49453
tristate
config SND_SOC_LOCHNAGAR_SC
tristate "Lochnagar Sound Card"
depends on MFD_LOCHNAGAR
help
This driver support the sound card functionality of the Cirrus
Logic Lochnagar audio development board.
config SND_SOC_MAX98088
tristate "Maxim MAX98088/9 Low-Power, Stereo Audio Codec"
depends on I2C
......@@ -1097,15 +1105,18 @@ config SND_SOC_TLV320AIC31XX
config SND_SOC_TLV320AIC32X4
tristate
depends on COMMON_CLK
config SND_SOC_TLV320AIC32X4_I2C
tristate "Texas Instruments TLV320AIC32x4 audio CODECs - I2C"
depends on I2C
depends on COMMON_CLK
select SND_SOC_TLV320AIC32X4
config SND_SOC_TLV320AIC32X4_SPI
tristate "Texas Instruments TLV320AIC32x4 audio CODECs - SPI"
depends on SPI_MASTER
depends on COMMON_CLK
select SND_SOC_TLV320AIC32X4
config SND_SOC_TLV320AIC3X
......
......@@ -91,6 +91,7 @@ snd-soc-jz4725b-codec-objs := jz4725b.o
snd-soc-l3-objs := l3.o
snd-soc-lm4857-objs := lm4857.o
snd-soc-lm49453-objs := lm49453.o
snd-soc-lochnagar-sc-objs := lochnagar-sc.o
snd-soc-max9759-objs := max9759.o
snd-soc-max9768-objs := max9768.o
snd-soc-max98088-objs := max98088.o
......@@ -192,7 +193,7 @@ snd-soc-tlv320aic23-i2c-objs := tlv320aic23-i2c.o
snd-soc-tlv320aic23-spi-objs := tlv320aic23-spi.o
snd-soc-tlv320aic26-objs := tlv320aic26.o
snd-soc-tlv320aic31xx-objs := tlv320aic31xx.o
snd-soc-tlv320aic32x4-objs := tlv320aic32x4.o
snd-soc-tlv320aic32x4-objs := tlv320aic32x4.o tlv320aic32x4-clk.o
snd-soc-tlv320aic32x4-i2c-objs := tlv320aic32x4-i2c.o
snd-soc-tlv320aic32x4-spi-objs := tlv320aic32x4-spi.o
snd-soc-tlv320aic3x-objs := tlv320aic3x.o
......@@ -364,6 +365,7 @@ obj-$(CONFIG_SND_SOC_JZ4725B_CODEC) += snd-soc-jz4725b-codec.o
obj-$(CONFIG_SND_SOC_L3) += snd-soc-l3.o
obj-$(CONFIG_SND_SOC_LM4857) += snd-soc-lm4857.o
obj-$(CONFIG_SND_SOC_LM49453) += snd-soc-lm49453.o
obj-$(CONFIG_SND_SOC_LOCHNAGAR_SC) += snd-soc-lochnagar-sc.o
obj-$(CONFIG_SND_SOC_MAX9759) += snd-soc-max9759.o
obj-$(CONFIG_SND_SOC_MAX9768) += snd-soc-max9768.o
obj-$(CONFIG_SND_SOC_MAX98088) += snd-soc-max98088.o
......
......@@ -29,18 +29,27 @@ static int cs42l51_i2c_probe(struct i2c_client *i2c,
struct regmap_config config;
config = cs42l51_regmap;
config.val_bits = 8;
config.reg_bits = 8;
return cs42l51_probe(&i2c->dev, devm_regmap_init_i2c(i2c, &config));
}
static int cs42l51_i2c_remove(struct i2c_client *i2c)
{
return cs42l51_remove(&i2c->dev);
}
static const struct dev_pm_ops cs42l51_pm_ops = {
SET_SYSTEM_SLEEP_PM_OPS(cs42l51_suspend, cs42l51_resume)
};
static struct i2c_driver cs42l51_i2c_driver = {
.driver = {
.name = "cs42l51",
.of_match_table = cs42l51_of_match,
.pm = &cs42l51_pm_ops,
},
.probe = cs42l51_i2c_probe,
.remove = cs42l51_i2c_remove,
.id_table = cs42l51_i2c_id,
};
......
......@@ -30,7 +30,9 @@
#include <sound/initval.h>
#include <sound/pcm_params.h>
#include <sound/pcm.h>
#include <linux/gpio/consumer.h>
#include <linux/regmap.h>
#include <linux/regulator/consumer.h>
#include "cs42l51.h"
......@@ -40,11 +42,21 @@ enum master_slave_mode {
MODE_MASTER,
};
static const char * const cs42l51_supply_names[] = {
"VL",
"VD",
"VA",
"VAHP",
};
struct cs42l51_private {
unsigned int mclk;
struct clk *mclk_handle;
unsigned int audio_mode; /* The mode (I2S or left-justified) */
enum master_slave_mode func;
struct regulator_bulk_data supplies[ARRAY_SIZE(cs42l51_supply_names)];
struct gpio_desc *reset_gpio;
struct regmap *regmap;
};
#define CS42L51_FORMATS ( \
......@@ -111,6 +123,7 @@ static const DECLARE_TLV_DB_SCALE(tone_tlv, -1050, 150, 0);
static const DECLARE_TLV_DB_SCALE(aout_tlv, -10200, 50, 0);
static const DECLARE_TLV_DB_SCALE(boost_tlv, 1600, 1600, 0);
static const DECLARE_TLV_DB_SCALE(adc_boost_tlv, 2000, 2000, 0);
static const char *chan_mix[] = {
"L R",
"L+R",
......@@ -139,6 +152,8 @@ static const struct snd_kcontrol_new cs42l51_snd_controls[] = {
SOC_SINGLE("Zero Cross Switch", CS42L51_DAC_CTL, 0, 0, 0),
SOC_DOUBLE_TLV("Mic Boost Volume",
CS42L51_MIC_CTL, 0, 1, 1, 0, boost_tlv),
SOC_DOUBLE_TLV("ADC Boost Volume",
CS42L51_MIC_CTL, 5, 6, 1, 0, adc_boost_tlv),
SOC_SINGLE_TLV("Bass Volume", CS42L51_TONE_CTL, 0, 0xf, 1, tone_tlv),
SOC_SINGLE_TLV("Treble Volume", CS42L51_TONE_CTL, 4, 0xf, 1, tone_tlv),
SOC_ENUM_EXT("PCM channel mixer",
......@@ -195,7 +210,8 @@ static const struct snd_kcontrol_new cs42l51_adcr_mux_controls =
SOC_DAPM_ENUM("Route", cs42l51_adcr_mux_enum);
static const struct snd_soc_dapm_widget cs42l51_dapm_widgets[] = {
SND_SOC_DAPM_MICBIAS("Mic Bias", CS42L51_MIC_POWER_CTL, 1, 1),
SND_SOC_DAPM_SUPPLY("Mic Bias", CS42L51_MIC_POWER_CTL, 1, 1, NULL,
SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
SND_SOC_DAPM_PGA_E("Left PGA", CS42L51_POWER_CTL1, 3, 1, NULL, 0,
cs42l51_pdn_event, SND_SOC_DAPM_PRE_POST_PMD),
SND_SOC_DAPM_PGA_E("Right PGA", CS42L51_POWER_CTL1, 4, 1, NULL, 0,
......@@ -329,6 +345,19 @@ static struct cs42l51_ratios slave_auto_ratios[] = {
{ 256, CS42L51_DSM_MODE, 1 }, { 384, CS42L51_DSM_MODE, 1 },
};
/*
* Master mode mclk/fs ratios.
* Recommended configurations are SSM for 4-50khz and DSM for 50-100kHz ranges
* The table below provides support of following ratios:
* 128: SSM (%128) with div2 disabled
* 256: SSM (%128) with div2 enabled
* In both cases, if sampling rate is above 50kHz, SSM is overridden
* with DSM (%128) configuration
*/
static struct cs42l51_ratios master_ratios[] = {
{ 128, CS42L51_SSM_MODE, 0 }, { 256, CS42L51_SSM_MODE, 1 },
};
static int cs42l51_set_dai_sysclk(struct snd_soc_dai *codec_dai,
int clk_id, unsigned int freq, int dir)
{
......@@ -351,11 +380,13 @@ static int cs42l51_hw_params(struct snd_pcm_substream *substream,
unsigned int ratio;
struct cs42l51_ratios *ratios = NULL;
int nr_ratios = 0;
int intf_ctl, power_ctl, fmt;
int intf_ctl, power_ctl, fmt, mode;
switch (cs42l51->func) {
case MODE_MASTER:
return -EINVAL;
ratios = master_ratios;
nr_ratios = ARRAY_SIZE(master_ratios);
break;
case MODE_SLAVE:
ratios = slave_ratios;
nr_ratios = ARRAY_SIZE(slave_ratios);
......@@ -391,7 +422,16 @@ static int cs42l51_hw_params(struct snd_pcm_substream *substream,
switch (cs42l51->func) {
case MODE_MASTER:
intf_ctl |= CS42L51_INTF_CTL_MASTER;
power_ctl |= CS42L51_MIC_POWER_CTL_SPEED(ratios[i].speed_mode);
mode = ratios[i].speed_mode;
/* Force DSM mode if sampling rate is above 50kHz */
if (rate > 50000)
mode = CS42L51_DSM_MODE;
power_ctl |= CS42L51_MIC_POWER_CTL_SPEED(mode);
/*
* Auto detect mode is not applicable for master mode and has to
* be disabled. Otherwise SPEED[1:0] bits will be ignored.
*/
power_ctl &= ~CS42L51_MIC_POWER_CTL_AUTO;
break;
case MODE_SLAVE:
power_ctl |= CS42L51_MIC_POWER_CTL_SPEED(ratios[i].speed_mode);
......@@ -464,6 +504,13 @@ static int cs42l51_dai_mute(struct snd_soc_dai *dai, int mute)
return snd_soc_component_write(component, CS42L51_DAC_OUT_CTL, reg);
}
static int cs42l51_of_xlate_dai_id(struct snd_soc_component *component,
struct device_node *endpoint)
{
/* return dai id 0, whatever the endpoint index */
return 0;
}
static const struct snd_soc_dai_ops cs42l51_dai_ops = {
.hw_params = cs42l51_hw_params,
.set_sysclk = cs42l51_set_dai_sysclk,
......@@ -526,13 +573,113 @@ static const struct snd_soc_component_driver soc_component_device_cs42l51 = {
.num_dapm_widgets = ARRAY_SIZE(cs42l51_dapm_widgets),
.dapm_routes = cs42l51_routes,
.num_dapm_routes = ARRAY_SIZE(cs42l51_routes),
.of_xlate_dai_id = cs42l51_of_xlate_dai_id,
.idle_bias_on = 1,
.use_pmdown_time = 1,
.endianness = 1,
.non_legacy_dai_naming = 1,
};
static bool cs42l51_writeable_reg(struct device *dev, unsigned int reg)
{
switch (reg) {
case CS42L51_POWER_CTL1:
case CS42L51_MIC_POWER_CTL:
case CS42L51_INTF_CTL:
case CS42L51_MIC_CTL:
case CS42L51_ADC_CTL:
case CS42L51_ADC_INPUT:
case CS42L51_DAC_OUT_CTL:
case CS42L51_DAC_CTL:
case CS42L51_ALC_PGA_CTL:
case CS42L51_ALC_PGB_CTL:
case CS42L51_ADCA_ATT:
case CS42L51_ADCB_ATT:
case CS42L51_ADCA_VOL:
case CS42L51_ADCB_VOL:
case CS42L51_PCMA_VOL:
case CS42L51_PCMB_VOL:
case CS42L51_BEEP_FREQ:
case CS42L51_BEEP_VOL:
case CS42L51_BEEP_CONF:
case CS42L51_TONE_CTL:
case CS42L51_AOUTA_VOL:
case CS42L51_AOUTB_VOL:
case CS42L51_PCM_MIXER:
case CS42L51_LIMIT_THRES_DIS:
case CS42L51_LIMIT_REL:
case CS42L51_LIMIT_ATT:
case CS42L51_ALC_EN:
case CS42L51_ALC_REL:
case CS42L51_ALC_THRES:
case CS42L51_NOISE_CONF:
case CS42L51_CHARGE_FREQ:
return true;
default:
return false;
}
}
static bool cs42l51_volatile_reg(struct device *dev, unsigned int reg)
{
switch (reg) {
case CS42L51_STATUS:
return true;
default:
return false;
}
}
static bool cs42l51_readable_reg(struct device *dev, unsigned int reg)
{
switch (reg) {
case CS42L51_CHIP_REV_ID:
case CS42L51_POWER_CTL1:
case CS42L51_MIC_POWER_CTL:
case CS42L51_INTF_CTL:
case CS42L51_MIC_CTL:
case CS42L51_ADC_CTL:
case CS42L51_ADC_INPUT:
case CS42L51_DAC_OUT_CTL:
case CS42L51_DAC_CTL:
case CS42L51_ALC_PGA_CTL:
case CS42L51_ALC_PGB_CTL:
case CS42L51_ADCA_ATT:
case CS42L51_ADCB_ATT:
case CS42L51_ADCA_VOL:
case CS42L51_ADCB_VOL:
case CS42L51_PCMA_VOL:
case CS42L51_PCMB_VOL:
case CS42L51_BEEP_FREQ:
case CS42L51_BEEP_VOL:
case CS42L51_BEEP_CONF:
case CS42L51_TONE_CTL:
case CS42L51_AOUTA_VOL:
case CS42L51_AOUTB_VOL:
case CS42L51_PCM_MIXER:
case CS42L51_LIMIT_THRES_DIS:
case CS42L51_LIMIT_REL:
case CS42L51_LIMIT_ATT:
case CS42L51_ALC_EN:
case CS42L51_ALC_REL:
case CS42L51_ALC_THRES:
case CS42L51_NOISE_CONF:
case CS42L51_STATUS:
case CS42L51_CHARGE_FREQ:
return true;
default:
return false;
}
}
const struct regmap_config cs42l51_regmap = {
.reg_bits = 8,
.reg_stride = 1,
.val_bits = 8,
.use_single_write = true,
.readable_reg = cs42l51_readable_reg,
.volatile_reg = cs42l51_volatile_reg,
.writeable_reg = cs42l51_writeable_reg,
.max_register = CS42L51_CHARGE_FREQ,
.cache_type = REGCACHE_RBTREE,
};
......@@ -542,7 +689,7 @@ int cs42l51_probe(struct device *dev, struct regmap *regmap)
{
struct cs42l51_private *cs42l51;
unsigned int val;
int ret;
int ret, i;
if (IS_ERR(regmap))
return PTR_ERR(regmap);
......@@ -553,6 +700,7 @@ int cs42l51_probe(struct device *dev, struct regmap *regmap)
return -ENOMEM;
dev_set_drvdata(dev, cs42l51);
cs42l51->regmap = regmap;
cs42l51->mclk_handle = devm_clk_get(dev, "MCLK");
if (IS_ERR(cs42l51->mclk_handle)) {
......@@ -561,6 +709,34 @@ int cs42l51_probe(struct device *dev, struct regmap *regmap)
cs42l51->mclk_handle = NULL;
}
for (i = 0; i < ARRAY_SIZE(cs42l51->supplies); i++)
cs42l51->supplies[i].supply = cs42l51_supply_names[i];
ret = devm_regulator_bulk_get(dev, ARRAY_SIZE(cs42l51->supplies),
cs42l51->supplies);
if (ret != 0) {
dev_err(dev, "Failed to request supplies: %d\n", ret);
return ret;
}
ret = regulator_bulk_enable(ARRAY_SIZE(cs42l51->supplies),
cs42l51->supplies);
if (ret != 0) {
dev_err(dev, "Failed to enable supplies: %d\n", ret);
return ret;
}
cs42l51->reset_gpio = devm_gpiod_get_optional(dev, "reset",
GPIOD_OUT_LOW);
if (IS_ERR(cs42l51->reset_gpio))
return PTR_ERR(cs42l51->reset_gpio);
if (cs42l51->reset_gpio) {
dev_dbg(dev, "Release reset gpio\n");
gpiod_set_value_cansleep(cs42l51->reset_gpio, 0);
mdelay(2);
}
/* Verify that we have a CS42L51 */
ret = regmap_read(regmap, CS42L51_CHIP_REV_ID, &val);
if (ret < 0) {
......@@ -579,11 +755,50 @@ int cs42l51_probe(struct device *dev, struct regmap *regmap)
ret = devm_snd_soc_register_component(dev,
&soc_component_device_cs42l51, &cs42l51_dai, 1);
if (ret < 0)
goto error;
return 0;
error:
regulator_bulk_disable(ARRAY_SIZE(cs42l51->supplies),
cs42l51->supplies);
return ret;
}
EXPORT_SYMBOL_GPL(cs42l51_probe);
int cs42l51_remove(struct device *dev)
{
struct cs42l51_private *cs42l51 = dev_get_drvdata(dev);
gpiod_set_value_cansleep(cs42l51->reset_gpio, 1);
return regulator_bulk_disable(ARRAY_SIZE(cs42l51->supplies),
cs42l51->supplies);
}
EXPORT_SYMBOL_GPL(cs42l51_remove);
int __maybe_unused cs42l51_suspend(struct device *dev)
{
struct cs42l51_private *cs42l51 = dev_get_drvdata(dev);
regcache_cache_only(cs42l51->regmap, true);
regcache_mark_dirty(cs42l51->regmap);
return 0;
}
EXPORT_SYMBOL_GPL(cs42l51_suspend);
int __maybe_unused cs42l51_resume(struct device *dev)
{
struct cs42l51_private *cs42l51 = dev_get_drvdata(dev);
regcache_cache_only(cs42l51->regmap, false);
return regcache_sync(cs42l51->regmap);
}
EXPORT_SYMBOL_GPL(cs42l51_resume);
const struct of_device_id cs42l51_of_match[] = {
{ .compatible = "cirrus,cs42l51", },
{ }
......
......@@ -22,6 +22,9 @@ struct device;
extern const struct regmap_config cs42l51_regmap;
int cs42l51_probe(struct device *dev, struct regmap *regmap);
int cs42l51_remove(struct device *dev);
int __maybe_unused cs42l51_suspend(struct device *dev);
int __maybe_unused cs42l51_resume(struct device *dev);
extern const struct of_device_id cs42l51_of_match[];
#define CS42L51_CHIP_ID 0x1B
......
......@@ -2322,6 +2322,8 @@ static int cs43130_probe(struct snd_soc_component *component)
return ret;
cs43130->wq = create_singlethread_workqueue("cs43130_hp");
if (!cs43130->wq)
return -ENOMEM;
INIT_WORK(&cs43130->work, cs43130_imp_meas);
}
......
......@@ -75,7 +75,9 @@ static int cs47l24_adsp_power_ev(struct snd_soc_dapm_widget *w,
v = (v & ARIZONA_SYSCLK_FREQ_MASK) >> ARIZONA_SYSCLK_FREQ_SHIFT;
return wm_adsp2_early_event(w, kcontrol, event, v);
wm_adsp2_set_dspclk(w, v);
return wm_adsp_early_event(w, kcontrol, event);
}
static DECLARE_TLV_DB_SCALE(eq_tlv, -1200, 100, 0);
......
This diff is collapsed.
......@@ -820,10 +820,10 @@ struct da7219_priv {
struct mutex pll_lock;
#ifdef CONFIG_COMMON_CLK
struct clk_hw dai_clks_hw;
struct clk_hw dai_clks_hw[DA7219_DAI_NUM_CLKS];
#endif
struct clk_lookup *dai_clks_lookup;
struct clk *dai_clks;
struct clk_lookup *dai_clks_lookup[DA7219_DAI_NUM_CLKS];
struct clk *dai_clks[DA7219_DAI_NUM_CLKS];
struct clk *mclk;
unsigned int mclk_rate;
......
......@@ -43,6 +43,7 @@ struct es8316_priv {
unsigned int sysclk;
unsigned int allowed_rates[NR_SUPPORTED_MCLK_LRCK_RATIOS];
struct snd_pcm_hw_constraint_list sysclk_constraints;
bool jd_inverted;
};
/*
......@@ -577,6 +578,9 @@ static irqreturn_t es8316_irq(int irq, void *data)
if (!es8316->jack)
goto out;
if (es8316->jd_inverted)
flags ^= ES8316_GPIO_FLAG_HP_NOT_INSERTED;
dev_dbg(comp->dev, "gpio flags %#04x\n", flags);
if (flags & ES8316_GPIO_FLAG_HP_NOT_INSERTED) {
/* Jack removed, or spurious IRQ? */
......@@ -592,6 +596,8 @@ static irqreturn_t es8316_irq(int irq, void *data)
/* Jack inserted, determine type */
es8316_enable_micbias_for_mic_gnd_short_detect(comp);
regmap_read(es8316->regmap, ES8316_GPIO_FLAG, &flags);
if (es8316->jd_inverted)
flags ^= ES8316_GPIO_FLAG_HP_NOT_INSERTED;
dev_dbg(comp->dev, "gpio flags %#04x\n", flags);
if (flags & ES8316_GPIO_FLAG_HP_NOT_INSERTED) {
/* Jack unplugged underneath us */
......@@ -633,6 +639,14 @@ static void es8316_enable_jack_detect(struct snd_soc_component *component,
{
struct es8316_priv *es8316 = snd_soc_component_get_drvdata(component);
/*
* Init es8316->jd_inverted here and not in the probe, as we cannot
* guarantee that the bytchr-es8316 driver, which might set this
* property, will probe before us.
*/
es8316->jd_inverted = device_property_read_bool(component->dev,
"everest,jack-detect-inverted");
mutex_lock(&es8316->lock);
es8316->jack = jack;
......
......@@ -496,10 +496,6 @@ static int hdmi_codec_hw_params(struct snd_pcm_substream *substream,
return ret;
}
ret = hdmi_codec_new_stream(substream, dai);
if (ret)
return ret;
hdmi_audio_infoframe_init(&hp.cea);
hp.cea.channels = params_channels(params);
hp.cea.coding_type = HDMI_AUDIO_CODING_TYPE_STREAM;
......@@ -761,7 +757,7 @@ static int hdmi_codec_probe(struct platform_device *pdev)
dev_dbg(dev, "%s()\n", __func__);
if (!hcd) {
dev_err(dev, "%s: No plalform data\n", __func__);
dev_err(dev, "%s: No platform data\n", __func__);
return -EINVAL;
}
......
// SPDX-License-Identifier: GPL-2.0
//
// Lochnagar sound card driver
//
// Copyright (c) 2017-2019 Cirrus Logic, Inc. and
// Cirrus Logic International Semiconductor Ltd.
//
// Author: Charles Keepax <ckeepax@opensource.cirrus.com>
// Piotr Stankiewicz <piotrs@opensource.cirrus.com>
#include <linux/clk.h>
#include <linux/module.h>
#include <sound/soc.h>
#include <linux/mfd/lochnagar.h>
#include <linux/mfd/lochnagar1_regs.h>
#include <linux/mfd/lochnagar2_regs.h>
struct lochnagar_sc_priv {
struct clk *mclk;
};
static const struct snd_soc_dapm_widget lochnagar_sc_widgets[] = {
SND_SOC_DAPM_LINE("Line Jack", NULL),
SND_SOC_DAPM_LINE("USB Audio", NULL),
};
static const struct snd_soc_dapm_route lochnagar_sc_routes[] = {
{ "Line Jack", NULL, "AIF1 Playback" },
{ "AIF1 Capture", NULL, "Line Jack" },
{ "USB Audio", NULL, "USB1 Playback" },
{ "USB Audio", NULL, "USB2 Playback" },
{ "USB1 Capture", NULL, "USB Audio" },
{ "USB2 Capture", NULL, "USB Audio" },
};
static const unsigned int lochnagar_sc_chan_vals[] = {
4, 8,
};
static const struct snd_pcm_hw_constraint_list lochnagar_sc_chan_constraint = {
.count = ARRAY_SIZE(lochnagar_sc_chan_vals),
.list = lochnagar_sc_chan_vals,
};
static const unsigned int lochnagar_sc_rate_vals[] = {
8000, 16000, 24000, 32000, 48000, 96000, 192000,
22050, 44100, 88200, 176400,
};
static const struct snd_pcm_hw_constraint_list lochnagar_sc_rate_constraint = {
.count = ARRAY_SIZE(lochnagar_sc_rate_vals),
.list = lochnagar_sc_rate_vals,
};
static int lochnagar_sc_hw_rule_rate(struct snd_pcm_hw_params *params,
struct snd_pcm_hw_rule *rule)
{
struct snd_interval range = {
.min = 8000,
.max = 24576000 / hw_param_interval(params, rule->deps[0])->max,
};
return snd_interval_refine(hw_param_interval(params, rule->var),
&range);
}
static int lochnagar_sc_startup(struct snd_pcm_substream *substream,
struct snd_soc_dai *dai)
{
struct snd_soc_component *comp = dai->component;
struct lochnagar_sc_priv *priv = snd_soc_component_get_drvdata(comp);
int ret;
ret = snd_pcm_hw_constraint_list(substream->runtime, 0,
SNDRV_PCM_HW_PARAM_RATE,
&lochnagar_sc_rate_constraint);
if (ret)
return ret;
return snd_pcm_hw_rule_add(substream->runtime, 0,
SNDRV_PCM_HW_PARAM_RATE,
lochnagar_sc_hw_rule_rate, priv,
SNDRV_PCM_HW_PARAM_FRAME_BITS, -1);
}
static int lochnagar_sc_line_startup(struct snd_pcm_substream *substream,
struct snd_soc_dai *dai)
{
struct snd_soc_component *comp = dai->component;
struct lochnagar_sc_priv *priv = snd_soc_component_get_drvdata(comp);
int ret;
ret = clk_prepare_enable(priv->mclk);
if (ret < 0) {
dev_err(dai->dev, "Failed to enable MCLK: %d\n", ret);
return ret;
}
ret = lochnagar_sc_startup(substream, dai);
if (ret)
return ret;
return snd_pcm_hw_constraint_list(substream->runtime, 0,
SNDRV_PCM_HW_PARAM_CHANNELS,
&lochnagar_sc_chan_constraint);
}
static void lochnagar_sc_line_shutdown(struct snd_pcm_substream *substream,
struct snd_soc_dai *dai)
{
struct snd_soc_component *comp = dai->component;
struct lochnagar_sc_priv *priv = snd_soc_component_get_drvdata(comp);
clk_disable_unprepare(priv->mclk);
}
static int lochnagar_sc_check_fmt(struct snd_soc_dai *dai, unsigned int fmt,
unsigned int tar)
{
tar |= SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF;
if ((fmt & ~SND_SOC_DAIFMT_CLOCK_MASK) != tar)
return -EINVAL;
return 0;
}
static int lochnagar_sc_set_line_fmt(struct snd_soc_dai *dai, unsigned int fmt)
{
return lochnagar_sc_check_fmt(dai, fmt, SND_SOC_DAIFMT_CBS_CFS);
}
static int lochnagar_sc_set_usb_fmt(struct snd_soc_dai *dai, unsigned int fmt)
{
return lochnagar_sc_check_fmt(dai, fmt, SND_SOC_DAIFMT_CBM_CFM);
}
static const struct snd_soc_dai_ops lochnagar_sc_line_ops = {
.startup = lochnagar_sc_line_startup,
.shutdown = lochnagar_sc_line_shutdown,
.set_fmt = lochnagar_sc_set_line_fmt,
};
static const struct snd_soc_dai_ops lochnagar_sc_usb_ops = {
.startup = lochnagar_sc_startup,
.set_fmt = lochnagar_sc_set_usb_fmt,
};
static struct snd_soc_dai_driver lochnagar_sc_dai[] = {
{
.name = "lochnagar-line",
.playback = {
.stream_name = "AIF1 Playback",
.channels_min = 4,
.channels_max = 8,
.rates = SNDRV_PCM_RATE_KNOT,
.formats = SNDRV_PCM_FMTBIT_S32_LE,
},
.capture = {
.stream_name = "AIF1 Capture",
.channels_min = 4,
.channels_max = 8,
.rates = SNDRV_PCM_RATE_KNOT,
.formats = SNDRV_PCM_FMTBIT_S32_LE,
},
.ops = &lochnagar_sc_line_ops,
.symmetric_rates = true,
.symmetric_samplebits = true,
},
{
.name = "lochnagar-usb1",
.playback = {
.stream_name = "USB1 Playback",
.channels_min = 1,
.channels_max = 8,
.rates = SNDRV_PCM_RATE_KNOT,
.formats = SNDRV_PCM_FMTBIT_S32_LE,
},
.capture = {
.stream_name = "USB1 Capture",
.channels_min = 1,
.channels_max = 8,
.rates = SNDRV_PCM_RATE_KNOT,
.formats = SNDRV_PCM_FMTBIT_S32_LE,
},
.ops = &lochnagar_sc_usb_ops,
.symmetric_rates = true,
.symmetric_samplebits = true,
},
{
.name = "lochnagar-usb2",
.playback = {
.stream_name = "USB2 Playback",
.channels_min = 1,
.channels_max = 8,
.rates = SNDRV_PCM_RATE_KNOT,
.formats = SNDRV_PCM_FMTBIT_S32_LE,
},
.capture = {
.stream_name = "USB2 Capture",
.channels_min = 1,
.channels_max = 8,
.rates = SNDRV_PCM_RATE_KNOT,
.formats = SNDRV_PCM_FMTBIT_S32_LE,
},
.ops = &lochnagar_sc_usb_ops,
.symmetric_rates = true,
.symmetric_samplebits = true,
},
};
static const struct snd_soc_component_driver lochnagar_sc_driver = {
.non_legacy_dai_naming = 1,
.dapm_widgets = lochnagar_sc_widgets,
.num_dapm_widgets = ARRAY_SIZE(lochnagar_sc_widgets),
.dapm_routes = lochnagar_sc_routes,
.num_dapm_routes = ARRAY_SIZE(lochnagar_sc_routes),
};
static int lochnagar_sc_probe(struct platform_device *pdev)
{
struct lochnagar_sc_priv *priv;
int ret;
priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
if (!priv)
return -ENOMEM;
priv->mclk = devm_clk_get(&pdev->dev, "mclk");
if (IS_ERR(priv->mclk)) {
ret = PTR_ERR(priv->mclk);
dev_err(&pdev->dev, "Failed to get MCLK: %d\n", ret);
return ret;
}
platform_set_drvdata(pdev, priv);
return devm_snd_soc_register_component(&pdev->dev,
&lochnagar_sc_driver,
lochnagar_sc_dai,
ARRAY_SIZE(lochnagar_sc_dai));
}
static const struct of_device_id lochnagar_of_match[] = {
{ .compatible = "cirrus,lochnagar2-soundcard" },
{}
};
MODULE_DEVICE_TABLE(of, lochnagar_of_match);
static struct platform_driver lochnagar_sc_codec_driver = {
.driver = {
.name = "lochnagar-soundcard",
.of_match_table = of_match_ptr(lochnagar_of_match),
},
.probe = lochnagar_sc_probe,
};
module_platform_driver(lochnagar_sc_codec_driver);
MODULE_DESCRIPTION("ASoC Lochnagar Sound Card Driver");
MODULE_AUTHOR("Piotr Stankiewicz <piotrs@opensource.cirrus.com>");
MODULE_LICENSE("GPL v2");
MODULE_ALIAS("platform:lochnagar-soundcard");
......@@ -97,7 +97,10 @@ static struct snd_soc_dai_driver max98357a_dai_driver = {
SNDRV_PCM_FMTBIT_S32,
.rates = SNDRV_PCM_RATE_8000 |
SNDRV_PCM_RATE_16000 |
SNDRV_PCM_RATE_32000 |
SNDRV_PCM_RATE_44100 |
SNDRV_PCM_RATE_48000 |
SNDRV_PCM_RATE_88200 |
SNDRV_PCM_RATE_96000,
.rate_min = 8000,
.rate_max = 96000,
......
This diff is collapsed.
......@@ -457,13 +457,16 @@ static int pcm3168a_hw_params(struct snd_pcm_substream *substream,
if (chan > 2) {
switch (fmt) {
case PCM3168A_FMT_I2S:
case PCM3168A_FMT_DSP_A:
fmt = PCM3168A_FMT_I2S_TDM;
break;
case PCM3168A_FMT_LEFT_J:
case PCM3168A_FMT_DSP_B:
fmt = PCM3168A_FMT_LEFT_J_TDM;
break;
default:
dev_err(component->dev, "TDM is supported under I2S/Left_J only\n");
dev_err(component->dev,
"TDM is supported under DSP/I2S/Left_J only\n");
return -EINVAL;
}
}
......@@ -526,6 +529,8 @@ static int pcm3168a_startup(struct snd_pcm_substream *substream,
break;
case PCM3168A_FMT_LEFT_J:
case PCM3168A_FMT_I2S:
case PCM3168A_FMT_DSP_A:
case PCM3168A_FMT_DSP_B:
sample_min = 24;
channel_max = channel_maxs[tx];
break;
......
This diff is collapsed.
This diff is collapsed.
......@@ -2083,6 +2083,7 @@ struct rt5651_priv {
int release_count;
int poll_count;
unsigned int jd_src;
bool jd_active_high;
unsigned int ovcd_th;
unsigned int ovcd_sf;
......
This diff is collapsed.
......@@ -89,7 +89,8 @@ static int simple_amp_probe(struct platform_device *pdev)
return -ENOMEM;
platform_set_drvdata(pdev, priv);
priv->gpiod_enable = devm_gpiod_get(dev, "enable", GPIOD_OUT_LOW);
priv->gpiod_enable = devm_gpiod_get_optional(dev, "enable",
GPIOD_OUT_LOW);
if (IS_ERR(priv->gpiod_enable)) {
err = PTR_ERR(priv->gpiod_enable);
if (err != -EPROBE_DEFER)
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment