Skip to content

Commit

Permalink
Merge remote-tracking branches 'asoc/topic/fsl-ssi', 'asoc/topic/hi62…
Browse files Browse the repository at this point in the history
…20' and 'asoc/topic/imx' into asoc-next
  • Loading branch information
broonie committed Apr 30, 2017
4 parents 0f57c12 + 23aaf4c + e6d56d2 + 8f7206d commit 50946b2
Show file tree
Hide file tree
Showing 11 changed files with 997 additions and 108 deletions.
34 changes: 18 additions & 16 deletions Documentation/devicetree/bindings/sound/fsl,ssi.txt
Original file line number Diff line number Diff line change
Expand Up @@ -20,24 +20,8 @@ Required properties:
have.
- interrupt-parent: The phandle for the interrupt controller that
services interrupts for this device.
- fsl,playback-dma: Phandle to a node for the DMA channel to use for
playback of audio. This is typically dictated by SOC
design. See the notes below.
- fsl,capture-dma: Phandle to a node for the DMA channel to use for
capture (recording) of audio. This is typically dictated
by SOC design. See the notes below.
- fsl,fifo-depth: The number of elements in the transmit and receive FIFOs.
This number is the maximum allowed value for SFCSR[TFWM0].
- fsl,ssi-asynchronous:
If specified, the SSI is to be programmed in asynchronous
mode. In this mode, pins SRCK, STCK, SRFS, and STFS must
all be connected to valid signals. In synchronous mode,
SRCK and SRFS are ignored. Asynchronous mode allows
playback and capture to use different sample sizes and
sample rates. Some drivers may require that SRCK and STCK
be connected together, and SRFS and STFS be connected
together. This would still allow different sample sizes,
but not different sample rates.
- clocks: "ipg" - Required clock for the SSI unit
"baud" - Required clock for SSI master mode. Otherwise this
clock is not used
Expand All @@ -61,6 +45,24 @@ Optional properties:
- fsl,mode: The operating mode for the AC97 interface only.
"ac97-slave" - AC97 mode, SSI is clock slave
"ac97-master" - AC97 mode, SSI is clock master
- fsl,ssi-asynchronous:
If specified, the SSI is to be programmed in asynchronous
mode. In this mode, pins SRCK, STCK, SRFS, and STFS must
all be connected to valid signals. In synchronous mode,
SRCK and SRFS are ignored. Asynchronous mode allows
playback and capture to use different sample sizes and
sample rates. Some drivers may require that SRCK and STCK
be connected together, and SRFS and STFS be connected
together. This would still allow different sample sizes,
but not different sample rates.
- fsl,playback-dma: Phandle to a node for the DMA channel to use for
playback of audio. This is typically dictated by SOC
design. See the notes below.
Only used on Power Architecture.
- fsl,capture-dma: Phandle to a node for the DMA channel to use for
capture (recording) of audio. This is typically dictated
by SOC design. See the notes below.
Only used on Power Architecture.

Child 'codec' node required properties:
- compatible: Compatible list, contains the name of the codec
Expand Down
42 changes: 42 additions & 0 deletions Documentation/devicetree/bindings/sound/hisilicon,hi6210-i2s.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
* Hisilicon 6210 i2s controller

Required properties:

- compatible: should be one of the following:
- "hisilicon,hi6210-i2s"
- reg: physical base address of the i2s controller unit and length of
memory mapped region.
- interrupts: should contain the i2s interrupt.
- clocks: a list of phandle + clock-specifier pairs, one for each entry
in clock-names.
- clock-names: should contain following:
- "dacodec"
- "i2s-base"
- dmas: DMA specifiers for tx dma. See the DMA client binding,
Documentation/devicetree/bindings/dma/dma.txt
- dma-names: should be "tx" and "rx"
- hisilicon,sysctrl-syscon: phandle to sysctrl syscon
- #sound-dai-cells: Should be set to 1 (for multi-dai)
- The dai cell indexes reference the following interfaces:
0: S2 interface
(Currently that is the only one available, but more may be
supported in the future)

Example for the hi6210 i2s controller:

