Commit 50946b2a authored by Mark Brown's avatar Mark Brown

Merge remote-tracking branches 'asoc/topic/fsl-ssi', 'asoc/topic/hi6220' and...

Merge remote-tracking branches 'asoc/topic/fsl-ssi', 'asoc/topic/hi6220' and 'asoc/topic/imx' into asoc-next
......@@ -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
......@@ -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
......
* 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 */
......@@ -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"
......
......@@ -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/
......
......@@ -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>
......@@ -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
*
......@@ -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,
......@@ -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,
......
......@@ -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,
......
......@@ -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),
......@@ -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;
}
......@@ -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;
......@@ -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,
......@@ -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;
......@@ -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) {
......@@ -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";
......@@ -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;
......@@ -277,16 +280,9 @@ 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);
......@@ -294,17 +290,6 @@ static int imx_wm8962_probe(struct platform_device *pdev)
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 */ }
......@@ -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);
......
config SND_I2S_HI6210_I2S
tristate "Hisilicon I2S controller"
select SND_SOC_GENERIC_DMAENGINE_PCM
help
Hisilicon I2S
obj-$(CONFIG_SND_I2S_HI6210_I2S) += hi6210-i2s.o
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