Commit b9546d09 authored by Mark Brown's avatar Mark Brown

Merge remote-tracking branches 'asoc/topic/fsl-spdif', 'asoc/topic/img' and...

Merge remote-tracking branches 'asoc/topic/fsl-spdif', 'asoc/topic/img' and 'asoc/topic/intel' into asoc-next
......@@ -27,6 +27,11 @@ Required properties:
Transceiver Clock Diagram" of SoC reference manual.
It can also be referred to TxClk_Source bit of
register SPDIF_STC.
"spba" The spba clock is required when SPDIF is placed as a
bus slave of the Shared Peripheral Bus and when two
or more bus masters (CPU, DMA or DSP) try to access
it. This property is optional depending on the SoC
design.
- big-endian : If this property is absent, the native endian mode
will be in use as default, or the big endian mode
......
Imagination Technologies I2S Input Controller
Required Properties:
- compatible : Compatible list, must contain "img,i2s-in"
- #sound-dai-cells : Must be equal to 0
- reg : Offset and length of the register set for the device
- clocks : Contains an entry for each entry in clock-names
- clock-names : Must include the following entry:
"sys" The system clock
- dmas: Contains an entry for each entry in dma-names.
- dma-names: Must include the following entry:
"rx" Single DMA channel used by all active I2S channels
- img,i2s-channels : Number of I2S channels instantiated in the I2S in block
Optional Properties:
- interrupts : Contains the I2S in interrupts. Depending on
the configuration, there may be no interrupts, one interrupt,
or an interrupt per I2S channel. For the case where there is
one interrupt per channel, the interrupts should be listed
in ascending channel order
- resets: Contains a phandle to the I2S in reset signal
- reset-names: Contains the reset signal name "rst"
Example:
i2s_in: i2s-in@18100800 {
compatible = "img,i2s-in";
reg = <0x18100800 0x200>;
interrupts = <GIC_SHARED 7 IRQ_TYPE_LEVEL_HIGH>;
dmas = <&mdc 30 0xffffffff 0>;
dma-names = "rx";
clocks = <&cr_periph SYS_CLK_I2S_IN>;
clock-names = "sys";
img,i2s-channels = <6>;
#sound-dai-cells = <0>;
};
Imagination Technologies I2S Output Controller
Required Properties:
- compatible : Compatible list, must contain "img,i2s-out"
- #sound-dai-cells : Must be equal to 0
- reg : Offset and length of the register set for the device
- clocks : Contains an entry for each entry in clock-names
- clock-names : Must include the following entries:
"sys" The system clock
"ref" The reference clock
- dmas: Contains an entry for each entry in dma-names.
- dma-names: Must include the following entry:
"tx" Single DMA channel used by all active I2S channels
- img,i2s-channels : Number of I2S channels instantiated in the I2S out block
- resets: Contains a phandle to the I2S out reset signal
- reset-names: Contains the reset signal name "rst"
Optional Properties:
- interrupts : Contains the I2S out interrupts. Depending on
the configuration, there may be no interrupts, one interrupt,
or an interrupt per I2S channel. For the case where there is
one interrupt per channel, the interrupts should be listed
in ascending channel order
Example:
i2s_out: i2s-out@18100A00 {
compatible = "img,i2s-out";
reg = <0x18100A00 0x200>;
interrupts = <GIC_SHARED 13 IRQ_TYPE_LEVEL_HIGH>;
dmas = <&mdc 23 0xffffffff 0>;
dma-names = "tx";
clocks = <&cr_periph SYS_CLK_I2S_OUT>,
<&clk_core CLK_I2S>;
clock-names = "sys", "ref";
img,i2s-channels = <6>;
resets = <&pistachio_reset PISTACHIO_RESET_I2S_OUT>;
reset-names = "rst";
#sound-dai-cells = <0>;
};
Imagination Technologies Parallel Output Controller
Required Properties:
- compatible : Compatible list, must contain "img,parallel-out".
- #sound-dai-cells : Must be equal to 0
- reg : Offset and length of the register set for the device.
- dmas: Contains an entry for each entry in dma-names.
- dma-names: Must include the following entry:
"tx"
- clocks : Contains an entry for each entry in clock-names.
- clock-names : Includes the following entries:
"sys" The system clock
"ref" The reference clock
- resets: Contains a phandle to the parallel out reset signal
- reset-names: Contains the reset signal name "rst"
Optional Properties:
- interrupts : Contains the parallel out interrupt, if present
Example:
parallel_out: parallel-out@18100C00 {
compatible = "img,parallel-out";
reg = <0x18100C00 0x100>;
interrupts = <GIC_SHARED 19 IRQ_TYPE_LEVEL_HIGH>;
dmas = <&mdc 16 0xffffffff 0>;
dma-names = "tx";
clocks = <&cr_periph SYS_CLK_PAUD_OUT>,
<&clk_core CLK_AUDIO_DAC>;
clock-names = "sys", "ref";
resets = <&pistachio_reset PISTACHIO_RESET_PRL_OUT>;
reset-names = "rst";
#sound-dai-cells = <0>;
};
Pistachio internal DAC DT bindings
Required properties:
- compatible: "img,pistachio-internal-dac"
- img,cr-top : Must contain a phandle to the top level control syscon
node which contains the internal dac control registers
- VDD-supply : Digital power supply regulator (+1.8V or +3.3V)
Examples:
internal_dac: internal-dac {
compatible = "img,pistachio-internal-dac";
img,cr-top = <&cr_top>;
VDD-supply = <&supply3v3>;
};
Imagination Technologies SPDIF Input Controller
Required Properties:
- compatible : Compatible list, must contain "img,spdif-in"
- #sound-dai-cells : Must be equal to 0
- reg : Offset and length of the register set for the device
- dmas: Contains an entry for each entry in dma-names.
- dma-names: Must include the following entry:
"rx"
- clocks : Contains an entry for each entry in clock-names
- clock-names : Includes the following entries:
"sys" The system clock
Optional Properties:
- resets: Should contain a phandle to the spdif in reset signal, if any
- reset-names: Should contain the reset signal name "rst", if a
reset phandle is given
- interrupts : Contains the spdif in interrupt, if present
Example:
spdif_in: spdif-in@18100E00 {
compatible = "img,spdif-in";
reg = <0x18100E00 0x100>;
interrupts = <GIC_SHARED 20 IRQ_TYPE_LEVEL_HIGH>;
dmas = <&mdc 15 0xffffffff 0>;
dma-names = "rx";
clocks = <&cr_periph SYS_CLK_SPDIF_IN>;
clock-names = "sys";
#sound-dai-cells = <0>;
};
Imagination Technologies SPDIF Output Controller
Required Properties:
- compatible : Compatible list, must contain "img,spdif-out"
- #sound-dai-cells : Must be equal to 0
- reg : Offset and length of the register set for the device
- dmas: Contains an entry for each entry in dma-names.
- dma-names: Must include the following entry:
"tx"
- clocks : Contains an entry for each entry in clock-names.
- clock-names : Includes the following entries:
"sys" The system clock
"ref" The reference clock
- resets: Contains a phandle to the spdif out reset signal
- reset-names: Contains the reset signal name "rst"
Optional Properties:
- interrupts : Contains the parallel out interrupt, if present
Example:
spdif_out: spdif-out@18100D00 {
compatible = "img,spdif-out";
reg = <0x18100D00 0x100>;
interrupts = <GIC_SHARED 21 IRQ_TYPE_LEVEL_HIGH>;
dmas = <&mdc 14 0xffffffff 0>;
dma-names = "tx";
clocks = <&cr_periph SYS_CLK_SPDIF_OUT>,
<&clk_core CLK_SPDIF>;
clock-names = "sys", "ref";
resets = <&pistachio_reset PISTACHIO_RESET_SPDIF_OUT>;
reset-names = "rst";
#sound-dai-cells = <0>;
};
The Imagination Technologies SPDIF Input controller contains the following
controls:
name='IEC958 Capture Mask',index=0
This control returns a mask that shows which of the IEC958 status bits
can be read using the 'IEC958 Capture Default' control.
name='IEC958 Capture Default',index=0
This control returns the status bits contained within the SPDIF stream that
is being received. The 'IEC958 Capture Mask' shows which bits can be read
from this control.
name='SPDIF In Multi Frequency Acquire',index=0
name='SPDIF In Multi Frequency Acquire',index=1
name='SPDIF In Multi Frequency Acquire',index=2
name='SPDIF In Multi Frequency Acquire',index=3
This control is used to attempt acquisition of up to four different sample
rates. The active rate can be obtained by reading the 'SPDIF In Lock Frequency'
control.
When the value of this control is set to {0,0,0,0}, the rate given to hw_params
will determine the single rate the block will capture. Else, the rate given to
hw_params will be ignored, and the block will attempt capture for each of the
four sample rates set here.
If less than four rates are required, the same rate can be specified more than
once
name='SPDIF In Lock Frequency',index=0
This control returns the active capture rate, or 0 if a lock has not been
acquired
name='SPDIF In Lock TRK',index=0
This control is used to modify the locking/jitter rejection characteristics
of the block. Larger values increase the locking range, but reduce jitter
rejection.
name='SPDIF In Lock Acquire Threshold',index=0
This control is used to change the threshold at which a lock is acquired.
name='SPDIF In Lock Release Threshold',index=0
This control is used to change the threshold at which a lock is released.
......@@ -55,6 +55,7 @@ enum sst_audio_device_id_mrfld {
PIPE_MEDIA0_IN = 0x8F,
PIPE_MEDIA1_IN = 0x90,
PIPE_MEDIA2_IN = 0x91,
PIPE_MEDIA3_IN = 0x9C,
PIPE_RSVD = 0xFF,
};
......
......@@ -186,9 +186,15 @@ struct hdac_ext_device {
/* codec ops */
struct hdac_ext_codec_ops ops;
struct snd_card *card;
void *scodec;
void *private_data;
};
struct hdac_ext_dma_params {
u32 format;
u8 stream_tag;
};
#define to_ehdac_device(dev) (container_of((dev), \
struct hdac_ext_device, hdac))
/*
......
......@@ -50,6 +50,7 @@ source "sound/soc/jz4740/Kconfig"
source "sound/soc/nuc900/Kconfig"
source "sound/soc/omap/Kconfig"
source "sound/soc/kirkwood/Kconfig"
source "sound/soc/img/Kconfig"
source "sound/soc/intel/Kconfig"
source "sound/soc/mediatek/Kconfig"
source "sound/soc/mxs/Kconfig"
......
......@@ -27,6 +27,7 @@ obj-$(CONFIG_SND_SOC) += davinci/
obj-$(CONFIG_SND_SOC) += dwc/
obj-$(CONFIG_SND_SOC) += fsl/
obj-$(CONFIG_SND_SOC) += jz4740/
obj-$(CONFIG_SND_SOC) += img/
obj-$(CONFIG_SND_SOC) += intel/
obj-$(CONFIG_SND_SOC) += mediatek/
obj-$(CONFIG_SND_SOC) += mxs/
......
......@@ -68,6 +68,7 @@ config SND_SOC_ALL_CODECS
select SND_SOC_ES8328_SPI if SPI_MASTER
select SND_SOC_ES8328_I2C if I2C
select SND_SOC_GTM601
select SND_SOC_HDAC_HDMI
select SND_SOC_ICS43432
select SND_SOC_ISABELLE if I2C
select SND_SOC_JZ4740_CODEC
......@@ -483,6 +484,11 @@ config SND_SOC_ES8328_SPI
config SND_SOC_GTM601
tristate 'GTM601 UMTS modem audio codec'
config SND_SOC_HDAC_HDMI
tristate
select SND_HDA_EXT_CORE
select HDMI
config SND_SOC_ICS43432
tristate
......
......@@ -61,6 +61,7 @@ snd-soc-es8328-objs := es8328.o
snd-soc-es8328-i2c-objs := es8328-i2c.o
snd-soc-es8328-spi-objs := es8328-spi.o
snd-soc-gtm601-objs := gtm601.o
snd-soc-hdac-hdmi-objs := hdac_hdmi.o
snd-soc-ics43432-objs := ics43432.o
snd-soc-isabelle-objs := isabelle.o
snd-soc-jz4740-codec-objs := jz4740.o
......@@ -261,6 +262,7 @@ obj-$(CONFIG_SND_SOC_ES8328) += snd-soc-es8328.o
obj-$(CONFIG_SND_SOC_ES8328_I2C)+= snd-soc-es8328-i2c.o
obj-$(CONFIG_SND_SOC_ES8328_SPI)+= snd-soc-es8328-spi.o
obj-$(CONFIG_SND_SOC_GTM601) += snd-soc-gtm601.o
obj-$(CONFIG_SND_SOC_HDAC_HDMI) += snd-soc-hdac-hdmi.o
obj-$(CONFIG_SND_SOC_ICS43432) += snd-soc-ics43432.o
obj-$(CONFIG_SND_SOC_ISABELLE) += snd-soc-isabelle.o
obj-$(CONFIG_SND_SOC_JZ4740_CODEC) += snd-soc-jz4740-codec.o
......
This diff is collapsed.
......@@ -88,6 +88,7 @@ struct spdif_mixer_control {
* @rxclk: rx clock sources for capture
* @coreclk: core clock for register access via DMA
* @sysclk: system clock for rx clock rate measurement
* @spbaclk: SPBA clock (optional, depending on SoC design)
* @dma_params_tx: DMA parameters for transmit channel
* @dma_params_rx: DMA parameters for receive channel
*/
......@@ -106,6 +107,7 @@ struct fsl_spdif_priv {
struct clk *rxclk;
struct clk *coreclk;
struct clk *sysclk;
struct clk *spbaclk;
struct snd_dmaengine_dai_dma_data dma_params_tx;
struct snd_dmaengine_dai_dma_data dma_params_rx;
/* regcache for SRPC */
......@@ -474,6 +476,14 @@ static int fsl_spdif_startup(struct snd_pcm_substream *substream,
return ret;
}
if (!IS_ERR(spdif_priv->spbaclk)) {
ret = clk_prepare_enable(spdif_priv->spbaclk);
if (ret) {
dev_err(&pdev->dev, "failed to enable spba clock\n");
goto err_spbaclk;
}
}
ret = spdif_softreset(spdif_priv);
if (ret) {
dev_err(&pdev->dev, "failed to soft reset\n");
......@@ -515,6 +525,9 @@ static int fsl_spdif_startup(struct snd_pcm_substream *substream,
for (i--; i >= 0; i--)
clk_disable_unprepare(spdif_priv->txclk[i]);
err:
if (!IS_ERR(spdif_priv->spbaclk))
clk_disable_unprepare(spdif_priv->spbaclk);
err_spbaclk:
clk_disable_unprepare(spdif_priv->coreclk);
return ret;
......@@ -548,6 +561,8 @@ static void fsl_spdif_shutdown(struct snd_pcm_substream *substream,
spdif_intr_status_clear(spdif_priv);
regmap_update_bits(regmap, REG_SPDIF_SCR,
SCR_LOW_POWER, SCR_LOW_POWER);
if (!IS_ERR(spdif_priv->spbaclk))
clk_disable_unprepare(spdif_priv->spbaclk);
clk_disable_unprepare(spdif_priv->coreclk);
}
}
......@@ -1261,6 +1276,10 @@ static int fsl_spdif_probe(struct platform_device *pdev)
return PTR_ERR(spdif_priv->coreclk);
}
spdif_priv->spbaclk = devm_clk_get(&pdev->dev, "spba");
if (IS_ERR(spdif_priv->spbaclk))
dev_warn(&pdev->dev, "no spba clock in devicetree\n");
/* Select clock source for rx/tx clock */
spdif_priv->rxclk = devm_clk_get(&pdev->dev, "rxtx1");
if (IS_ERR(spdif_priv->rxclk)) {
......
config SND_SOC_IMG
bool "Audio support for Imagination Technologies designs"
help
Audio support for Imagination Technologies audio hardware
config SND_SOC_IMG_I2S_IN
tristate "Imagination I2S Input Device Driver"
depends on SND_SOC_IMG
select SND_SOC_GENERIC_DMAENGINE_PCM
help
Say Y or M if you want to add support for I2S in driver for
Imagination Technologies I2S in device.
config SND_SOC_IMG_I2S_OUT
tristate "Imagination I2S Output Device Driver"
depends on SND_SOC_IMG
select SND_SOC_GENERIC_DMAENGINE_PCM
help
Say Y or M if you want to add support for I2S out driver for
Imagination Technologies I2S out device.
config SND_SOC_IMG_PARALLEL_OUT
tristate "Imagination Parallel Output Device Driver"
depends on SND_SOC_IMG
select SND_SOC_GENERIC_DMAENGINE_PCM
help
Say Y or M if you want to add support for parallel out driver for
Imagination Technologies parallel out device.
config SND_SOC_IMG_SPDIF_IN
tristate "Imagination SPDIF Input Device Driver"
depends on SND_SOC_IMG
select SND_SOC_GENERIC_DMAENGINE_PCM
help
Say Y or M if you want to add support for SPDIF input driver for
Imagination Technologies SPDIF input device.
config SND_SOC_IMG_SPDIF_OUT
tristate "Imagination SPDIF Output Device Driver"
depends on SND_SOC_IMG
select SND_SOC_GENERIC_DMAENGINE_PCM
help
Say Y or M if you want to add support for SPDIF out driver for
Imagination Technologies SPDIF out device.
config SND_SOC_IMG_PISTACHIO_INTERNAL_DAC
tristate "Support for Pistachio SoC Internal DAC Driver"
depends on SND_SOC_IMG
help
Say Y or M if you want to add support for Pistachio internal DAC
driver for Imagination Technologies Pistachio internal DAC device.
obj-$(CONFIG_SND_SOC_IMG_I2S_IN) += img-i2s-in.o
obj-$(CONFIG_SND_SOC_IMG_I2S_OUT) += img-i2s-out.o
obj-$(CONFIG_SND_SOC_IMG_PARALLEL_OUT) += img-parallel-out.o
obj-$(CONFIG_SND_SOC_IMG_SPDIF_IN) += img-spdif-in.o
obj-$(CONFIG_SND_SOC_IMG_SPDIF_OUT) += img-spdif-out.o
obj-$(CONFIG_SND_SOC_IMG_PISTACHIO_INTERNAL_DAC) += pistachio-internal-dac.o
This diff is collapsed.
This diff is collapsed.
/*
* IMG parallel output controller driver
*
* Copyright (C) 2015 Imagination Technologies Ltd.
*
* Author: Damien Horsley <Damien.Horsley@imgtec.com>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*/
#include <linux/clk.h>
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/platform_device.h>
#include <linux/pm_runtime.h>
#include <linux/reset.h>
#include <sound/core.h>
#include <sound/dmaengine_pcm.h>
#include <sound/initval.h>
#include <sound/pcm.h>
#include <sound/pcm_params.h>
#include <sound/soc.h>
#define IMG_PRL_OUT_TX_FIFO 0
#define IMG_PRL_OUT_CTL 0x4
#define IMG_PRL_OUT_CTL_CH_MASK BIT(4)
#define IMG_PRL_OUT_CTL_PACKH_MASK BIT(3)
#define IMG_PRL_OUT_CTL_EDGE_MASK BIT(2)
#define IMG_PRL_OUT_CTL_ME_MASK BIT(1)
#define IMG_PRL_OUT_CTL_SRST_MASK BIT(0)
struct img_prl_out {
void __iomem *base;
struct clk *clk_sys;
struct clk *clk_ref;
struct snd_dmaengine_dai_dma_data dma_data;
struct device *dev;
struct reset_control *rst;
};
static int img_prl_out_suspend(struct device *dev)
{
struct img_prl_out *prl = dev_get_drvdata(dev);
clk_disable_unprepare(prl->clk_ref);
return 0;
}
static int img_prl_out_resume(struct device *dev)
{
struct img_prl_out *prl = dev_get_drvdata(dev);
int ret;
ret = clk_prepare_enable(prl->clk_ref);
if (ret) {
dev_err(dev, "clk_enable failed: %d\n", ret);
return ret;
}
return 0;
}
static inline void img_prl_out_writel(struct img_prl_out *prl,
u32 val, u32 reg)
{
writel(val, prl->base + reg);
}
static inline u32 img_prl_out_readl(struct img_prl_out *prl, u32 reg)
{
return readl(prl->base + reg);
}
static void img_prl_out_reset(struct img_prl_out *prl)
{
u32 ctl;
ctl = img_prl_out_readl(prl, IMG_PRL_OUT_CTL) &
~IMG_PRL_OUT_CTL_ME_MASK;
reset_control_assert(prl->rst);
reset_control_deassert(prl->rst);
img_prl_out_writel(prl, ctl, IMG_PRL_OUT_CTL);
}
static int img_prl_out_trigger(struct snd_pcm_substream *substream, int cmd,
struct snd_soc_dai *dai)
{
struct img_prl_out *prl = snd_soc_dai_get_drvdata(dai);
u32 reg;
switch (cmd) {
case SNDRV_PCM_TRIGGER_START:
case SNDRV_PCM_TRIGGER_RESUME:
case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
reg = img_prl_out_readl(prl, IMG_PRL_OUT_CTL);
reg |= IMG_PRL_OUT_CTL_ME_MASK;
img_prl_out_writel(prl, reg, IMG_PRL_OUT_CTL);
break;
case SNDRV_PCM_TRIGGER_STOP:
case SNDRV_PCM_TRIGGER_SUSPEND:
case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
img_prl_out_reset(prl);
break;
default:
return -EINVAL;
}
return 0;
}
static int img_prl_out_hw_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params, struct snd_soc_dai *dai)
{
struct img_prl_out *prl = snd_soc_dai_get_drvdata(dai);
unsigned int rate, channels;
u32 reg, control_set = 0;
snd_pcm_format_t format;
rate = params_rate(params);
format = params_format(params);
channels = params_channels(params);
switch (params_format(params)) {
case SNDRV_PCM_FORMAT_S32_LE:
control_set |= IMG_PRL_OUT_CTL_PACKH_MASK;
break;
case SNDRV_PCM_FORMAT_S24_LE:
break;
default:
return -EINVAL;
}
if (channels != 2)
return -EINVAL;
clk_set_rate(prl->clk_ref, rate * 256);
reg = img_prl_out_readl(prl, IMG_PRL_OUT_CTL);
reg = (reg & ~IMG_PRL_OUT_CTL_PACKH_MASK) | control_set;
img_prl_out_writel(prl, reg, IMG_PRL_OUT_CTL);
return 0;
}
static int img_prl_out_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
{
struct img_prl_out *prl = snd_soc_dai_get_drvdata(dai);
u32 reg, control_set = 0;
switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
case SND_SOC_DAIFMT_NB_NF:
break;
case SND_SOC_DAIFMT_NB_IF:
control_set |= IMG_PRL_OUT_CTL_EDGE_MASK;
break;
default:
return -EINVAL;
}
reg = img_prl_out_readl(prl, IMG_PRL_OUT_CTL);
reg = (reg & ~IMG_PRL_OUT_CTL_EDGE_MASK) | control_set;
img_prl_out_writel(prl, reg, IMG_PRL_OUT_CTL);
return 0;
}
static const struct snd_soc_dai_ops img_prl_out_dai_ops = {
.trigger = img_prl_out_trigger,
.hw_params = img_prl_out_hw_params,
.set_fmt = img_prl_out_set_fmt
};
static int img_prl_out_dai_probe(struct snd_soc_dai *dai)
{
struct img_prl_out *prl = snd_soc_dai_get_drvdata(dai);
snd_soc_dai_init_dma_data(dai, &prl->dma_data, NULL);
return 0;
}
static struct snd_soc_dai_driver img_prl_out_dai = {
.probe = img_prl_out_dai_probe,
.playback = {
.channels_min = 2,
.channels_max = 2,
.rates = SNDRV_PCM_RATE_8000_192000,
.formats = SNDRV_PCM_FMTBIT_S32_LE | SNDRV_PCM_FMTBIT_S24_LE
},
.ops = &img_prl_out_dai_ops
};
static const struct snd_soc_component_driver img_prl_out_component = {
.name = "img-prl-out"
};
static int img_prl_out_probe(struct platform_device *pdev)
{
struct img_prl_out *prl;
struct resource *res;
void __iomem *base;
int ret;
struct device *dev = &pdev->dev;
prl = devm_kzalloc(&pdev->dev, sizeof(*prl), GFP_KERNEL);
if (!prl)
return -ENOMEM;
platform_set_drvdata(pdev, prl);
prl->dev = &pdev->dev;
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
base = devm_ioremap_resource(&pdev->dev, res);
if (IS_ERR(base))
return PTR_ERR(base);
prl->base = base;
prl->rst = devm_reset_control_get(&pdev->dev, "rst");
if (IS_ERR(prl->rst)) {
if (PTR_ERR(prl->rst) != -EPROBE_DEFER)
dev_err(&pdev->dev, "No top level reset found\n");
return PTR_ERR(prl->rst);
}
prl->clk_sys = devm_clk_get(&pdev->dev, "sys");
if (IS_ERR(prl->clk_sys)) {
if (PTR_ERR(prl->clk_sys) != -EPROBE_DEFER)
dev_err(dev, "Failed to acquire clock 'sys'\n");
return PTR_ERR(prl->clk_sys);
}
prl->clk_ref = devm_clk_get(&pdev->dev, "ref");
if (IS_ERR(prl->clk_ref)) {
if (PTR_ERR(prl->clk_ref) != -EPROBE_DEFER)
dev_err(dev, "Failed to acquire clock 'ref'\n");
return PTR_ERR(prl->clk_ref);
}
ret = clk_prepare_enable(prl->clk_sys);
if (ret)
return ret;
img_prl_out_writel(prl, IMG_PRL_OUT_CTL_EDGE_MASK, IMG_PRL_OUT_CTL);
img_prl_out_reset(prl);
pm_runtime_enable(&pdev->dev);
if (!pm_runtime_enabled(&pdev->dev)) {
ret = img_prl_out_resume(&pdev->dev);
if (ret)
goto err_pm_disable;
}
prl->dma_data.addr = res->start + IMG_PRL_OUT_TX_FIFO;
prl->dma_data.addr_width = 4;
prl->dma_data.maxburst = 4;
ret = devm_snd_soc_register_component(&pdev->dev,
&img_prl_out_component,
&img_prl_out_dai, 1);
if (ret)
goto err_suspend;
ret = devm_snd_dmaengine_pcm_register(&pdev->dev, NULL, 0);
if (ret)
goto err_suspend;
return 0;
err_suspend:
if (!pm_runtime_status_suspended(&pdev->dev))
img_prl_out_suspend(&pdev->dev);
err_pm_disable:
pm_runtime_disable(&pdev->dev);
clk_disable_unprepare(prl->clk_sys);
return ret;
}
static int img_prl_out_dev_remove(struct platform_device *pdev)
{
struct img_prl_out *prl = platform_get_drvdata(pdev);
pm_runtime_disable(&pdev->dev);
if (!pm_runtime_status_suspended(&pdev->dev))
img_prl_out_suspend(&pdev->dev);
clk_disable_unprepare(prl->clk_sys);
return 0;
}
static const struct of_device_id img_prl_out_of_match[] = {
{ .compatible = "img,parallel-out" },
{}
};
MODULE_DEVICE_TABLE(of, img_prl_out_of_match);
static const struct dev_pm_ops img_prl_out_pm_ops = {
SET_RUNTIME_PM_OPS(img_prl_out_suspend,
img_prl_out_resume, NULL)
};
static struct platform_driver img_prl_out_driver = {
.driver = {
.name = "img-parallel-out",
.of_match_table = img_prl_out_of_match,
.pm = &img_prl_out_pm_ops
},
.probe = img_prl_out_probe,
.remove = img_prl_out_dev_remove
};
module_platform_driver(img_prl_out_driver);
MODULE_AUTHOR("Damien Horsley <Damien.Horsley@imgtec.com>");
MODULE_DESCRIPTION("IMG Parallel Output Driver");
MODULE_LICENSE("GPL v2");
This diff is collapsed.
This diff is collapsed.
/*
* Pistachio internal dac driver
*
* Copyright (C) 2015 Imagination Technologies Ltd.
*
* Author: Damien Horsley <Damien.Horsley@imgtec.com>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*/
#include <linux/clk.h>
#include <linux/delay.h>
#include <linux/mfd/syscon.h>
#include <linux/module.h>
#include <linux/pm_runtime.h>
#include <linux/regmap.h>
#include <linux/regulator/consumer.h>
#include <sound/pcm_params.h>
#include <sound/soc.h>
#define PISTACHIO_INTERNAL_DAC_CTRL 0x40
#define PISTACHIO_INTERNAL_DAC_CTRL_PWR_SEL_MASK 0x2
#define PISTACHIO_INTERNAL_DAC_CTRL_PWRDN_MASK 0x1
#define PISTACHIO_INTERNAL_DAC_SRST 0x44
#define PISTACHIO_INTERNAL_DAC_SRST_MASK 0x1
#define PISTACHIO_INTERNAL_DAC_GTI_CTRL 0x48
#define PISTACHIO_INTERNAL_DAC_GTI_CTRL_ADDR_SHIFT 0
#define PISTACHIO_INTERNAL_DAC_GTI_CTRL_ADDR_MASK 0xFFF
#define PISTACHIO_INTERNAL_DAC_GTI_CTRL_WE_MASK 0x1000
#define PISTACHIO_INTERNAL_DAC_GTI_CTRL_WDATA_SHIFT 13
#define PISTACHIO_INTERNAL_DAC_GTI_CTRL_WDATA_MASK 0x1FE000
#define PISTACHIO_INTERNAL_DAC_PWR 0x1
#define PISTACHIO_INTERNAL_DAC_PWR_MASK 0x1
#define PISTACHIO_INTERNAL_DAC_FORMATS (SNDRV_PCM_FMTBIT_S24_LE | \
SNDRV_PCM_FMTBIT_S32_LE)
/* codec private data */
struct pistachio_internal_dac {
struct regmap *regmap;
struct regulator *supply;
bool mute;
};
static const struct snd_kcontrol_new pistachio_internal_dac_snd_controls[] = {
SOC_SINGLE("Playback Switch", PISTACHIO_INTERNAL_DAC_CTRL, 2, 1, 1)
};
static const struct snd_soc_dapm_widget pistachio_internal_dac_widgets[] = {
SND_SOC_DAPM_DAC("DAC", "Playback", SND_SOC_NOPM, 0, 0),
SND_SOC_DAPM_OUTPUT("AOUTL"),
SND_SOC_DAPM_OUTPUT("AOUTR"),
};
static const struct snd_soc_dapm_route pistachio_internal_dac_routes[] = {
{ "AOUTL", NULL, "DAC" },
{ "AOUTR", NULL, "DAC" },
};
static void pistachio_internal_dac_reg_writel(struct regmap *top_regs,
u32 val, u32 reg)
{
regmap_update_bits(top_regs, PISTACHIO_INTERNAL_DAC_GTI_CTRL,
PISTACHIO_INTERNAL_DAC_GTI_CTRL_ADDR_MASK,
reg << PISTACHIO_INTERNAL_DAC_GTI_CTRL_ADDR_SHIFT);
regmap_update_bits(top_regs, PISTACHIO_INTERNAL_DAC_GTI_CTRL,
PISTACHIO_INTERNAL_DAC_GTI_CTRL_WDATA_MASK,
val << PISTACHIO_INTERNAL_DAC_GTI_CTRL_WDATA_SHIFT);
regmap_update_bits(top_regs, PISTACHIO_INTERNAL_DAC_GTI_CTRL,
PISTACHIO_INTERNAL_DAC_GTI_CTRL_WE_MASK,
PISTACHIO_INTERNAL_DAC_GTI_CTRL_WE_MASK);
regmap_update_bits(top_regs, PISTACHIO_INTERNAL_DAC_GTI_CTRL,
PISTACHIO_INTERNAL_DAC_GTI_CTRL_WE_MASK, 0);
}
static void pistachio_internal_dac_pwr_off(struct pistachio_internal_dac *dac)
{
regmap_update_bits(dac->regmap, PISTACHIO_INTERNAL_DAC_CTRL,
PISTACHIO_INTERNAL_DAC_CTRL_PWRDN_MASK,
PISTACHIO_INTERNAL_DAC_CTRL_PWRDN_MASK);
pistachio_internal_dac_reg_writel(dac->regmap, 0,
PISTACHIO_INTERNAL_DAC_PWR);
}
static void pistachio_internal_dac_pwr_on(struct pistachio_internal_dac *dac)
{
regmap_update_bits(dac->regmap, PISTACHIO_INTERNAL_DAC_SRST,
PISTACHIO_INTERNAL_DAC_SRST_MASK,
PISTACHIO_INTERNAL_DAC_SRST_MASK);
regmap_update_bits(dac->regmap, PISTACHIO_INTERNAL_DAC_SRST,
PISTACHIO_INTERNAL_DAC_SRST_MASK, 0);
pistachio_internal_dac_reg_writel(dac->regmap,
PISTACHIO_INTERNAL_DAC_PWR_MASK,
PISTACHIO_INTERNAL_DAC_PWR);
regmap_update_bits(dac->regmap, PISTACHIO_INTERNAL_DAC_CTRL,
PISTACHIO_INTERNAL_DAC_CTRL_PWRDN_MASK, 0);
}
static struct snd_soc_dai_driver pistachio_internal_dac_dais[] = {
{
.name = "pistachio_internal_dac",
.playback = {
.stream_name = "Playback",
.channels_min = 2,
.channels_max = 2,
.rates = SNDRV_PCM_RATE_8000_48000,
.formats = PISTACHIO_INTERNAL_DAC_FORMATS,
}
},
};
static int pistachio_internal_dac_codec_probe(struct snd_soc_codec *codec)
{
struct pistachio_internal_dac *dac = snd_soc_codec_get_drvdata(codec);
snd_soc_codec_init_regmap(codec, dac->regmap);
return 0;
}
static const struct snd_soc_codec_driver pistachio_internal_dac_driver = {
.probe = pistachio_internal_dac_codec_probe,
.idle_bias_off = true,
.controls = pistachio_internal_dac_snd_controls,
.num_controls = ARRAY_SIZE(pistachio_internal_dac_snd_controls),
.dapm_widgets = pistachio_internal_dac_widgets,
.num_dapm_widgets = ARRAY_SIZE(pistachio_internal_dac_widgets),
.dapm_routes = pistachio_internal_dac_routes,
.num_dapm_routes = ARRAY_SIZE(pistachio_internal_dac_routes),
};
static int pistachio_internal_dac_probe(struct platform_device *pdev)
{
struct pistachio_internal_dac *dac;
int ret, voltage;
struct device *dev = &pdev->dev;
u32 reg;
dac = devm_kzalloc(dev, sizeof(*dac), GFP_KERNEL);
if (!dac)
return -ENOMEM;
platform_set_drvdata(pdev, dac);
dac->regmap = syscon_regmap_lookup_by_phandle(pdev->dev.of_node,
"img,cr-top");
if (IS_ERR(dac->regmap))
return PTR_ERR(dac->regmap);
dac->supply = devm_regulator_get(dev, "VDD");
if (IS_ERR(dac->supply)) {
ret = PTR_ERR(dac->supply);
if (ret != -EPROBE_DEFER)
dev_err(dev, "failed to acquire supply 'VDD-supply': %d\n", ret);
return ret;
}
ret = regulator_enable(dac->supply);
if (ret) {
dev_err(dev, "failed to enable supply: %d\n", ret);
return ret;
}
voltage = regulator_get_voltage(dac->supply);
switch (voltage) {
case 1800000:
reg = 0;
break;
case 3300000:
reg = PISTACHIO_INTERNAL_DAC_CTRL_PWR_SEL_MASK;
break;
default:
dev_err(dev, "invalid voltage: %d\n", voltage);
ret = -EINVAL;
goto err_regulator;
}
regmap_update_bits(dac->regmap, PISTACHIO_INTERNAL_DAC_CTRL,
PISTACHIO_INTERNAL_DAC_CTRL_PWR_SEL_MASK, reg);
pistachio_internal_dac_pwr_off(dac);
pistachio_internal_dac_pwr_on(dac);
pm_runtime_set_active(dev);
pm_runtime_enable(dev);
pm_runtime_idle(dev);
ret = snd_soc_register_codec(dev, &pistachio_internal_dac_driver,
pistachio_internal_dac_dais,
ARRAY_SIZE(pistachio_internal_dac_dais));
if (ret) {
dev_err(dev, "failed to register codec: %d\n", ret);
goto err_pwr;
}
return 0;
err_pwr:
pm_runtime_disable(&pdev->dev);
pistachio_internal_dac_pwr_off(dac);
err_regulator:
regulator_disable(dac->supply);
return ret;
}
static int pistachio_internal_dac_remove(struct platform_device *pdev)
{
struct pistachio_internal_dac *dac = dev_get_drvdata(&pdev->dev);
snd_soc_unregister_codec(&pdev->dev);
pm_runtime_disable(&pdev->dev);
pistachio_internal_dac_pwr_off(dac);
regulator_disable(dac->supply);
return 0;
}
#ifdef CONFIG_PM
static int pistachio_internal_dac_rt_resume(struct device *dev)
{
struct pistachio_internal_dac *dac = dev_get_drvdata(dev);
int ret;
ret = regulator_enable(dac->supply);
if (ret) {
dev_err(dev, "failed to enable supply: %d\n", ret);
return ret;
}
pistachio_internal_dac_pwr_on(dac);
return 0;
}
static int pistachio_internal_dac_rt_suspend(struct device *dev)
{
struct pistachio_internal_dac *dac = dev_get_drvdata(dev);
pistachio_internal_dac_pwr_off(dac);
regulator_disable(dac->supply);
return 0;
}
#endif
static const struct dev_pm_ops pistachio_internal_dac_pm_ops = {
SET_RUNTIME_PM_OPS(pistachio_internal_dac_rt_suspend,
pistachio_internal_dac_rt_resume, NULL)
};
static const struct of_device_id pistachio_internal_dac_of_match[] = {
{ .compatible = "img,pistachio-internal-dac" },
{}
};
MODULE_DEVICE_TABLE(of, pistachio_internal_dac_of_match);
static struct platform_driver pistachio_internal_dac_plat_driver = {
.driver = {
.name = "img-pistachio-internal-dac",
.of_match_table = pistachio_internal_dac_of_match,
.pm = &pistachio_internal_dac_pm_ops
},
.probe = pistachio_internal_dac_probe,
.remove = pistachio_internal_dac_remove
};
module_platform_driver(pistachio_internal_dac_plat_driver);
MODULE_DESCRIPTION("Pistachio Internal DAC driver");
MODULE_AUTHOR("Damien Horsley <Damien.Horsley@imgtec.com>");
MODULE_LICENSE("GPL v2");
......@@ -24,6 +24,7 @@ config SND_SST_IPC_PCI
config SND_SST_IPC_ACPI
tristate
select SND_SST_IPC
select SND_SOC_INTEL_SST
depends on ACPI
config SND_SOC_INTEL_SST
......@@ -43,7 +44,7 @@ config SND_SOC_INTEL_BAYTRAIL
config SND_SOC_INTEL_HASWELL_MACH
tristate "ASoC Audio DSP support for Intel Haswell Lynxpoint"
depends on X86_INTEL_LPSS && I2C && I2C_DESIGNWARE_PLATFORM
depends on DW_DMAC_CORE
depends on DW_DMAC_CORE=y
select SND_SOC_INTEL_SST
select SND_SOC_INTEL_HASWELL
select SND_SOC_RT5640
......@@ -56,18 +57,19 @@ config SND_SOC_INTEL_HASWELL_MACH
config SND_SOC_INTEL_BYT_RT5640_MACH
tristate "ASoC Audio driver for Intel Baytrail with RT5640 codec"
depends on X86_INTEL_LPSS && I2C
depends on DW_DMAC_CORE
depends on DW_DMAC_CORE=y && (SND_SOC_INTEL_BYTCR_RT5640_MACH = n)
select SND_SOC_INTEL_SST
select SND_SOC_INTEL_BAYTRAIL
select SND_SOC_RT5640
help
This adds audio driver for Intel Baytrail platform based boards
with the RT5640 audio codec.
with the RT5640 audio codec. This driver is deprecated, use
SND_SOC_INTEL_BYTCR_RT5640_MACH instead for better functionality
config SND_SOC_INTEL_BYT_MAX98090_MACH
tristate "ASoC Audio driver for Intel Baytrail with MAX98090 codec"
depends on X86_INTEL_LPSS && I2C
depends on DW_DMAC_CORE
depends on DW_DMAC_CORE=y
select SND_SOC_INTEL_SST
select SND_SOC_INTEL_BAYTRAIL
select SND_SOC_MAX98090
......@@ -79,7 +81,7 @@ config SND_SOC_INTEL_BROADWELL_MACH
tristate "ASoC Audio DSP support for Intel Broadwell Wildcatpoint"
depends on X86_INTEL_LPSS && I2C && DW_DMAC && \
I2C_DESIGNWARE_PLATFORM
depends on DW_DMAC_CORE
depends on DW_DMAC_CORE=y
select SND_SOC_INTEL_SST
select SND_SOC_INTEL_HASWELL
select SND_SOC_RT286
......@@ -90,14 +92,14 @@ config SND_SOC_INTEL_BROADWELL_MACH
If unsure select "N".
config SND_SOC_INTEL_BYTCR_RT5640_MACH
tristate "ASoC Audio DSP Support for MID BYT Platform"
tristate "ASoC Audio driver for Intel Baytrail and Baytrail-CR with RT5640 codec"
depends on X86 && I2C
select SND_SOC_RT5640
select SND_SST_MFLD_PLATFORM
select SND_SST_IPC_ACPI
help
This adds support for ASoC machine driver for Intel(R) MID Baytrail platform
used as alsa device in audio substem in Intel(R) MID devices
This adds support for ASoC machine driver for Intel(R) Baytrail and Baytrail-CR
platforms with RT5640 audio codec.
Say Y if you have such a device
If unsure select "N".
......@@ -154,3 +156,31 @@ config SND_SOC_INTEL_SKL_RT286_MACH
with RT286 I2S audio codec.
Say Y if you have such a device
If unsure select "N".
config SND_SOC_INTEL_SKL_NAU88L25_SSM4567_MACH
tristate "ASoC Audio driver for SKL with NAU88L25 and SSM4567 in I2S Mode"
depends on X86_INTEL_LPSS && I2C
select SND_SOC_INTEL_SST
select SND_SOC_INTEL_SKYLAKE
select SND_SOC_NAU8825
select SND_SOC_SSM4567
select SND_SOC_DMIC
help
This adds support for ASoC Onboard Codec I2S machine driver. This will
create an alsa sound card for NAU88L25 + SSM4567.
Say Y if you have such a device
If unsure select "N".
config SND_SOC_INTEL_SKL_NAU88L25_MAX98357A_MACH
tristate "ASoC Audio driver for SKL with NAU88L25 and MAX98357A in I2S Mode"
depends on X86_INTEL_LPSS && I2C
select SND_SOC_INTEL_SST
select SND_SOC_INTEL_SKYLAKE
select SND_SOC_NAU8825
select SND_SOC_MAX98357A
select SND_SOC_DMIC
help
This adds support for ASoC Onboard Codec I2S machine driver. This will
create an alsa sound card for NAU88L25 + MAX98357A.
Say Y if you have such a device
If unsure select "N".
......@@ -443,7 +443,7 @@ static int sst_gain_get(struct snd_kcontrol *kcontrol,
break;
case SST_GAIN_MUTE:
ucontrol->value.integer.value[0] = gv->mute ? 1 : 0;
ucontrol->value.integer.value[0] = gv->mute ? 0 : 1;
break;
case SST_GAIN_RAMP_DURATION:
......@@ -479,7 +479,7 @@ static int sst_gain_put(struct snd_kcontrol *kcontrol,
break;
case SST_GAIN_MUTE:
gv->mute = !!ucontrol->value.integer.value[0];
gv->mute = !ucontrol->value.integer.value[0];
dev_dbg(cmpnt->dev, "%s: Mute %d\n", mc->pname, gv->mute);
break;
......@@ -1109,6 +1109,7 @@ static const struct snd_soc_dapm_route intercon[] = {
{"media0_in", NULL, "Compress Playback"},
{"media1_in", NULL, "Headset Playback"},
{"media2_in", NULL, "pcm0_out"},
{"media3_in", NULL, "Deepbuffer Playback"},
{"media0_out mix 0", "media0_in Switch", "media0_in"},
{"media0_out mix 0", "media1_in Switch", "media1_in"},
......
......@@ -28,6 +28,7 @@
enum {
MERR_DPCM_AUDIO = 0,
MERR_DPCM_DEEP_BUFFER,
MERR_DPCM_COMPR,
};
......
......@@ -98,6 +98,7 @@ static struct sst_dev_stream_map dpcm_strm_map[] = {
{MERR_DPCM_AUDIO, 0, SNDRV_PCM_STREAM_PLAYBACK, PIPE_MEDIA1_IN, SST_TASK_ID_MEDIA, 0},
{MERR_DPCM_COMPR, 0, SNDRV_PCM_STREAM_PLAYBACK, PIPE_MEDIA0_IN, SST_TASK_ID_MEDIA, 0},
{MERR_DPCM_AUDIO, 0, SNDRV_PCM_STREAM_CAPTURE, PIPE_PCM1_OUT, SST_TASK_ID_MEDIA, 0},
{MERR_DPCM_DEEP_BUFFER, 0, SNDRV_PCM_STREAM_PLAYBACK, PIPE_MEDIA3_IN, SST_TASK_ID_MEDIA, 0},
};
static int sst_media_digital_mute(struct snd_soc_dai *dai, int mute, int stream)
......@@ -500,14 +501,25 @@ static struct snd_soc_dai_driver sst_platform_dai[] = {
.channels_min = SST_STEREO,
.channels_max = SST_STEREO,
.rates = SNDRV_PCM_RATE_44100|SNDRV_PCM_RATE_48000,
.formats = SNDRV_PCM_FMTBIT_S16_LE,
.formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE,
},
.capture = {
.stream_name = "Headset Capture",
.channels_min = 1,
.channels_max = 2,
.rates = SNDRV_PCM_RATE_44100|SNDRV_PCM_RATE_48000,
.formats = SNDRV_PCM_FMTBIT_S16_LE,
.formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE,
},
},
{
.name = "deepbuffer-cpu-dai",
.ops = &sst_media_dai_ops,
.playback = {
.stream_name = "Deepbuffer Playback",
.channels_min = SST_STEREO,
.channels_max = SST_STEREO,
.rates = SNDRV_PCM_RATE_44100|SNDRV_PCM_RATE_48000,
.formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE,
},
},
{
......@@ -516,10 +528,6 @@ static struct snd_soc_dai_driver sst_platform_dai[] = {
.ops = &sst_compr_dai_ops,
.playback = {
.stream_name = "Compress Playback",
.channels_min = SST_STEREO,
.channels_max = SST_STEREO,
.rates = SNDRV_PCM_RATE_48000,
.formats = SNDRV_PCM_FMTBIT_S16_LE,
},
},
/* BE CPU Dais */
......
......@@ -40,18 +40,9 @@
#include <acpi/acpi_bus.h>
#include "../sst-mfld-platform.h"
#include "../../common/sst-dsp.h"
#include "../../common/sst-acpi.h"
#include "sst.h"
struct sst_machines {
char *codec_id;
char board[32];
char machine[32];
void (*machine_quirk)(void);
char firmware[FW_NAME_SIZE];
struct sst_platform_info *pdata;
};
/* LPE viewpoint addresses */
#define SST_BYT_IRAM_PHY_START 0xff2c0000
#define SST_BYT_IRAM_PHY_END 0xff2d4000
......@@ -223,37 +214,16 @@ static int sst_platform_get_resources(struct intel_sst_drv *ctx)
return 0;
}
static acpi_status sst_acpi_mach_match(acpi_handle handle, u32 level,
void *context, void **ret)
{
*(bool *)context = true;
return AE_OK;
}
static struct sst_machines *sst_acpi_find_machine(
struct sst_machines *machines)
{
struct sst_machines *mach;
bool found = false;
for (mach = machines; mach->codec_id; mach++)
if (ACPI_SUCCESS(acpi_get_devices(mach->codec_id,
sst_acpi_mach_match,
&found, NULL)) && found)
return mach;
return NULL;
}
static int sst_acpi_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
int ret = 0;
struct intel_sst_drv *ctx;
const struct acpi_device_id *id;
struct sst_machines *mach;
struct sst_acpi_mach *mach;
struct platform_device *mdev;
struct platform_device *plat_dev;
struct sst_platform_info *pdata;
unsigned int dev_id;
id = acpi_match_device(dev->driver->acpi_match_table, dev);
......@@ -261,12 +231,13 @@ static int sst_acpi_probe(struct platform_device *pdev)
return -ENODEV;
dev_dbg(dev, "for %s", id->id);
mach = (struct sst_machines *)id->driver_data;
mach = (struct sst_acpi_mach *)id->driver_data;
mach = sst_acpi_find_machine(mach);
if (mach == NULL) {
dev_err(dev, "No matching machine driver found\n");
return -ENODEV;
}
pdata = mach->pdata;
ret = kstrtouint(id->id, 16, &dev_id);
if (ret < 0) {
......@@ -276,16 +247,16 @@ static int sst_acpi_probe(struct platform_device *pdev)
dev_dbg(dev, "ACPI device id: %x\n", dev_id);
plat_dev = platform_device_register_data(dev, mach->pdata->platform, -1, NULL, 0);
plat_dev = platform_device_register_data(dev, pdata->platform, -1, NULL, 0);
if (IS_ERR(plat_dev)) {
dev_err(dev, "Failed to create machine device: %s\n", mach->pdata->platform);
dev_err(dev, "Failed to create machine device: %s\n", pdata->platform);
return PTR_ERR(plat_dev);
}
/* Create platform device for sst machine driver */
mdev = platform_device_register_data(dev, mach->machine, -1, NULL, 0);
mdev = platform_device_register_data(dev, mach->drv_name, -1, NULL, 0);
if (IS_ERR(mdev)) {
dev_err(dev, "Failed to create machine device: %s\n", mach->machine);
dev_err(dev, "Failed to create machine device: %s\n", mach->drv_name);
return PTR_ERR(mdev);
}
......@@ -294,8 +265,8 @@ static int sst_acpi_probe(struct platform_device *pdev)
return ret;
/* Fill sst platform data */
ctx->pdata = mach->pdata;
strcpy(ctx->firmware_name, mach->firmware);
ctx->pdata = pdata;
strcpy(ctx->firmware_name, mach->fw_filename);
ret = sst_platform_get_resources(ctx);
if (ret)
......@@ -342,22 +313,22 @@ static int sst_acpi_remove(struct platform_device *pdev)
return 0;
}
static struct sst_machines sst_acpi_bytcr[] = {
{"10EC5640", "T100", "bytt100_rt5640", NULL, "intel/fw_sst_0f28.bin",
static struct sst_acpi_mach sst_acpi_bytcr[] = {
{"10EC5640", "bytcr_rt5640", "intel/fw_sst_0f28.bin", "bytcr_rt5640", NULL,
&byt_rvp_platform_data },
{},
};
/* Cherryview-based platforms: CherryTrail and Braswell */
static struct sst_machines sst_acpi_chv[] = {
{"10EC5670", "cht-bsw", "cht-bsw-rt5672", NULL, "intel/fw_sst_22a8.bin",
static struct sst_acpi_mach sst_acpi_chv[] = {
{"10EC5670", "cht-bsw-rt5672", "intel/fw_sst_22a8.bin", "cht-bsw", NULL,
&chv_platform_data },
{"10EC5645", "cht-bsw-rt5645", "intel/fw_sst_22a8.bin", "cht-bsw", NULL,
&chv_platform_data },
{"10EC5645", "cht-bsw", "cht-bsw-rt5645", NULL, "intel/fw_sst_22a8.bin",
{"10EC5650", "cht-bsw-rt5645", "intel/fw_sst_22a8.bin", "cht-bsw", NULL,
&chv_platform_data },
{"10EC5650", "cht-bsw", "cht-bsw-rt5645", NULL, "intel/fw_sst_22a8.bin",
{"193C9890", "cht-bsw-max98090", "intel/fw_sst_22a8.bin", "cht-bsw", NULL,
&chv_platform_data },
{"193C9890", "cht-bsw", "cht-bsw-max98090", NULL,
"intel/fw_sst_22a8.bin", &chv_platform_data },
{},
};
......
......@@ -108,7 +108,7 @@ int sst_alloc_stream_mrfld(struct intel_sst_drv *sst_drv_ctx, void *params)
str_id, pipe_id);
ret = sst_prepare_and_post_msg(sst_drv_ctx, task_id, IPC_CMD,
IPC_IA_ALLOC_STREAM_MRFLD, pipe_id, sizeof(alloc_param),
&alloc_param, data, true, true, false, true);
&alloc_param, &data, true, true, false, true);
if (ret < 0) {
dev_err(sst_drv_ctx->dev, "FW alloc failed ret %d\n", ret);
......
......@@ -7,6 +7,8 @@ snd-soc-sst-cht-bsw-rt5672-objs := cht_bsw_rt5672.o
snd-soc-sst-cht-bsw-rt5645-objs := cht_bsw_rt5645.o
snd-soc-sst-cht-bsw-max98090_ti-objs := cht_bsw_max98090_ti.o
snd-soc-skl_rt286-objs := skl_rt286.o
snd-skl_nau88l25_max98357a-objs := skl_nau88l25_max98357a.o
snd-soc-skl_nau88l25_ssm4567-objs := skl_nau88l25_ssm4567.o
obj-$(CONFIG_SND_SOC_INTEL_HASWELL_MACH) += snd-soc-sst-haswell.o
obj-$(CONFIG_SND_SOC_INTEL_BYT_RT5640_MACH) += snd-soc-sst-byt-rt5640-mach.o
......@@ -17,3 +19,5 @@ obj-$(CONFIG_SND_SOC_INTEL_CHT_BSW_RT5672_MACH) += snd-soc-sst-cht-bsw-rt5672.o
obj-$(CONFIG_SND_SOC_INTEL_CHT_BSW_RT5645_MACH) += snd-soc-sst-cht-bsw-rt5645.o
obj-$(CONFIG_SND_SOC_INTEL_CHT_BSW_MAX98090_TI_MACH) += snd-soc-sst-cht-bsw-max98090_ti.o
obj-$(CONFIG_SND_SOC_INTEL_SKL_RT286_MACH) += snd-soc-skl_rt286.o
obj-$(CONFIG_SND_SOC_INTEL_SKL_NAU88L25_MAX98357A_MACH) += snd-skl_nau88l25_max98357a.o
obj-$(CONFIG_SND_SOC_INTEL_SKL_NAU88L25_SSM4567_MACH) += snd-soc-skl_nau88l25_ssm4567.o
This diff is collapsed.
......@@ -232,6 +232,18 @@ static struct snd_soc_dai_link cht_dailink[] = {
.dpcm_capture = 1,
.ops = &cht_aif1_ops,
},
[MERR_DPCM_DEEP_BUFFER] = {
.name = "Deep-Buffer Audio Port",
.stream_name = "Deep-Buffer Audio",
.cpu_dai_name = "deepbuffer-cpu-dai",
.codec_dai_name = "snd-soc-dummy-dai",
.codec_name = "snd-soc-dummy",
.platform_name = "sst-mfld-platform",
.nonatomic = true,
.dynamic = 1,
.dpcm_playback = 1,
.ops = &cht_aif1_ops,
},
[MERR_DPCM_COMPR] = {
.name = "Compressed Port",
.stream_name = "Compress",
......
......@@ -260,6 +260,18 @@ static struct snd_soc_dai_link cht_dailink[] = {
.dpcm_capture = 1,
.ops = &cht_aif1_ops,
},
[MERR_DPCM_DEEP_BUFFER] = {
.name = "Deep-Buffer Audio Port",
.stream_name = "Deep-Buffer Audio",
.cpu_dai_name = "deepbuffer-cpu-dai",
.codec_dai_name = "snd-soc-dummy-dai",
.codec_name = "snd-soc-dummy",
.platform_name = "sst-mfld-platform",
.nonatomic = true,
.dynamic = 1,
.dpcm_playback = 1,
.ops = &cht_aif1_ops,
},
[MERR_DPCM_COMPR] = {
.name = "Compressed Port",
.stream_name = "Compress",
......
......@@ -248,6 +248,18 @@ static struct snd_soc_dai_link cht_dailink[] = {
.dpcm_capture = 1,
.ops = &cht_aif1_ops,
},
[MERR_DPCM_DEEP_BUFFER] = {
.name = "Deep-Buffer Audio Port",
.stream_name = "Deep-Buffer Audio",
.cpu_dai_name = "deepbuffer-cpu-dai",
.codec_dai_name = "snd-soc-dummy-dai",
.codec_name = "snd-soc-dummy",
.platform_name = "sst-mfld-platform",
.nonatomic = true,
.dynamic = 1,
.dpcm_playback = 1,
.ops = &cht_aif1_ops,
},
[MERR_DPCM_COMPR] = {
.name = "Compressed Port",
.stream_name = "Compress",
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
snd-soc-sst-dsp-objs := sst-dsp.o
snd-soc-sst-acpi-objs := sst-acpi.o
snd-soc-sst-acpi-objs := sst-acpi.o sst-match-acpi.o
snd-soc-sst-ipc-objs := sst-ipc.o
ifneq ($(CONFIG_DW_DMAC_CORE),)
snd-soc-sst-dsp-objs += sst-firmware.o
endif
snd-soc-sst-dsp-$(CONFIG_DW_DMAC_CORE) += sst-firmware.o
obj-$(CONFIG_SND_SOC_INTEL_SST) += snd-soc-sst-dsp.o snd-soc-sst-ipc.o
obj-$(CONFIG_SND_SOC_INTEL_SST_ACPI) += snd-soc-sst-acpi.o
......@@ -21,21 +21,12 @@
#include <linux/platform_device.h>
#include "sst-dsp.h"
#include "sst-acpi.h"
#define SST_LPT_DSP_DMA_ADDR_OFFSET 0x0F0000
#define SST_WPT_DSP_DMA_ADDR_OFFSET 0x0FE000
#define SST_LPT_DSP_DMA_SIZE (1024 - 1)
/* Descriptor for SST ASoC machine driver */
struct sst_acpi_mach {
/* ACPI ID for the matching machine driver. Audio codec for instance */
const u8 id[ACPI_ID_LEN];
/* machine driver name */
const char *drv_name;
/* firmware file name */
const char *fw_filename;
};
/* Descriptor for setting up SST platform data */
struct sst_acpi_desc {
const char *drv_name;
......@@ -88,28 +79,6 @@ static void sst_acpi_fw_cb(const struct firmware *fw, void *context)
return;
}
static acpi_status sst_acpi_mach_match(acpi_handle handle, u32 level,
void *context, void **ret)
{
*(bool *)context = true;
return AE_OK;
}
static struct sst_acpi_mach *sst_acpi_find_machine(
struct sst_acpi_mach *machines)
{
struct sst_acpi_mach *mach;
bool found = false;
for (mach = machines; mach->id[0]; mach++)
if (ACPI_SUCCESS(acpi_get_devices(mach->id,
sst_acpi_mach_match,
&found, NULL)) && found)
return mach;
return NULL;
}
static int sst_acpi_probe(struct platform_device *pdev)
{
const struct acpi_device_id *id;
......@@ -211,7 +180,7 @@ static int sst_acpi_remove(struct platform_device *pdev)
}
static struct sst_acpi_mach haswell_machines[] = {
{ "INT33CA", "haswell-audio", "intel/IntcSST1.bin" },
{ "INT33CA", "haswell-audio", "intel/IntcSST1.bin", NULL, NULL, NULL },
{}
};
......@@ -229,7 +198,7 @@ static struct sst_acpi_desc sst_acpi_haswell_desc = {
};
static struct sst_acpi_mach broadwell_machines[] = {
{ "INT343A", "broadwell-audio", "intel/IntcSST2.bin" },
{ "INT343A", "broadwell-audio", "intel/IntcSST2.bin", NULL, NULL, NULL },
{}
};
......@@ -247,8 +216,8 @@ static struct sst_acpi_desc sst_acpi_broadwell_desc = {
};
static struct sst_acpi_mach baytrail_machines[] = {
{ "10EC5640", "byt-rt5640", "intel/fw_sst_0f28.bin-48kHz_i2s_master" },
{ "193C9890", "byt-max98090", "intel/fw_sst_0f28.bin-48kHz_i2s_master" },
{ "10EC5640", "byt-rt5640", "intel/fw_sst_0f28.bin-48kHz_i2s_master", NULL, NULL, NULL },
{ "193C9890", "byt-max98090", "intel/fw_sst_0f28.bin-48kHz_i2s_master", NULL, NULL, NULL },
{}
};
......
/*
* Copyright (C) 2013-15, Intel Corporation. All rights reserved.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License version
* 2 as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
*/
#include <linux/acpi.h>
/* acpi match */
struct sst_acpi_mach *sst_acpi_find_machine(struct sst_acpi_mach *machines);
/* Descriptor for SST ASoC machine driver */
struct sst_acpi_mach {
/* ACPI ID for the matching machine driver. Audio codec for instance */
const u8 id[ACPI_ID_LEN];
/* machine driver name */
const char *drv_name;
/* firmware file name */
const char *fw_filename;
/* board name */
const char *board;
void (*machine_quirk)(void);
void *pdata;
};
......@@ -243,7 +243,7 @@ struct sst_mem_block {
u32 size; /* block size */
u32 index; /* block index 0..N */
enum sst_mem_type type; /* block memory type IRAM/DRAM */
struct sst_block_ops *ops; /* block operations, if any */
const struct sst_block_ops *ops;/* block operations, if any */
/* block status */
u32 bytes_used; /* bytes in use by modules */
......@@ -308,6 +308,8 @@ struct sst_dsp {
/* SKL data */
const char *fw_name;
/* To allocate CL dma buffers */
struct skl_dsp_loader_ops dsp_ops;
struct skl_dsp_fw_ops fw_ops;
......@@ -376,8 +378,8 @@ void sst_block_free_scratch(struct sst_dsp *dsp);
/* Register the DSPs memory blocks - would be nice to read from ACPI */
struct sst_mem_block *sst_mem_block_register(struct sst_dsp *dsp, u32 offset,
u32 size, enum sst_mem_type type, struct sst_block_ops *ops, u32 index,
void *private);
u32 size, enum sst_mem_type type, const struct sst_block_ops *ops,
u32 index, void *private);
void sst_mem_block_unregister_all(struct sst_dsp *dsp);
/* Create/Free DMA resources */
......
......@@ -420,7 +420,7 @@ void sst_dsp_inbox_read(struct sst_dsp *sst, void *message, size_t bytes)
}
EXPORT_SYMBOL_GPL(sst_dsp_inbox_read);
#if IS_ENABLED(CONFIG_DW_DMAC_CORE)
#ifdef CONFIG_DW_DMAC_CORE
struct sst_dsp *sst_dsp_new(struct device *dev,
struct sst_dsp_device *sst_dev, struct sst_pdata *pdata)
{
......
......@@ -216,7 +216,7 @@ struct sst_pdata {
void *dsp;
};
#if IS_ENABLED(CONFIG_DW_DMAC_CORE)
#ifdef CONFIG_DW_DMAC_CORE
/* Initialization */
struct sst_dsp *sst_dsp_new(struct device *dev,
struct sst_dsp_device *sst_dev, struct sst_pdata *pdata);
......
This diff is collapsed.
This diff is collapsed.
......@@ -607,7 +607,7 @@ static int hsw_block_disable(struct sst_mem_block *block)
return 0;
}
static struct sst_block_ops sst_hsw_ops = {
static const struct sst_block_ops sst_hsw_ops = {
.enable = hsw_block_enable,
.disable = hsw_block_disable,
};
......
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.
......@@ -61,13 +61,17 @@ struct skl {
unsigned int init_failed:1; /* delayed init failed */
struct platform_device *dmic_dev;
struct platform_device *i2s_dev;
void *nhlt; /* nhlt ptr */
struct skl_sst *skl_sst; /* sst skl ctx */
struct skl_dsp_resource resource;
struct list_head ppl_list;
struct list_head dapm_path_list;
const char *fw_name;
int supend_active;
};
#define skl_to_ebus(s) (&(s)->ebus)
......
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