0001
0002
0003
0004
0005
0006
0007
0008
0009
0010 #include <linux/clk.h>
0011 #include <linux/io.h>
0012 #include <linux/module.h>
0013 #include <linux/of.h>
0014 #include <linux/of_platform.h>
0015 #include <linux/platform_device.h>
0016 #include <sound/pcm_params.h>
0017 #include <sound/soc.h>
0018
0019 #define XLNX_SPDIF_RATES \
0020 (SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000 | \
0021 SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000 | SNDRV_PCM_RATE_176400 | \
0022 SNDRV_PCM_RATE_192000)
0023
0024 #define XLNX_SPDIF_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE)
0025
0026 #define XSPDIF_IRQ_STS_REG 0x20
0027 #define XSPDIF_IRQ_ENABLE_REG 0x28
0028 #define XSPDIF_SOFT_RESET_REG 0x40
0029 #define XSPDIF_CONTROL_REG 0x44
0030 #define XSPDIF_CHAN_0_STS_REG 0x4C
0031 #define XSPDIF_GLOBAL_IRQ_ENABLE_REG 0x1C
0032 #define XSPDIF_CH_A_USER_DATA_REG_0 0x64
0033
0034 #define XSPDIF_CORE_ENABLE_MASK BIT(0)
0035 #define XSPDIF_FIFO_FLUSH_MASK BIT(1)
0036 #define XSPDIF_CH_STS_MASK BIT(5)
0037 #define XSPDIF_GLOBAL_IRQ_ENABLE BIT(31)
0038 #define XSPDIF_CLOCK_CONFIG_BITS_MASK GENMASK(5, 2)
0039 #define XSPDIF_CLOCK_CONFIG_BITS_SHIFT 2
0040 #define XSPDIF_SOFT_RESET_VALUE 0xA
0041
0042 #define MAX_CHANNELS 2
0043 #define AES_SAMPLE_WIDTH 32
0044 #define CH_STATUS_UPDATE_TIMEOUT 40
0045
0046 struct spdif_dev_data {
0047 u32 mode;
0048 u32 aclk;
0049 bool rx_chsts_updated;
0050 void __iomem *base;
0051 struct clk *axi_clk;
0052 wait_queue_head_t chsts_q;
0053 };
0054
0055 static irqreturn_t xlnx_spdifrx_irq_handler(int irq, void *arg)
0056 {
0057 u32 val;
0058 struct spdif_dev_data *ctx = arg;
0059
0060 val = readl(ctx->base + XSPDIF_IRQ_STS_REG);
0061 if (val & XSPDIF_CH_STS_MASK) {
0062 writel(val & XSPDIF_CH_STS_MASK,
0063 ctx->base + XSPDIF_IRQ_STS_REG);
0064 val = readl(ctx->base +
0065 XSPDIF_IRQ_ENABLE_REG);
0066 writel(val & ~XSPDIF_CH_STS_MASK,
0067 ctx->base + XSPDIF_IRQ_ENABLE_REG);
0068
0069 ctx->rx_chsts_updated = true;
0070 wake_up_interruptible(&ctx->chsts_q);
0071 return IRQ_HANDLED;
0072 }
0073
0074 return IRQ_NONE;
0075 }
0076
0077 static int xlnx_spdif_startup(struct snd_pcm_substream *substream,
0078 struct snd_soc_dai *dai)
0079 {
0080 u32 val;
0081 struct spdif_dev_data *ctx = dev_get_drvdata(dai->dev);
0082
0083 val = readl(ctx->base + XSPDIF_CONTROL_REG);
0084 val |= XSPDIF_FIFO_FLUSH_MASK;
0085 writel(val, ctx->base + XSPDIF_CONTROL_REG);
0086
0087 if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) {
0088 writel(XSPDIF_CH_STS_MASK,
0089 ctx->base + XSPDIF_IRQ_ENABLE_REG);
0090 writel(XSPDIF_GLOBAL_IRQ_ENABLE,
0091 ctx->base + XSPDIF_GLOBAL_IRQ_ENABLE_REG);
0092 }
0093
0094 return 0;
0095 }
0096
0097 static void xlnx_spdif_shutdown(struct snd_pcm_substream *substream,
0098 struct snd_soc_dai *dai)
0099 {
0100 struct spdif_dev_data *ctx = dev_get_drvdata(dai->dev);
0101
0102 writel(XSPDIF_SOFT_RESET_VALUE, ctx->base + XSPDIF_SOFT_RESET_REG);
0103 }
0104
0105 static int xlnx_spdif_hw_params(struct snd_pcm_substream *substream,
0106 struct snd_pcm_hw_params *params,
0107 struct snd_soc_dai *dai)
0108 {
0109 u32 val, clk_div, clk_cfg;
0110 struct spdif_dev_data *ctx = dev_get_drvdata(dai->dev);
0111
0112 clk_div = DIV_ROUND_CLOSEST(ctx->aclk, MAX_CHANNELS * AES_SAMPLE_WIDTH *
0113 params_rate(params));
0114
0115 switch (clk_div) {
0116 case 4:
0117 clk_cfg = 0;
0118 break;
0119 case 8:
0120 clk_cfg = 1;
0121 break;
0122 case 16:
0123 clk_cfg = 2;
0124 break;
0125 case 24:
0126 clk_cfg = 3;
0127 break;
0128 case 32:
0129 clk_cfg = 4;
0130 break;
0131 case 48:
0132 clk_cfg = 5;
0133 break;
0134 case 64:
0135 clk_cfg = 6;
0136 break;
0137 default:
0138 return -EINVAL;
0139 }
0140
0141 val = readl(ctx->base + XSPDIF_CONTROL_REG);
0142 val &= ~XSPDIF_CLOCK_CONFIG_BITS_MASK;
0143 val |= clk_cfg << XSPDIF_CLOCK_CONFIG_BITS_SHIFT;
0144 writel(val, ctx->base + XSPDIF_CONTROL_REG);
0145
0146 return 0;
0147 }
0148
0149 static int rx_stream_detect(struct snd_soc_dai *dai)
0150 {
0151 int err;
0152 struct spdif_dev_data *ctx = dev_get_drvdata(dai->dev);
0153 unsigned long jiffies = msecs_to_jiffies(CH_STATUS_UPDATE_TIMEOUT);
0154
0155
0156 err = wait_event_interruptible_timeout(ctx->chsts_q,
0157 ctx->rx_chsts_updated,
0158 jiffies);
0159 if (!err) {
0160 dev_err(dai->dev, "No streaming audio detected!\n");
0161 return -EINVAL;
0162 }
0163 ctx->rx_chsts_updated = false;
0164
0165 return 0;
0166 }
0167
0168 static int xlnx_spdif_trigger(struct snd_pcm_substream *substream, int cmd,
0169 struct snd_soc_dai *dai)
0170 {
0171 u32 val;
0172 int ret = 0;
0173 struct spdif_dev_data *ctx = dev_get_drvdata(dai->dev);
0174
0175 val = readl(ctx->base + XSPDIF_CONTROL_REG);
0176 switch (cmd) {
0177 case SNDRV_PCM_TRIGGER_START:
0178 case SNDRV_PCM_TRIGGER_RESUME:
0179 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
0180 val |= XSPDIF_CORE_ENABLE_MASK;
0181 writel(val, ctx->base + XSPDIF_CONTROL_REG);
0182 if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)
0183 ret = rx_stream_detect(dai);
0184 break;
0185 case SNDRV_PCM_TRIGGER_STOP:
0186 case SNDRV_PCM_TRIGGER_SUSPEND:
0187 case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
0188 val &= ~XSPDIF_CORE_ENABLE_MASK;
0189 writel(val, ctx->base + XSPDIF_CONTROL_REG);
0190 break;
0191 default:
0192 ret = -EINVAL;
0193 }
0194
0195 return ret;
0196 }
0197
0198 static const struct snd_soc_dai_ops xlnx_spdif_dai_ops = {
0199 .startup = xlnx_spdif_startup,
0200 .shutdown = xlnx_spdif_shutdown,
0201 .trigger = xlnx_spdif_trigger,
0202 .hw_params = xlnx_spdif_hw_params,
0203 };
0204
0205 static struct snd_soc_dai_driver xlnx_spdif_tx_dai = {
0206 .name = "xlnx_spdif_tx",
0207 .playback = {
0208 .channels_min = 2,
0209 .channels_max = 2,
0210 .rates = XLNX_SPDIF_RATES,
0211 .formats = XLNX_SPDIF_FORMATS,
0212 },
0213 .ops = &xlnx_spdif_dai_ops,
0214 };
0215
0216 static struct snd_soc_dai_driver xlnx_spdif_rx_dai = {
0217 .name = "xlnx_spdif_rx",
0218 .capture = {
0219 .channels_min = 2,
0220 .channels_max = 2,
0221 .rates = XLNX_SPDIF_RATES,
0222 .formats = XLNX_SPDIF_FORMATS,
0223 },
0224 .ops = &xlnx_spdif_dai_ops,
0225 };
0226
0227 static const struct snd_soc_component_driver xlnx_spdif_component = {
0228 .name = "xlnx-spdif",
0229 .legacy_dai_naming = 1,
0230 };
0231
0232 static const struct of_device_id xlnx_spdif_of_match[] = {
0233 { .compatible = "xlnx,spdif-2.0", },
0234 {},
0235 };
0236 MODULE_DEVICE_TABLE(of, xlnx_spdif_of_match);
0237
0238 static int xlnx_spdif_probe(struct platform_device *pdev)
0239 {
0240 int ret;
0241 struct snd_soc_dai_driver *dai_drv;
0242 struct spdif_dev_data *ctx;
0243
0244 struct device *dev = &pdev->dev;
0245 struct device_node *node = dev->of_node;
0246
0247 ctx = devm_kzalloc(dev, sizeof(*ctx), GFP_KERNEL);
0248 if (!ctx)
0249 return -ENOMEM;
0250
0251 ctx->axi_clk = devm_clk_get(dev, "s_axi_aclk");
0252 if (IS_ERR(ctx->axi_clk)) {
0253 ret = PTR_ERR(ctx->axi_clk);
0254 dev_err(dev, "failed to get s_axi_aclk(%d)\n", ret);
0255 return ret;
0256 }
0257 ret = clk_prepare_enable(ctx->axi_clk);
0258 if (ret) {
0259 dev_err(dev, "failed to enable s_axi_aclk(%d)\n", ret);
0260 return ret;
0261 }
0262
0263 ctx->base = devm_platform_ioremap_resource(pdev, 0);
0264 if (IS_ERR(ctx->base)) {
0265 ret = PTR_ERR(ctx->base);
0266 goto clk_err;
0267 }
0268 ret = of_property_read_u32(node, "xlnx,spdif-mode", &ctx->mode);
0269 if (ret < 0) {
0270 dev_err(dev, "cannot get SPDIF mode\n");
0271 goto clk_err;
0272 }
0273 if (ctx->mode) {
0274 dai_drv = &xlnx_spdif_tx_dai;
0275 } else {
0276 ret = platform_get_irq(pdev, 0);
0277 if (ret < 0)
0278 goto clk_err;
0279 ret = devm_request_irq(dev, ret,
0280 xlnx_spdifrx_irq_handler,
0281 0, "XLNX_SPDIF_RX", ctx);
0282 if (ret) {
0283 dev_err(dev, "spdif rx irq request failed\n");
0284 ret = -ENODEV;
0285 goto clk_err;
0286 }
0287
0288 init_waitqueue_head(&ctx->chsts_q);
0289 dai_drv = &xlnx_spdif_rx_dai;
0290 }
0291
0292 ret = of_property_read_u32(node, "xlnx,aud_clk_i", &ctx->aclk);
0293 if (ret < 0) {
0294 dev_err(dev, "cannot get aud_clk_i value\n");
0295 goto clk_err;
0296 }
0297
0298 dev_set_drvdata(dev, ctx);
0299
0300 ret = devm_snd_soc_register_component(dev, &xlnx_spdif_component,
0301 dai_drv, 1);
0302 if (ret) {
0303 dev_err(dev, "SPDIF component registration failed\n");
0304 goto clk_err;
0305 }
0306
0307 writel(XSPDIF_SOFT_RESET_VALUE, ctx->base + XSPDIF_SOFT_RESET_REG);
0308 dev_info(dev, "%s DAI registered\n", dai_drv->name);
0309
0310 clk_err:
0311 clk_disable_unprepare(ctx->axi_clk);
0312 return ret;
0313 }
0314
0315 static int xlnx_spdif_remove(struct platform_device *pdev)
0316 {
0317 struct spdif_dev_data *ctx = dev_get_drvdata(&pdev->dev);
0318
0319 clk_disable_unprepare(ctx->axi_clk);
0320 return 0;
0321 }
0322
0323 static struct platform_driver xlnx_spdif_driver = {
0324 .driver = {
0325 .name = "xlnx-spdif",
0326 .of_match_table = xlnx_spdif_of_match,
0327 },
0328 .probe = xlnx_spdif_probe,
0329 .remove = xlnx_spdif_remove,
0330 };
0331 module_platform_driver(xlnx_spdif_driver);
0332
0333 MODULE_AUTHOR("Maruthi Srinivas Bayyavarapu <maruthis@xilinx.com>");
0334 MODULE_DESCRIPTION("XILINX SPDIF driver");
0335 MODULE_LICENSE("GPL v2");