Commit e7177999 authored by Mark Brown's avatar Mark Brown

Merge remote-tracking branches 'asoc/topic/fsl', 'asoc/topic/fsl-asrc',...

Merge remote-tracking branches 'asoc/topic/fsl', 'asoc/topic/fsl-asrc', 'asoc/topic/fsl-spdif' and 'asoc/topic/imx-audmux' into asoc-next
Freescale Asynchronous Sample Rate Converter (ASRC) Controller
The Asynchronous Sample Rate Converter (ASRC) converts the sampling rate of a
signal associated with an input clock into a signal associated with a different
output clock. The driver currently works as a Front End of DPCM with other Back
Ends Audio controller such as ESAI, SSI and SAI. It has three pairs to support
three substreams within totally 10 channels.
Required properties:
- compatible : Contains "fsl,imx35-asrc" or "fsl,imx53-asrc".
- reg : Offset and length of the register set for the device.
- interrupts : Contains the spdif interrupt.
- dmas : Generic dma devicetree binding as described in
Documentation/devicetree/bindings/dma/dma.txt.
- dma-names : Contains "rxa", "rxb", "rxc", "txa", "txb" and "txc".
- clocks : Contains an entry for each entry in clock-names.
- clock-names : Contains the following entries
"mem" Peripheral access clock to access registers.
"ipg" Peripheral clock to driver module.
"asrck_<0-f>" Clock sources for input and output clock.
- big-endian : If this property is absent, the little endian mode
will be in use as default. Otherwise, the big endian
mode will be in use for all the device registers.
- fsl,asrc-rate : Defines a mutual sample rate used by DPCM Back Ends.
- fsl,asrc-width : Defines a mutual sample width used by DPCM Back Ends.
Example:
asrc: asrc@02034000 {
compatible = "fsl,imx53-asrc";
reg = <0x02034000 0x4000>;
interrupts = <0 50 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&clks 107>, <&clks 107>, <&clks 0>,
<&clks 0>, <&clks 0>, <&clks 0>, <&clks 0>,
<&clks 0>, <&clks 0>, <&clks 0>, <&clks 0>,
<&clks 0>, <&clks 0>, <&clks 0>, <&clks 0>,
<&clks 107>, <&clks 0>, <&clks 0>;
clock-names = "mem", "ipg", "asrck0",
"asrck_1", "asrck_2", "asrck_3", "asrck_4",
"asrck_5", "asrck_6", "asrck_7", "asrck_8",
"asrck_9", "asrck_a", "asrck_b", "asrck_c",
"asrck_d", "asrck_e", "asrck_f";
dmas = <&sdma 17 23 1>, <&sdma 18 23 1>, <&sdma 19 23 1>,
<&sdma 20 23 1>, <&sdma 21 23 1>, <&sdma 22 23 1>;
dma-names = "rxa", "rxb", "rxc",
"txa", "txb", "txc";
fsl,asrc-rate = <48000>;
fsl,asrc-width = <16>;
status = "okay";
};
......@@ -50,6 +50,7 @@ enum imx_dma_prio {
struct imx_dma_data {
int dma_request; /* DMA request line */
int dma_request2; /* secondary DMA request line */
enum sdma_peripheral_type peripheral_type;
int priority;
};
......
......@@ -2,9 +2,20 @@ menu "SoC Audio for Freescale CPUs"
comment "Common SoC Audio options for Freescale CPUs:"
config SND_SOC_FSL_ASRC
tristate "Asynchronous Sample Rate Converter (ASRC) module support"
select REGMAP_MMIO
select SND_SOC_GENERIC_DMAENGINE_PCM
help
Say Y if you want to add Asynchronous Sample Rate Converter (ASRC)
support for the Freescale CPUs.
This option is only useful for out-of-tree drivers since
in-tree drivers select it automatically.
config SND_SOC_FSL_SAI
tristate "Synchronous Audio Interface (SAI) module support"
select REGMAP_MMIO
select SND_SOC_IMX_PCM_DMA if SND_IMX_SOC != n
select SND_SOC_GENERIC_DMAENGINE_PCM
help
Say Y if you want to add Synchronous Audio Interface (SAI)
......@@ -15,7 +26,7 @@ config SND_SOC_FSL_SAI
config SND_SOC_FSL_SSI
tristate "Synchronous Serial Interface module support"
select SND_SOC_IMX_PCM_DMA if SND_IMX_SOC != n
select SND_SOC_IMX_PCM_FIQ if SND_IMX_SOC != n && ARCH_MXC
select SND_SOC_IMX_PCM_FIQ if SND_IMX_SOC != n && (MXC_TZIC || MXC_AVIC)
select REGMAP_MMIO
help
Say Y if you want to add Synchronous Serial Interface (SSI)
......@@ -27,7 +38,7 @@ config SND_SOC_FSL_SPDIF
tristate "Sony/Philips Digital Interface module support"
select REGMAP_MMIO
select SND_SOC_IMX_PCM_DMA if SND_IMX_SOC != n
select SND_SOC_IMX_PCM_FIQ if SND_IMX_SOC != n && ARCH_MXC
select SND_SOC_IMX_PCM_FIQ if SND_IMX_SOC != n && (MXC_TZIC || MXC_AVIC)
help
Say Y if you want to add Sony/Philips Digital Interface (SPDIF)
support for the Freescale CPUs.
......@@ -37,6 +48,7 @@ config SND_SOC_FSL_SPDIF
config SND_SOC_FSL_ESAI
tristate "Enhanced Serial Audio Interface (ESAI) module support"
select REGMAP_MMIO
select SND_SOC_IMX_PCM_DMA if SND_IMX_SOC != n
select SND_SOC_FSL_UTILS
help
Say Y if you want to add Enhanced Synchronous Audio Interface
......
......@@ -11,6 +11,7 @@ snd-soc-p1022-rdk-objs := p1022_rdk.o
obj-$(CONFIG_SND_SOC_P1022_RDK) += snd-soc-p1022-rdk.o
# Freescale SSI/DMA/SAI/SPDIF Support
snd-soc-fsl-asrc-objs := fsl_asrc.o fsl_asrc_dma.o
snd-soc-fsl-sai-objs := fsl_sai.o
snd-soc-fsl-ssi-y := fsl_ssi.o
snd-soc-fsl-ssi-$(CONFIG_DEBUG_FS) += fsl_ssi_dbg.o
......@@ -18,6 +19,7 @@ snd-soc-fsl-spdif-objs := fsl_spdif.o
snd-soc-fsl-esai-objs := fsl_esai.o
snd-soc-fsl-utils-objs := fsl_utils.o
snd-soc-fsl-dma-objs := fsl_dma.o
obj-$(CONFIG_SND_SOC_FSL_ASRC) += snd-soc-fsl-asrc.o
obj-$(CONFIG_SND_SOC_FSL_SAI) += snd-soc-fsl-sai.o
obj-$(CONFIG_SND_SOC_FSL_SSI) += snd-soc-fsl-ssi.o
obj-$(CONFIG_SND_SOC_FSL_SPDIF) += snd-soc-fsl-spdif.o
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
......@@ -624,12 +624,14 @@ static int fsl_esai_dai_probe(struct snd_soc_dai *dai)
static struct snd_soc_dai_driver fsl_esai_dai = {
.probe = fsl_esai_dai_probe,
.playback = {
.stream_name = "CPU-Playback",
.channels_min = 1,
.channels_max = 12,
.rates = FSL_ESAI_RATES,
.formats = FSL_ESAI_FORMATS,
},
.capture = {
.stream_name = "CPU-Capture",
.channels_min = 1,
.channels_max = 8,
.rates = FSL_ESAI_RATES,
......
......@@ -455,12 +455,14 @@ static int fsl_sai_dai_probe(struct snd_soc_dai *cpu_dai)
static struct snd_soc_dai_driver fsl_sai_dai = {
.probe = fsl_sai_dai_probe,
.playback = {
.stream_name = "CPU-Playback",
.channels_min = 1,
.channels_max = 2,
.rates = SNDRV_PCM_RATE_8000_96000,
.formats = FSL_SAI_FORMATS,
},
.capture = {
.stream_name = "CPU-Capture",
.channels_min = 1,
.channels_max = 2,
.rates = SNDRV_PCM_RATE_8000_96000,
......
......@@ -32,10 +32,13 @@
#define FSL_SPDIF_TXFIFO_WML 0x8
#define FSL_SPDIF_RXFIFO_WML 0x8
#define INTR_FOR_PLAYBACK (INT_TXFIFO_RESYNC)
#define INTR_FOR_CAPTURE (INT_SYM_ERR | INT_BIT_ERR | INT_URX_FUL | INT_URX_OV|\
INT_QRX_FUL | INT_QRX_OV | INT_UQ_SYNC | INT_UQ_ERR |\
INT_RXFIFO_RESYNC | INT_LOSS_LOCK | INT_DPLL_LOCKED)
#define INTR_FOR_PLAYBACK (INT_TXFIFO_RESYNC)
#define INTR_FOR_CAPTURE (INT_SYM_ERR | INT_BIT_ERR | INT_URX_FUL |\
INT_URX_OV | INT_QRX_FUL | INT_QRX_OV |\
INT_UQ_SYNC | INT_UQ_ERR | INT_RXFIFO_RESYNC |\
INT_LOSS_LOCK | INT_DPLL_LOCKED)
#define SIE_INTR_FOR(tx) (tx ? INTR_FOR_PLAYBACK : INTR_FOR_CAPTURE)
/* Index list for the values that has if (DPLL Locked) condition */
static u8 srpc_dpll_locked[] = { 0x0, 0x1, 0x2, 0x3, 0x4, 0xa, 0xb };
......@@ -96,7 +99,7 @@ struct fsl_spdif_priv {
struct platform_device *pdev;
struct regmap *regmap;
bool dpll_locked;
u16 txrate[SPDIF_TXRATE_MAX];
u32 txrate[SPDIF_TXRATE_MAX];
u8 txclk_df[SPDIF_TXRATE_MAX];
u8 sysclk_df[SPDIF_TXRATE_MAX];
u8 txclk_src[SPDIF_TXRATE_MAX];
......@@ -137,10 +140,9 @@ static void spdif_irq_sym_error(struct fsl_spdif_priv *spdif_priv)
dev_dbg(&pdev->dev, "isr: receiver found illegal symbol\n");
if (!spdif_priv->dpll_locked) {
/* DPLL unlocked seems no audio stream */
/* Clear illegal symbol if DPLL unlocked since no audio stream */
if (!spdif_priv->dpll_locked)
regmap_update_bits(regmap, REG_SPDIF_SIE, INT_SYM_ERR, 0);
}
}
/* U/Q Channel receive register full */
......@@ -335,8 +337,8 @@ static void spdif_write_channel_status(struct fsl_spdif_priv *spdif_priv)
u32 ch_status;
ch_status = (bitrev8(ctrl->ch_status[0]) << 16) |
(bitrev8(ctrl->ch_status[1]) << 8) |
bitrev8(ctrl->ch_status[2]);
(bitrev8(ctrl->ch_status[1]) << 8) |
bitrev8(ctrl->ch_status[2]);
regmap_write(regmap, REG_SPDIF_STCSCH, ch_status);
dev_dbg(&pdev->dev, "STCSCH: 0x%06x\n", ch_status);
......@@ -390,6 +392,14 @@ static int spdif_set_sample_rate(struct snd_pcm_substream *substream,
rate = SPDIF_TXRATE_48000;
csfs = IEC958_AES3_CON_FS_48000;
break;
case 96000:
rate = SPDIF_TXRATE_96000;
csfs = IEC958_AES3_CON_FS_96000;
break;
case 192000:
rate = SPDIF_TXRATE_192000;
csfs = IEC958_AES3_CON_FS_192000;
break;
default:
dev_err(&pdev->dev, "unsupported sample rate %d\n", sample_rate);
return -EINVAL;
......@@ -433,13 +443,12 @@ static int spdif_set_sample_rate(struct snd_pcm_substream *substream,
spdif_set_cstatus(ctrl, IEC958_AES3_CON_FS, csfs);
/* select clock source and divisor */
stc = STC_TXCLK_ALL_EN | STC_TXCLK_SRC_SET(clk) | STC_TXCLK_DF(txclk_df);
mask = STC_TXCLK_ALL_EN_MASK | STC_TXCLK_SRC_MASK | STC_TXCLK_DF_MASK;
stc = STC_TXCLK_ALL_EN | STC_TXCLK_SRC_SET(clk) |
STC_TXCLK_DF(txclk_df) | STC_SYSCLK_DF(sysclk_df);
mask = STC_TXCLK_ALL_EN_MASK | STC_TXCLK_SRC_MASK |
STC_TXCLK_DF_MASK | STC_SYSCLK_DF_MASK;
regmap_update_bits(regmap, REG_SPDIF_STC, mask, stc);
regmap_update_bits(regmap, REG_SPDIF_STC,
STC_SYSCLK_DF_MASK, STC_SYSCLK_DF(sysclk_df));
dev_dbg(&pdev->dev, "set sample rate to %dHz for %dHz playback\n",
spdif_priv->txrate[rate], sample_rate);
......@@ -553,7 +562,7 @@ static int fsl_spdif_hw_params(struct snd_pcm_substream *substream,
return ret;
}
spdif_set_cstatus(ctrl, IEC958_AES3_CON_CLOCK,
IEC958_AES3_CON_CLOCK_1000PPM);
IEC958_AES3_CON_CLOCK_1000PPM);
spdif_write_channel_status(spdif_priv);
} else {
/* Setup rx clock source */
......@@ -569,9 +578,9 @@ static int fsl_spdif_trigger(struct snd_pcm_substream *substream,
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct fsl_spdif_priv *spdif_priv = snd_soc_dai_get_drvdata(rtd->cpu_dai);
struct regmap *regmap = spdif_priv->regmap;
int is_playack = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK);
u32 intr = is_playack ? INTR_FOR_PLAYBACK : INTR_FOR_CAPTURE;
u32 dmaen = is_playack ? SCR_DMA_TX_EN : SCR_DMA_RX_EN;;
bool tx = substream->stream == SNDRV_PCM_STREAM_PLAYBACK;
u32 intr = SIE_INTR_FOR(tx);
u32 dmaen = SCR_DMA_xX_EN(tx);
switch (cmd) {
case SNDRV_PCM_TRIGGER_START:
......@@ -662,9 +671,8 @@ static int fsl_spdif_capture_get(struct snd_kcontrol *kcontrol,
u32 cstatus, val;
regmap_read(regmap, REG_SPDIF_SIS, &val);
if (!(val & INT_CNEW)) {
if (!(val & INT_CNEW))
return -EAGAIN;
}
regmap_read(regmap, REG_SPDIF_SRCSH, &cstatus);
ucontrol->value.iec958.status[0] = (cstatus >> 16) & 0xFF;
......@@ -693,15 +701,14 @@ static int fsl_spdif_subcode_get(struct snd_kcontrol *kcontrol,
struct fsl_spdif_priv *spdif_priv = snd_soc_dai_get_drvdata(cpu_dai);
struct spdif_mixer_control *ctrl = &spdif_priv->fsl_spdif_control;
unsigned long flags;
int ret = 0;
int ret = -EAGAIN;
spin_lock_irqsave(&ctrl->ctl_lock, flags);
if (ctrl->ready_buf) {
int idx = (ctrl->ready_buf - 1) * SPDIF_UBITS_SIZE;
memcpy(&ucontrol->value.iec958.subcode[0],
&ctrl->subcode[idx], SPDIF_UBITS_SIZE);
} else {
ret = -EAGAIN;
ret = 0;
}
spin_unlock_irqrestore(&ctrl->ctl_lock, flags);
......@@ -726,15 +733,14 @@ static int fsl_spdif_qget(struct snd_kcontrol *kcontrol,
struct fsl_spdif_priv *spdif_priv = snd_soc_dai_get_drvdata(cpu_dai);
struct spdif_mixer_control *ctrl = &spdif_priv->fsl_spdif_control;
unsigned long flags;
int ret = 0;
int ret = -EAGAIN;
spin_lock_irqsave(&ctrl->ctl_lock, flags);
if (ctrl->ready_buf) {
int idx = (ctrl->ready_buf - 1) * SPDIF_QSUB_SIZE;
memcpy(&ucontrol->value.bytes.data[0],
&ctrl->qsub[idx], SPDIF_QSUB_SIZE);
} else {
ret = -EAGAIN;
ret = 0;
}
spin_unlock_irqrestore(&ctrl->ctl_lock, flags);
......@@ -799,10 +805,10 @@ static int spdif_get_rxclk_rate(struct fsl_spdif_priv *spdif_priv,
regmap_read(regmap, REG_SPDIF_SRPC, &phaseconf);
clksrc = (phaseconf >> SRPC_CLKSRC_SEL_OFFSET) & 0xf;
if (srpc_dpll_locked[clksrc] && (phaseconf & SRPC_DPLL_LOCKED)) {
/* Get bus clock from system */
/* Get bus clock from system */
if (srpc_dpll_locked[clksrc] && (phaseconf & SRPC_DPLL_LOCKED))
busclk_freq = clk_get_rate(spdif_priv->sysclk);
}
/* FreqMeas_CLK = (BUS_CLK * FreqMeas) / 2 ^ 10 / GAINSEL / 128 */
tmpval64 = (u64) busclk_freq * freqmeas;
......@@ -826,12 +832,12 @@ static int fsl_spdif_rxrate_get(struct snd_kcontrol *kcontrol,
{
struct snd_soc_dai *cpu_dai = snd_kcontrol_chip(kcontrol);
struct fsl_spdif_priv *spdif_priv = snd_soc_dai_get_drvdata(cpu_dai);
int rate = spdif_get_rxclk_rate(spdif_priv, SPDIF_DEFAULT_GAINSEL);
int rate = 0;
if (spdif_priv->dpll_locked)
ucontrol->value.integer.value[0] = rate;
else
ucontrol->value.integer.value[0] = 0;
rate = spdif_get_rxclk_rate(spdif_priv, SPDIF_DEFAULT_GAINSEL);
ucontrol->value.integer.value[0] = rate;
return 0;
}
......@@ -969,12 +975,14 @@ static int fsl_spdif_dai_probe(struct snd_soc_dai *dai)
static struct snd_soc_dai_driver fsl_spdif_dai = {
.probe = &fsl_spdif_dai_probe,
.playback = {
.stream_name = "CPU-Playback",
.channels_min = 2,
.channels_max = 2,
.rates = FSL_SPDIF_RATES_PLAYBACK,
.formats = FSL_SPDIF_FORMATS_PLAYBACK,
},
.capture = {
.stream_name = "CPU-Capture",
.channels_min = 2,
.channels_max = 2,
.rates = FSL_SPDIF_RATES_CAPTURE,
......@@ -1046,7 +1054,7 @@ static u32 fsl_spdif_txclk_caldiv(struct fsl_spdif_priv *spdif_priv,
struct clk *clk, u64 savesub,
enum spdif_txrate index, bool round)
{
const u32 rate[] = { 32000, 44100, 48000 };
const u32 rate[] = { 32000, 44100, 48000, 96000, 192000 };
bool is_sysclk = clk == spdif_priv->sysclk;
u64 rate_ideal, rate_actual, sub;
u32 sysclk_dfmin, sysclk_dfmax;
......@@ -1105,7 +1113,7 @@ static u32 fsl_spdif_txclk_caldiv(struct fsl_spdif_priv *spdif_priv,
static int fsl_spdif_probe_txclk(struct fsl_spdif_priv *spdif_priv,
enum spdif_txrate index)
{
const u32 rate[] = { 32000, 44100, 48000 };
const u32 rate[] = { 32000, 44100, 48000, 96000, 192000 };
struct platform_device *pdev = spdif_priv->pdev;
struct device *dev = &pdev->dev;
u64 savesub = 100000, ret;
......@@ -1238,12 +1246,12 @@ static int fsl_spdif_probe(struct platform_device *pdev)
spin_lock_init(&ctrl->ctl_lock);
/* Init tx channel status default value */
ctrl->ch_status[0] =
IEC958_AES0_CON_NOT_COPYRIGHT | IEC958_AES0_CON_EMPHASIS_5015;
ctrl->ch_status[0] = IEC958_AES0_CON_NOT_COPYRIGHT |
IEC958_AES0_CON_EMPHASIS_5015;
ctrl->ch_status[1] = IEC958_AES1_CON_DIGDIGCONV_ID;
ctrl->ch_status[2] = 0x00;
ctrl->ch_status[3] =
IEC958_AES3_CON_FS_44100 | IEC958_AES3_CON_CLOCK_1000PPM;
ctrl->ch_status[3] = IEC958_AES3_CON_FS_44100 |
IEC958_AES3_CON_CLOCK_1000PPM;
spdif_priv->dpll_locked = false;
......
......@@ -93,6 +93,8 @@
#define SCR_USRC_SEL_RECV (0x1 << SCR_USRC_SEL_OFFSET)
#define SCR_USRC_SEL_CHIP (0x3 << SCR_USRC_SEL_OFFSET)
#define SCR_DMA_xX_EN(tx) (tx ? SCR_DMA_TX_EN : SCR_DMA_RX_EN)
/* SPDIF CDText control */
#define SRCD_CD_USER_OFFSET 1
#define SRCD_CD_USER (1 << SRCD_CD_USER_OFFSET)
......@@ -164,8 +166,10 @@ enum spdif_txrate {
SPDIF_TXRATE_32000 = 0,
SPDIF_TXRATE_44100,
SPDIF_TXRATE_48000,
SPDIF_TXRATE_96000,
SPDIF_TXRATE_192000,
};
#define SPDIF_TXRATE_MAX (SPDIF_TXRATE_48000 + 1)
#define SPDIF_TXRATE_MAX (SPDIF_TXRATE_192000 + 1)
#define SPDIF_CSTATUS_BYTE 6
......@@ -175,7 +179,9 @@ enum spdif_txrate {
#define FSL_SPDIF_RATES_PLAYBACK (SNDRV_PCM_RATE_32000 | \
SNDRV_PCM_RATE_44100 | \
SNDRV_PCM_RATE_48000)
SNDRV_PCM_RATE_48000 | \
SNDRV_PCM_RATE_96000 | \
SNDRV_PCM_RATE_192000)
#define FSL_SPDIF_RATES_CAPTURE (SNDRV_PCM_RATE_16000 | \
SNDRV_PCM_RATE_32000 | \
......
......@@ -1032,12 +1032,14 @@ static const struct snd_soc_dai_ops fsl_ssi_dai_ops = {
static struct snd_soc_dai_driver fsl_ssi_dai_template = {
.probe = fsl_ssi_dai_probe,
.playback = {
.stream_name = "CPU-Playback",
.channels_min = 1,
.channels_max = 2,
.rates = FSLSSI_I2S_RATES,
.formats = FSLSSI_I2S_FORMATS,
},
.capture = {
.stream_name = "CPU-Capture",
.channels_min = 1,
.channels_max = 2,
.rates = FSLSSI_I2S_RATES,
......
......@@ -67,7 +67,7 @@ static ssize_t audmux_read_file(struct file *file, char __user *user_buf,
{
ssize_t ret;
char *buf;
int port = (int)file->private_data;
uintptr_t port = (uintptr_t)file->private_data;
u32 pdcr, ptcr;
if (audmux_clk) {
......@@ -147,7 +147,7 @@ static const struct file_operations audmux_debugfs_fops = {
static void audmux_debugfs_init(void)
{
int i;
uintptr_t i;
char buf[20];
audmux_debugfs_root = debugfs_create_dir("audmux", NULL);
......@@ -157,10 +157,10 @@ static void audmux_debugfs_init(void)
}
for (i = 0; i < MX31_AUDMUX_PORT7_SSI_PINS_7 + 1; i++) {
snprintf(buf, sizeof(buf), "ssi%d", i);
snprintf(buf, sizeof(buf), "ssi%lu", i);
if (!debugfs_create_file(buf, 0444, audmux_debugfs_root,
(void *)i, &audmux_debugfs_fops))
pr_warning("Failed to create AUDMUX port %d debugfs file\n",
pr_warning("Failed to create AUDMUX port %lu debugfs file\n",
i);
}
}
......
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