i2s0: i2s@f7118000{
compatible = "hisilicon,hi6210-i2s";
reg = <0x0 0xf7118000 0x0 0x8000>; /* i2s unit */
interrupts = <GIC_SPI 123 IRQ_TYPE_LEVEL_HIGH>; /* 155 "DigACodec_intr"-32 */
clocks = <&sys_ctrl HI6220_DACODEC_PCLK>,
<&sys_ctrl HI6220_BBPPLL0_DIV>;
clock-names = "dacodec", "i2s-base";
dmas = <&dma0 15 &dma0 14>;
dma-names = "rx", "tx";
hisilicon,sysctrl-syscon = <&sys_ctrl>;
#sound-dai-cells = <1>;
};

Then when referencing the i2s controller:
sound-dai = <&i2s0 0>; /* index 0 => S2 interface */

1 change: 1 addition & 0 deletions sound/soc/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ source "sound/soc/cirrus/Kconfig"
source "sound/soc/davinci/Kconfig"
source "sound/soc/dwc/Kconfig"
source "sound/soc/fsl/Kconfig"
source "sound/soc/hisilicon/Kconfig"
source "sound/soc/jz4740/Kconfig"
source "sound/soc/nuc900/Kconfig"
source "sound/soc/omap/Kconfig"
Expand Down
1 change: 1 addition & 0 deletions sound/soc/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ obj-$(CONFIG_SND_SOC) += cirrus/
obj-$(CONFIG_SND_SOC) += davinci/
obj-$(CONFIG_SND_SOC) += dwc/
obj-$(CONFIG_SND_SOC) += fsl/
obj-$(CONFIG_SND_SOC) += hisilicon/
obj-$(CONFIG_SND_SOC) += jz4740/
obj-$(CONFIG_SND_SOC) += img/
obj-$(CONFIG_SND_SOC) += intel/
Expand Down
27 changes: 7 additions & 20 deletions sound/soc/fsl/fsl_ssi.c
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
#include <linux/module.h>
#include <linux/interrupt.h>
#include <linux/clk.h>
#include <linux/ctype.h>
#include <linux/device.h>
#include <linux/delay.h>
#include <linux/slab.h>
Expand All @@ -54,16 +55,6 @@
#include "fsl_ssi.h"
#include "imx-pcm.h"

/**
* FSLSSI_I2S_RATES: sample rates supported by the I2S
*
* This driver currently only supports the SSI running in I2S slave mode,
* which means the codec determines the sample rate. Therefore, we tell
* ALSA that we support all rates and let the codec driver decide what rates
* are really supported.
*/
#define FSLSSI_I2S_RATES SNDRV_PCM_RATE_CONTINUOUS

/**
* FSLSSI_I2S_FORMATS: audio formats supported by the SSI
*
Expand Down Expand Up @@ -1212,14 +1203,14 @@ static struct snd_soc_dai_driver fsl_ssi_dai_template = {
.stream_name = "CPU-Playback",
.channels_min = 1,
.channels_max = 32,
.rates = FSLSSI_I2S_RATES,
.rates = SNDRV_PCM_RATE_CONTINUOUS,
.formats = FSLSSI_I2S_FORMATS,
},
.capture = {
.stream_name = "CPU-Capture",
.channels_min = 1,
.channels_max = 32,
.rates = FSLSSI_I2S_RATES,
.rates = SNDRV_PCM_RATE_CONTINUOUS,
.formats = FSLSSI_I2S_FORMATS,
},
.ops = &fsl_ssi_dai_ops,
Expand Down Expand Up @@ -1325,14 +1316,10 @@ static struct snd_ac97_bus_ops fsl_ssi_ac97_ops = {
*/
static void make_lowercase(char *s)
{
char *p = s;
char c;

while ((c = *p)) {
if ((c >= 'A') && (c <= 'Z'))
*p = c + ('a' - 'A');
p++;
}
if (!s)
return;
for (; *s; s++)
*s = tolower(*s);
}

static int fsl_ssi_imx_probe(struct platform_device *pdev,
Expand Down
28 changes: 0 additions & 28 deletions sound/soc/fsl/imx-pcm-dma.c
Original file line number Diff line number Diff line change
Expand Up @@ -33,48 +33,20 @@ static bool filter(struct dma_chan *chan, void *param)
return true;
}

static const struct snd_pcm_hardware imx_pcm_hardware = {
.info = SNDRV_PCM_INFO_INTERLEAVED |
SNDRV_PCM_INFO_BLOCK_TRANSFER |
SNDRV_PCM_INFO_MMAP |
SNDRV_PCM_INFO_MMAP_VALID |
SNDRV_PCM_INFO_PAUSE |
SNDRV_PCM_INFO_RESUME,
.buffer_bytes_max = IMX_DEFAULT_DMABUF_SIZE,
.period_bytes_min = 128,
.period_bytes_max = 65535, /* Limited by SDMA engine */
.periods_min = 2,
.periods_max = 255,
.fifo_size = 0,
};

