summaryrefslogtreecommitdiffstats
path: root/sound/soc/fsl/fsl_spdif.c
diff options
context:
space:
mode:
Diffstat (limited to 'sound/soc/fsl/fsl_spdif.c')
-rw-r--r--sound/soc/fsl/fsl_spdif.c73
1 files changed, 60 insertions, 13 deletions
diff --git a/sound/soc/fsl/fsl_spdif.c b/sound/soc/fsl/fsl_spdif.c
index b0f643fefe1e..5fa178f3f497 100644
--- a/sound/soc/fsl/fsl_spdif.c
+++ b/sound/soc/fsl/fsl_spdif.c
@@ -49,10 +49,18 @@ static u8 srpc_dpll_locked[] = { 0x0, 0x1, 0x2, 0x3, 0x4, 0xa, 0xb };
* @imx: for imx platform
* @shared_root_clock: flag of sharing a clock source with others;
* so the driver shouldn't set root clock rate
+ * @interrupts: interrupt number
+ * @tx_burst: tx maxburst size
+ * @rx_burst: rx maxburst size
+ * @tx_formats: tx supported data format
*/
struct fsl_spdif_soc_data {
bool imx;
bool shared_root_clock;
+ u32 interrupts;
+ u32 tx_burst;
+ u32 rx_burst;
+ u64 tx_formats;
};
/*
@@ -128,16 +136,38 @@ struct fsl_spdif_priv {
static struct fsl_spdif_soc_data fsl_spdif_vf610 = {
.imx = false,
.shared_root_clock = false,
+ .interrupts = 1,
+ .tx_burst = FSL_SPDIF_TXFIFO_WML,
+ .rx_burst = FSL_SPDIF_RXFIFO_WML,
+ .tx_formats = FSL_SPDIF_FORMATS_PLAYBACK,
};
static struct fsl_spdif_soc_data fsl_spdif_imx35 = {
.imx = true,
.shared_root_clock = false,
+ .interrupts = 1,
+ .tx_burst = FSL_SPDIF_TXFIFO_WML,
+ .rx_burst = FSL_SPDIF_RXFIFO_WML,
+ .tx_formats = FSL_SPDIF_FORMATS_PLAYBACK,
};
static struct fsl_spdif_soc_data fsl_spdif_imx6sx = {
.imx = true,
.shared_root_clock = true,
+ .interrupts = 1,
+ .tx_burst = FSL_SPDIF_TXFIFO_WML,
+ .rx_burst = FSL_SPDIF_RXFIFO_WML,
+ .tx_formats = FSL_SPDIF_FORMATS_PLAYBACK,
+
+};
+
+static struct fsl_spdif_soc_data fsl_spdif_imx8qm = {
+ .imx = true,
+ .shared_root_clock = true,
+ .interrupts = 2,
+ .tx_burst = 2, /* Applied for EDMA */
+ .rx_burst = 2, /* Applied for EDMA */
+ .tx_formats = SNDRV_PCM_FMTBIT_S24_LE, /* Applied for EDMA */
};
/* Check if clk is a root clock that does not share clock source with others */
@@ -429,10 +459,18 @@ static int spdif_set_sample_rate(struct snd_pcm_substream *substream,
rate = SPDIF_TXRATE_48000;
csfs = IEC958_AES3_CON_FS_48000;
break;
+ case 88200:
+ rate = SPDIF_TXRATE_88200;
+ csfs = IEC958_AES3_CON_FS_88200;
+ break;
case 96000:
rate = SPDIF_TXRATE_96000;
csfs = IEC958_AES3_CON_FS_96000;
break;
+ case 176400:
+ rate = SPDIF_TXRATE_176400;
+ csfs = IEC958_AES3_CON_FS_176400;
+ break;
case 192000:
rate = SPDIF_TXRATE_192000;
csfs = IEC958_AES3_CON_FS_192000;
@@ -827,7 +865,7 @@ static int fsl_spdif_rxrate_info(struct snd_kcontrol *kcontrol,
uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
uinfo->count = 1;
uinfo->value.integer.min = 16000;
- uinfo->value.integer.max = 96000;
+ uinfo->value.integer.max = 192000;
return 0;
}
@@ -1145,7 +1183,8 @@ static u32 fsl_spdif_txclk_caldiv(struct fsl_spdif_priv *spdif_priv,
struct clk *clk, u64 savesub,
enum spdif_txrate index, bool round)
{
- static const u32 rate[] = { 32000, 44100, 48000, 96000, 192000 };
+ static const u32 rate[] = { 32000, 44100, 48000, 88200, 96000, 176400,
+ 192000, };
bool is_sysclk = clk_is_match(clk, spdif_priv->sysclk);
u64 rate_ideal, rate_actual, sub;
u32 arate;
@@ -1205,7 +1244,8 @@ out:
static int fsl_spdif_probe_txclk(struct fsl_spdif_priv *spdif_priv,
enum spdif_txrate index)
{
- static const u32 rate[] = { 32000, 44100, 48000, 96000, 192000 };
+ static const u32 rate[] = { 32000, 44100, 48000, 88200, 96000, 176400,
+ 192000, };
struct platform_device *pdev = spdif_priv->pdev;
struct device *dev = &pdev->dev;
u64 savesub = 100000, ret;
@@ -1273,6 +1313,8 @@ static int fsl_spdif_probe(struct platform_device *pdev)
/* Initialize this copy of the CPU DAI driver structure */
memcpy(&spdif_priv->cpu_dai_drv, &fsl_spdif_dai, sizeof(fsl_spdif_dai));
spdif_priv->cpu_dai_drv.name = dev_name(&pdev->dev);
+ spdif_priv->cpu_dai_drv.playback.formats =
+ spdif_priv->soc->tx_formats;
/* Get the addresses and IRQ */
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
@@ -1287,15 +1329,19 @@ static int fsl_spdif_probe(struct platform_device *pdev)
return PTR_ERR(spdif_priv->regmap);
}
- irq = platform_get_irq(pdev, 0);
- if (irq < 0)
- return irq;
+ for (i = 0; i < spdif_priv->soc->interrupts; i++) {
+ irq = platform_get_irq(pdev, i);
+ if (irq < 0) {
+ dev_err(&pdev->dev, "no irq for node %s\n", pdev->name);
+ return irq;
+ }
- ret = devm_request_irq(&pdev->dev, irq, spdif_isr, 0,
- dev_name(&pdev->dev), spdif_priv);
- if (ret) {
- dev_err(&pdev->dev, "could not claim irq %u\n", irq);
- return ret;
+ ret = devm_request_irq(&pdev->dev, irq, spdif_isr, 0,
+ dev_name(&pdev->dev), spdif_priv);
+ if (ret) {
+ dev_err(&pdev->dev, "could not claim irq %u\n", irq);
+ return ret;
+ }
}
/* Get system clock for rx clock rate calculation */
@@ -1344,8 +1390,8 @@ static int fsl_spdif_probe(struct platform_device *pdev)
spdif_priv->dpll_locked = false;
- spdif_priv->dma_params_tx.maxburst = FSL_SPDIF_TXFIFO_WML;
- spdif_priv->dma_params_rx.maxburst = FSL_SPDIF_RXFIFO_WML;
+ spdif_priv->dma_params_tx.maxburst = spdif_priv->soc->tx_burst;
+ spdif_priv->dma_params_rx.maxburst = spdif_priv->soc->rx_burst;
spdif_priv->dma_params_tx.addr = res->start + REG_SPDIF_STL;
spdif_priv->dma_params_rx.addr = res->start + REG_SPDIF_SRL;
@@ -1458,6 +1504,7 @@ static const struct of_device_id fsl_spdif_dt_ids[] = {
{ .compatible = "fsl,imx35-spdif", .data = &fsl_spdif_imx35, },
{ .compatible = "fsl,vf610-spdif", .data = &fsl_spdif_vf610, },
{ .compatible = "fsl,imx6sx-spdif", .data = &fsl_spdif_imx6sx, },
+ { .compatible = "fsl,imx8qm-spdif", .data = &fsl_spdif_imx8qm, },
{}
};
MODULE_DEVICE_TABLE(of, fsl_spdif_dt_ids);