static const struct snd_dmaengine_pcm_config imx_dmaengine_pcm_config = {
.pcm_hardware = &imx_pcm_hardware,
.prepare_slave_config = snd_dmaengine_pcm_prepare_slave_config,
.compat_filter_fn = filter,
.prealloc_buffer_size = IMX_DEFAULT_DMABUF_SIZE,
};

int imx_pcm_dma_init(struct platform_device *pdev, size_t size)
{
struct snd_dmaengine_pcm_config *config;
struct snd_pcm_hardware *pcm_hardware;

config = devm_kzalloc(&pdev->dev,
sizeof(struct snd_dmaengine_pcm_config), GFP_KERNEL);
if (!config)
return -ENOMEM;
*config = imx_dmaengine_pcm_config;
if (size)
config->prealloc_buffer_size = size;

pcm_hardware = devm_kzalloc(&pdev->dev,
sizeof(struct snd_pcm_hardware), GFP_KERNEL);
*pcm_hardware = imx_pcm_hardware;
if (size)
pcm_hardware->buffer_bytes_max = size;

config->pcm_hardware = pcm_hardware;

return devm_snd_dmaengine_pcm_register(&pdev->dev,
config,
Expand Down
72 changes: 28 additions & 44 deletions sound/soc/fsl/imx-wm8962.c
Original file line number Diff line number Diff line change
Expand Up @@ -33,14 +33,14 @@ struct imx_wm8962_data {
struct snd_soc_card card;
char codec_dai_name[DAI_NAME_SIZE];
char platform_name[DAI_NAME_SIZE];
struct clk *codec_clk;
unsigned int clk_frequency;
};

struct imx_priv {
struct platform_device *pdev;
int sample_rate;
snd_pcm_format_t sample_format;
};
static struct imx_priv card_priv;

static const struct snd_soc_dapm_widget imx_wm8962_dapm_widgets[] = {
SND_SOC_DAPM_HP("Headphone Jack", NULL),
Expand All @@ -49,14 +49,14 @@ static const struct snd_soc_dapm_widget imx_wm8962_dapm_widgets[] = {
SND_SOC_DAPM_MIC("DMIC", NULL),
};

static int sample_rate = 44100;
static snd_pcm_format_t sample_format = SNDRV_PCM_FORMAT_S16_LE;

static int imx_hifi_hw_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params)
{
sample_rate = params_rate(params);
sample_format = params_format(params);
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct imx_priv *priv = snd_soc_card_get_drvdata(rtd->card);

priv->sample_rate = params_rate(params);
priv->sample_format = params_format(params);

return 0;
}
Expand All @@ -71,7 +71,7 @@ static int imx_wm8962_set_bias_level(struct snd_soc_card *card,
{
struct snd_soc_pcm_runtime *rtd;
struct snd_soc_dai *codec_dai;
struct imx_priv *priv = &card_priv;
struct imx_priv *priv = snd_soc_card_get_drvdata(card);
struct imx_wm8962_data *data = snd_soc_card_get_drvdata(card);
struct device *dev = &priv->pdev->dev;
unsigned int pll_out;
Expand All @@ -85,10 +85,10 @@ static int imx_wm8962_set_bias_level(struct snd_soc_card *card,
switch (level) {
case SND_SOC_BIAS_PREPARE:
if (dapm->bias_level == SND_SOC_BIAS_STANDBY) {
if (sample_format == SNDRV_PCM_FORMAT_S24_LE)
pll_out = sample_rate * 384;
if (priv->sample_format == SNDRV_PCM_FORMAT_S24_LE)
pll_out = priv->sample_rate * 384;
else
pll_out = sample_rate * 256;
pll_out = priv->sample_rate * 256;

ret = snd_soc_dai_set_pll(codec_dai, WM8962_FLL,
WM8962_FLL_MCLK, data->clk_frequency,
Expand Down Expand Up @@ -140,7 +140,7 @@ static int imx_wm8962_late_probe(struct snd_soc_card *card)
{
struct snd_soc_pcm_runtime *rtd;
struct snd_soc_dai *codec_dai;
struct imx_priv *priv = &card_priv;
struct imx_priv *priv = snd_soc_card_get_drvdata(card);
struct imx_wm8962_data *data = snd_soc_card_get_drvdata(card);
struct device *dev = &priv->pdev->dev;
int ret;
Expand All @@ -160,13 +160,20 @@ static int imx_wm8962_probe(struct platform_device *pdev)
struct device_node *np = pdev->dev.of_node;
struct device_node *ssi_np, *codec_np;
struct platform_device *ssi_pdev;
struct imx_priv *priv = &card_priv;
struct i2c_client *codec_dev;
struct imx_wm8962_data *data;
struct imx_priv *priv;
struct clk *codec_clk;
int int_port, ext_port;
int ret;

priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
if (!priv)
return -ENOMEM;

priv->pdev = pdev;
priv->sample_rate = 44100;
priv->sample_format = SNDRV_PCM_FORMAT_S16_LE;

ret = of_property_read_u32(np, "mux-int-port", &int_port);
if (ret) {
Expand Down Expand Up @@ -231,19 +238,15 @@ static int imx_wm8962_probe(struct platform_device *pdev)
goto fail;
}

data->codec_clk = devm_clk_get(&codec_dev->dev, NULL);
if (IS_ERR(data->codec_clk)) {
ret = PTR_ERR(data->codec_clk);
codec_clk = clk_get(&codec_dev->dev, NULL);
if (IS_ERR(codec_clk)) {
ret = PTR_ERR(codec_clk);
dev_err(&codec_dev->dev, "failed to get codec clk: %d\n", ret);
goto fail;
}

data->clk_frequency = clk_get_rate(data->codec_clk);
ret = clk_prepare_enable(data->codec_clk);
if (ret) {
dev_err(&codec_dev->dev, "failed to enable codec clk: %d\n", ret);
goto fail;
}
data->clk_frequency = clk_get_rate(codec_clk);
clk_put(codec_clk);

data->dai.name = "HiFi";
data->dai.stream_name = "HiFi";
Expand All @@ -258,10 +261,10 @@ static int imx_wm8962_probe(struct platform_device *pdev)
data->card.dev = &pdev->dev;
ret = snd_soc_of_parse_card_name(&data->card, "model");
if (ret)
goto clk_fail;
goto fail;
ret = snd_soc_of_parse_audio_routing(&data->card, "audio-routing");
if (ret)
goto clk_fail;
goto fail;
data->card.num_links = 1;
data->card.owner = THIS_MODULE;
data->card.dai_link = &data->dai;
Expand All @@ -277,34 +280,16 @@ static int imx_wm8962_probe(struct platform_device *pdev)
ret = devm_snd_soc_register_card(&pdev->dev, &data->card);
if (ret) {
dev_err(&pdev->dev, "snd_soc_register_card failed (%d)\n", ret);
goto clk_fail;
goto fail;
}

of_node_put(ssi_np);
of_node_put(codec_np);

return 0;

clk_fail:
clk_disable_unprepare(data->codec_clk);
fail:
of_node_put(ssi_np);
of_node_put(codec_np);

return ret;
}

static int imx_wm8962_remove(struct platform_device *pdev)
{
struct snd_soc_card *card = platform_get_drvdata(pdev);
struct imx_wm8962_data *data = snd_soc_card_get_drvdata(card);

if (!IS_ERR(data->codec_clk))
clk_disable_unprepare(data->codec_clk);

return 0;
}

static const struct of_device_id imx_wm8962_dt_ids[] = {
{ .compatible = "fsl,imx-audio-wm8962", },
{ /* sentinel */ }
Expand All @@ -318,7 +303,6 @@ static struct platform_driver imx_wm8962_driver = {
.of_match_table = imx_wm8962_dt_ids,
},
.probe = imx_wm8962_probe,
.remove = imx_wm8962_remove,
};
module_platform_driver(imx_wm8962_driver);

Expand Down
5 changes: 5 additions & 0 deletions sound/soc/hisilicon/Kconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
config SND_I2S_HI6210_I2S
tristate "Hisilicon I2S controller"
select SND_SOC_GENERIC_DMAENGINE_PCM
help
Hisilicon I2S
1 change: 1 addition & 0 deletions sound/soc/hisilicon/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
obj-$(CONFIG_SND_I2S_HI6210_I2S) += hi6210-i2s.o
Loading

0 comments on commit 50946b2

Please sign in to comment.