Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 //
0003 // Xilinx ASoC audio formatter support
0004 //
0005 // Copyright (C) 2018 Xilinx, Inc.
0006 //
0007 // Author: Maruthi Srinivas Bayyavarapu <maruthis@xilinx.com>
0008 
0009 #include <linux/clk.h>
0010 #include <linux/io.h>
0011 #include <linux/module.h>
0012 #include <linux/of_address.h>
0013 #include <linux/of_irq.h>
0014 #include <linux/sizes.h>
0015 
0016 #include <sound/asoundef.h>
0017 #include <sound/soc.h>
0018 #include <sound/pcm_params.h>
0019 
0020 #define DRV_NAME "xlnx_formatter_pcm"
0021 
0022 #define XLNX_S2MM_OFFSET    0
0023 #define XLNX_MM2S_OFFSET    0x100
0024 
0025 #define XLNX_AUD_CORE_CONFIG    0x4
0026 #define XLNX_AUD_CTRL       0x10
0027 #define XLNX_AUD_STS        0x14
0028 
0029 #define AUD_CTRL_RESET_MASK BIT(1)
0030 #define AUD_CFG_MM2S_MASK   BIT(15)
0031 #define AUD_CFG_S2MM_MASK   BIT(31)
0032 
0033 #define XLNX_AUD_FS_MULTIPLIER  0x18
0034 #define XLNX_AUD_PERIOD_CONFIG  0x1C
0035 #define XLNX_AUD_BUFF_ADDR_LSB  0x20
0036 #define XLNX_AUD_BUFF_ADDR_MSB  0x24
0037 #define XLNX_AUD_XFER_COUNT 0x28
0038 #define XLNX_AUD_CH_STS_START   0x2C
0039 #define XLNX_BYTES_PER_CH   0x44
0040 #define XLNX_AUD_ALIGN_BYTES    64
0041 
0042 #define AUD_STS_IOC_IRQ_MASK    BIT(31)
0043 #define AUD_STS_CH_STS_MASK BIT(29)
0044 #define AUD_CTRL_IOC_IRQ_MASK   BIT(13)
0045 #define AUD_CTRL_TOUT_IRQ_MASK  BIT(14)
0046 #define AUD_CTRL_DMA_EN_MASK    BIT(0)
0047 
0048 #define CFG_MM2S_CH_MASK    GENMASK(11, 8)
0049 #define CFG_MM2S_CH_SHIFT   8
0050 #define CFG_MM2S_XFER_MASK  GENMASK(14, 13)
0051 #define CFG_MM2S_XFER_SHIFT 13
0052 #define CFG_MM2S_PKG_MASK   BIT(12)
0053 
0054 #define CFG_S2MM_CH_MASK    GENMASK(27, 24)
0055 #define CFG_S2MM_CH_SHIFT   24
0056 #define CFG_S2MM_XFER_MASK  GENMASK(30, 29)
0057 #define CFG_S2MM_XFER_SHIFT 29
0058 #define CFG_S2MM_PKG_MASK   BIT(28)
0059 
0060 #define AUD_CTRL_DATA_WIDTH_SHIFT   16
0061 #define AUD_CTRL_ACTIVE_CH_SHIFT    19
0062 #define PERIOD_CFG_PERIODS_SHIFT    16
0063 
0064 #define PERIODS_MIN     2
0065 #define PERIODS_MAX     6
0066 #define PERIOD_BYTES_MIN    192
0067 #define PERIOD_BYTES_MAX    (50 * 1024)
0068 #define XLNX_PARAM_UNKNOWN  0
0069 
0070 enum bit_depth {
0071     BIT_DEPTH_8,
0072     BIT_DEPTH_16,
0073     BIT_DEPTH_20,
0074     BIT_DEPTH_24,
0075     BIT_DEPTH_32,
0076 };
0077 
0078 struct xlnx_pcm_drv_data {
0079     void __iomem *mmio;
0080     bool s2mm_presence;
0081     bool mm2s_presence;
0082     int s2mm_irq;
0083     int mm2s_irq;
0084     struct snd_pcm_substream *play_stream;
0085     struct snd_pcm_substream *capture_stream;
0086     struct clk *axi_clk;
0087     unsigned int sysclk;
0088 };
0089 
0090 /*
0091  * struct xlnx_pcm_stream_param - stream configuration
0092  * @mmio: base address offset
0093  * @interleaved: audio channels arrangement in buffer
0094  * @xfer_mode: data formatting mode during transfer
0095  * @ch_limit: Maximum channels supported
0096  * @buffer_size: stream ring buffer size
0097  */
0098 struct xlnx_pcm_stream_param {
0099     void __iomem *mmio;
0100     bool interleaved;
0101     u32 xfer_mode;
0102     u32 ch_limit;
0103     u64 buffer_size;
0104 };
0105 
0106 static const struct snd_pcm_hardware xlnx_pcm_hardware = {
0107     .info = SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_BLOCK_TRANSFER |
0108         SNDRV_PCM_INFO_BATCH | SNDRV_PCM_INFO_PAUSE |
0109         SNDRV_PCM_INFO_RESUME,
0110     .formats = SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_S16_LE |
0111            SNDRV_PCM_FMTBIT_S24_LE,
0112     .channels_min = 2,
0113     .channels_max = 2,
0114     .rates = SNDRV_PCM_RATE_8000_192000,
0115     .rate_min = 8000,
0116     .rate_max = 192000,
0117     .buffer_bytes_max = PERIODS_MAX * PERIOD_BYTES_MAX,
0118     .period_bytes_min = PERIOD_BYTES_MIN,
0119     .period_bytes_max = PERIOD_BYTES_MAX,
0120     .periods_min = PERIODS_MIN,
0121     .periods_max = PERIODS_MAX,
0122 };
0123 
0124 enum {
0125     AES_TO_AES,
0126     AES_TO_PCM,
0127     PCM_TO_PCM,
0128     PCM_TO_AES
0129 };
0130 
0131 static void xlnx_parse_aes_params(u32 chsts_reg1_val, u32 chsts_reg2_val,
0132                   struct device *dev)
0133 {
0134     u32 padded, srate, bit_depth, status[2];
0135 
0136     if (chsts_reg1_val & IEC958_AES0_PROFESSIONAL) {
0137         status[0] = chsts_reg1_val & 0xff;
0138         status[1] = (chsts_reg1_val >> 16) & 0xff;
0139 
0140         switch (status[0] & IEC958_AES0_PRO_FS) {
0141         case IEC958_AES0_PRO_FS_44100:
0142             srate = 44100;
0143             break;
0144         case IEC958_AES0_PRO_FS_48000:
0145             srate = 48000;
0146             break;
0147         case IEC958_AES0_PRO_FS_32000:
0148             srate = 32000;
0149             break;
0150         case IEC958_AES0_PRO_FS_NOTID:
0151         default:
0152             srate = XLNX_PARAM_UNKNOWN;
0153             break;
0154         }
0155 
0156         switch (status[1] & IEC958_AES2_PRO_SBITS) {
0157         case IEC958_AES2_PRO_WORDLEN_NOTID:
0158         case IEC958_AES2_PRO_SBITS_20:
0159             padded = 0;
0160             break;
0161         case IEC958_AES2_PRO_SBITS_24:
0162             padded = 4;
0163             break;
0164         default:
0165             bit_depth = XLNX_PARAM_UNKNOWN;
0166             goto log_params;
0167         }
0168 
0169         switch (status[1] & IEC958_AES2_PRO_WORDLEN) {
0170         case IEC958_AES2_PRO_WORDLEN_20_16:
0171             bit_depth = 16 + padded;
0172             break;
0173         case IEC958_AES2_PRO_WORDLEN_22_18:
0174             bit_depth = 18 + padded;
0175             break;
0176         case IEC958_AES2_PRO_WORDLEN_23_19:
0177             bit_depth = 19 + padded;
0178             break;
0179         case IEC958_AES2_PRO_WORDLEN_24_20:
0180             bit_depth = 20 + padded;
0181             break;
0182         case IEC958_AES2_PRO_WORDLEN_NOTID:
0183         default:
0184             bit_depth = XLNX_PARAM_UNKNOWN;
0185             break;
0186         }
0187 
0188     } else {
0189         status[0] = (chsts_reg1_val >> 24) & 0xff;
0190         status[1] = chsts_reg2_val & 0xff;
0191 
0192         switch (status[0] & IEC958_AES3_CON_FS) {
0193         case IEC958_AES3_CON_FS_44100:
0194             srate = 44100;
0195             break;
0196         case IEC958_AES3_CON_FS_48000:
0197             srate = 48000;
0198             break;
0199         case IEC958_AES3_CON_FS_32000:
0200             srate = 32000;
0201             break;
0202         default:
0203             srate = XLNX_PARAM_UNKNOWN;
0204             break;
0205         }
0206 
0207         if (status[1] & IEC958_AES4_CON_MAX_WORDLEN_24)
0208             padded = 4;
0209         else
0210             padded = 0;
0211 
0212         switch (status[1] & IEC958_AES4_CON_WORDLEN) {
0213         case IEC958_AES4_CON_WORDLEN_20_16:
0214             bit_depth = 16 + padded;
0215             break;
0216         case IEC958_AES4_CON_WORDLEN_22_18:
0217             bit_depth = 18 + padded;
0218             break;
0219         case IEC958_AES4_CON_WORDLEN_23_19:
0220             bit_depth = 19 + padded;
0221             break;
0222         case IEC958_AES4_CON_WORDLEN_24_20:
0223             bit_depth = 20 + padded;
0224             break;
0225         case IEC958_AES4_CON_WORDLEN_21_17:
0226             bit_depth = 17 + padded;
0227             break;
0228         case IEC958_AES4_CON_WORDLEN_NOTID:
0229         default:
0230             bit_depth = XLNX_PARAM_UNKNOWN;
0231             break;
0232         }
0233     }
0234 
0235 log_params:
0236     if (srate != XLNX_PARAM_UNKNOWN)
0237         dev_info(dev, "sample rate = %d\n", srate);
0238     else
0239         dev_info(dev, "sample rate = unknown\n");
0240 
0241     if (bit_depth != XLNX_PARAM_UNKNOWN)
0242         dev_info(dev, "bit_depth = %d\n", bit_depth);
0243     else
0244         dev_info(dev, "bit_depth = unknown\n");
0245 }
0246 
0247 static int xlnx_formatter_pcm_reset(void __iomem *mmio_base)
0248 {
0249     u32 val, retries = 0;
0250 
0251     val = readl(mmio_base + XLNX_AUD_CTRL);
0252     val |= AUD_CTRL_RESET_MASK;
0253     writel(val, mmio_base + XLNX_AUD_CTRL);
0254 
0255     val = readl(mmio_base + XLNX_AUD_CTRL);
0256     /* Poll for maximum timeout of approximately 100ms (1 * 100)*/
0257     while ((val & AUD_CTRL_RESET_MASK) && (retries < 100)) {
0258         mdelay(1);
0259         retries++;
0260         val = readl(mmio_base + XLNX_AUD_CTRL);
0261     }
0262     if (val & AUD_CTRL_RESET_MASK)
0263         return -ENODEV;
0264 
0265     return 0;
0266 }
0267 
0268 static void xlnx_formatter_disable_irqs(void __iomem *mmio_base, int stream)
0269 {
0270     u32 val;
0271 
0272     val = readl(mmio_base + XLNX_AUD_CTRL);
0273     val &= ~AUD_CTRL_IOC_IRQ_MASK;
0274     if (stream == SNDRV_PCM_STREAM_CAPTURE)
0275         val &= ~AUD_CTRL_TOUT_IRQ_MASK;
0276 
0277     writel(val, mmio_base + XLNX_AUD_CTRL);
0278 }
0279 
0280 static irqreturn_t xlnx_mm2s_irq_handler(int irq, void *arg)
0281 {
0282     u32 val;
0283     void __iomem *reg;
0284     struct device *dev = arg;
0285     struct xlnx_pcm_drv_data *adata = dev_get_drvdata(dev);
0286 
0287     reg = adata->mmio + XLNX_MM2S_OFFSET + XLNX_AUD_STS;
0288     val = readl(reg);
0289     if (val & AUD_STS_IOC_IRQ_MASK) {
0290         writel(val & AUD_STS_IOC_IRQ_MASK, reg);
0291         if (adata->play_stream)
0292             snd_pcm_period_elapsed(adata->play_stream);
0293         return IRQ_HANDLED;
0294     }
0295 
0296     return IRQ_NONE;
0297 }
0298 
0299 static irqreturn_t xlnx_s2mm_irq_handler(int irq, void *arg)
0300 {
0301     u32 val;
0302     void __iomem *reg;
0303     struct device *dev = arg;
0304     struct xlnx_pcm_drv_data *adata = dev_get_drvdata(dev);
0305 
0306     reg = adata->mmio + XLNX_S2MM_OFFSET + XLNX_AUD_STS;
0307     val = readl(reg);
0308     if (val & AUD_STS_IOC_IRQ_MASK) {
0309         writel(val & AUD_STS_IOC_IRQ_MASK, reg);
0310         if (adata->capture_stream)
0311             snd_pcm_period_elapsed(adata->capture_stream);
0312         return IRQ_HANDLED;
0313     }
0314 
0315     return IRQ_NONE;
0316 }
0317 
0318 static int xlnx_formatter_set_sysclk(struct snd_soc_component *component,
0319                      int clk_id, int source, unsigned int freq, int dir)
0320 {
0321     struct xlnx_pcm_drv_data *adata = dev_get_drvdata(component->dev);
0322 
0323     adata->sysclk = freq;
0324     return 0;
0325 }
0326 
0327 static int xlnx_formatter_pcm_open(struct snd_soc_component *component,
0328                    struct snd_pcm_substream *substream)
0329 {
0330     int err;
0331     u32 val, data_format_mode;
0332     u32 ch_count_mask, ch_count_shift, data_xfer_mode, data_xfer_shift;
0333     struct xlnx_pcm_stream_param *stream_data;
0334     struct snd_pcm_runtime *runtime = substream->runtime;
0335     struct xlnx_pcm_drv_data *adata = dev_get_drvdata(component->dev);
0336 
0337     if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK &&
0338         !adata->mm2s_presence)
0339         return -ENODEV;
0340     else if (substream->stream == SNDRV_PCM_STREAM_CAPTURE &&
0341          !adata->s2mm_presence)
0342         return -ENODEV;
0343 
0344     stream_data = kzalloc(sizeof(*stream_data), GFP_KERNEL);
0345     if (!stream_data)
0346         return -ENOMEM;
0347 
0348     if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
0349         ch_count_mask = CFG_MM2S_CH_MASK;
0350         ch_count_shift = CFG_MM2S_CH_SHIFT;
0351         data_xfer_mode = CFG_MM2S_XFER_MASK;
0352         data_xfer_shift = CFG_MM2S_XFER_SHIFT;
0353         data_format_mode = CFG_MM2S_PKG_MASK;
0354         stream_data->mmio = adata->mmio + XLNX_MM2S_OFFSET;
0355         adata->play_stream = substream;
0356 
0357     } else {
0358         ch_count_mask = CFG_S2MM_CH_MASK;
0359         ch_count_shift = CFG_S2MM_CH_SHIFT;
0360         data_xfer_mode = CFG_S2MM_XFER_MASK;
0361         data_xfer_shift = CFG_S2MM_XFER_SHIFT;
0362         data_format_mode = CFG_S2MM_PKG_MASK;
0363         stream_data->mmio = adata->mmio + XLNX_S2MM_OFFSET;
0364         adata->capture_stream = substream;
0365     }
0366 
0367     val = readl(adata->mmio + XLNX_AUD_CORE_CONFIG);
0368 
0369     if (!(val & data_format_mode))
0370         stream_data->interleaved = true;
0371 
0372     stream_data->xfer_mode = (val & data_xfer_mode) >> data_xfer_shift;
0373     stream_data->ch_limit = (val & ch_count_mask) >> ch_count_shift;
0374     dev_info(component->dev,
0375          "stream %d : format = %d mode = %d ch_limit = %d\n",
0376          substream->stream, stream_data->interleaved,
0377          stream_data->xfer_mode, stream_data->ch_limit);
0378 
0379     snd_soc_set_runtime_hwparams(substream, &xlnx_pcm_hardware);
0380     runtime->private_data = stream_data;
0381 
0382     /* Resize the period bytes as divisible by 64 */
0383     err = snd_pcm_hw_constraint_step(runtime, 0,
0384                      SNDRV_PCM_HW_PARAM_PERIOD_BYTES,
0385                      XLNX_AUD_ALIGN_BYTES);
0386     if (err) {
0387         dev_err(component->dev,
0388             "Unable to set constraint on period bytes\n");
0389         return err;
0390     }
0391 
0392     /* Resize the buffer bytes as divisible by 64 */
0393     err = snd_pcm_hw_constraint_step(runtime, 0,
0394                      SNDRV_PCM_HW_PARAM_BUFFER_BYTES,
0395                      XLNX_AUD_ALIGN_BYTES);
0396     if (err) {
0397         dev_err(component->dev,
0398             "Unable to set constraint on buffer bytes\n");
0399         return err;
0400     }
0401 
0402     /* Set periods as integer multiple */
0403     err = snd_pcm_hw_constraint_integer(runtime,
0404                         SNDRV_PCM_HW_PARAM_PERIODS);
0405     if (err < 0) {
0406         dev_err(component->dev,
0407             "Unable to set constraint on periods to be integer\n");
0408         return err;
0409     }
0410 
0411     /* enable DMA IOC irq */
0412     val = readl(stream_data->mmio + XLNX_AUD_CTRL);
0413     val |= AUD_CTRL_IOC_IRQ_MASK;
0414     writel(val, stream_data->mmio + XLNX_AUD_CTRL);
0415 
0416     return 0;
0417 }
0418 
0419 static int xlnx_formatter_pcm_close(struct snd_soc_component *component,
0420                     struct snd_pcm_substream *substream)
0421 {
0422     int ret;
0423     struct xlnx_pcm_stream_param *stream_data =
0424             substream->runtime->private_data;
0425 
0426     ret = xlnx_formatter_pcm_reset(stream_data->mmio);
0427     if (ret) {
0428         dev_err(component->dev, "audio formatter reset failed\n");
0429         goto err_reset;
0430     }
0431     xlnx_formatter_disable_irqs(stream_data->mmio, substream->stream);
0432 
0433 err_reset:
0434     kfree(stream_data);
0435     return 0;
0436 }
0437 
0438 static snd_pcm_uframes_t
0439 xlnx_formatter_pcm_pointer(struct snd_soc_component *component,
0440                struct snd_pcm_substream *substream)
0441 {
0442     u32 pos;
0443     struct snd_pcm_runtime *runtime = substream->runtime;
0444     struct xlnx_pcm_stream_param *stream_data = runtime->private_data;
0445 
0446     pos = readl(stream_data->mmio + XLNX_AUD_XFER_COUNT);
0447 
0448     if (pos >= stream_data->buffer_size)
0449         pos = 0;
0450 
0451     return bytes_to_frames(runtime, pos);
0452 }
0453 
0454 static int xlnx_formatter_pcm_hw_params(struct snd_soc_component *component,
0455                     struct snd_pcm_substream *substream,
0456                     struct snd_pcm_hw_params *params)
0457 {
0458     u32 low, high, active_ch, val, bytes_per_ch, bits_per_sample;
0459     u32 aes_reg1_val, aes_reg2_val;
0460     u64 size;
0461     struct snd_pcm_runtime *runtime = substream->runtime;
0462     struct xlnx_pcm_stream_param *stream_data = runtime->private_data;
0463     struct xlnx_pcm_drv_data *adata = dev_get_drvdata(component->dev);
0464 
0465     active_ch = params_channels(params);
0466     if (active_ch > stream_data->ch_limit)
0467         return -EINVAL;
0468 
0469     if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK &&
0470         adata->sysclk) {
0471         unsigned int mclk_fs = adata->sysclk / params_rate(params);
0472 
0473         if (adata->sysclk % params_rate(params) != 0) {
0474             dev_warn(component->dev, "sysclk %u not divisible by rate %u\n",
0475                  adata->sysclk, params_rate(params));
0476             return -EINVAL;
0477         }
0478 
0479         writel(mclk_fs, stream_data->mmio + XLNX_AUD_FS_MULTIPLIER);
0480     }
0481 
0482     if (substream->stream == SNDRV_PCM_STREAM_CAPTURE &&
0483         stream_data->xfer_mode == AES_TO_PCM) {
0484         val = readl(stream_data->mmio + XLNX_AUD_STS);
0485         if (val & AUD_STS_CH_STS_MASK) {
0486             aes_reg1_val = readl(stream_data->mmio +
0487                          XLNX_AUD_CH_STS_START);
0488             aes_reg2_val = readl(stream_data->mmio +
0489                          XLNX_AUD_CH_STS_START + 0x4);
0490 
0491             xlnx_parse_aes_params(aes_reg1_val, aes_reg2_val,
0492                           component->dev);
0493         }
0494     }
0495 
0496     size = params_buffer_bytes(params);
0497 
0498     stream_data->buffer_size = size;
0499 
0500     low = lower_32_bits(runtime->dma_addr);
0501     high = upper_32_bits(runtime->dma_addr);
0502     writel(low, stream_data->mmio + XLNX_AUD_BUFF_ADDR_LSB);
0503     writel(high, stream_data->mmio + XLNX_AUD_BUFF_ADDR_MSB);
0504 
0505     val = readl(stream_data->mmio + XLNX_AUD_CTRL);
0506     bits_per_sample = params_width(params);
0507     switch (bits_per_sample) {
0508     case 8:
0509         val |= (BIT_DEPTH_8 << AUD_CTRL_DATA_WIDTH_SHIFT);
0510         break;
0511     case 16:
0512         val |= (BIT_DEPTH_16 << AUD_CTRL_DATA_WIDTH_SHIFT);
0513         break;
0514     case 20:
0515         val |= (BIT_DEPTH_20 << AUD_CTRL_DATA_WIDTH_SHIFT);
0516         break;
0517     case 24:
0518         val |= (BIT_DEPTH_24 << AUD_CTRL_DATA_WIDTH_SHIFT);
0519         break;
0520     case 32:
0521         val |= (BIT_DEPTH_32 << AUD_CTRL_DATA_WIDTH_SHIFT);
0522         break;
0523     default:
0524         return -EINVAL;
0525     }
0526 
0527     val |= active_ch << AUD_CTRL_ACTIVE_CH_SHIFT;
0528     writel(val, stream_data->mmio + XLNX_AUD_CTRL);
0529 
0530     val = (params_periods(params) << PERIOD_CFG_PERIODS_SHIFT)
0531         | params_period_bytes(params);
0532     writel(val, stream_data->mmio + XLNX_AUD_PERIOD_CONFIG);
0533     bytes_per_ch = DIV_ROUND_UP(params_period_bytes(params), active_ch);
0534     writel(bytes_per_ch, stream_data->mmio + XLNX_BYTES_PER_CH);
0535 
0536     return 0;
0537 }
0538 
0539 static int xlnx_formatter_pcm_trigger(struct snd_soc_component *component,
0540                       struct snd_pcm_substream *substream,
0541                       int cmd)
0542 {
0543     u32 val;
0544     struct xlnx_pcm_stream_param *stream_data =
0545             substream->runtime->private_data;
0546 
0547     switch (cmd) {
0548     case SNDRV_PCM_TRIGGER_START:
0549     case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
0550     case SNDRV_PCM_TRIGGER_RESUME:
0551         val = readl(stream_data->mmio + XLNX_AUD_CTRL);
0552         val |= AUD_CTRL_DMA_EN_MASK;
0553         writel(val, stream_data->mmio + XLNX_AUD_CTRL);
0554         break;
0555     case SNDRV_PCM_TRIGGER_STOP:
0556     case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
0557     case SNDRV_PCM_TRIGGER_SUSPEND:
0558         val = readl(stream_data->mmio + XLNX_AUD_CTRL);
0559         val &= ~AUD_CTRL_DMA_EN_MASK;
0560         writel(val, stream_data->mmio + XLNX_AUD_CTRL);
0561         break;
0562     }
0563 
0564     return 0;
0565 }
0566 
0567 static int xlnx_formatter_pcm_new(struct snd_soc_component *component,
0568                   struct snd_soc_pcm_runtime *rtd)
0569 {
0570     snd_pcm_set_managed_buffer_all(rtd->pcm,
0571             SNDRV_DMA_TYPE_DEV, component->dev,
0572             xlnx_pcm_hardware.buffer_bytes_max,
0573             xlnx_pcm_hardware.buffer_bytes_max);
0574     return 0;
0575 }
0576 
0577 static const struct snd_soc_component_driver xlnx_asoc_component = {
0578     .name           = DRV_NAME,
0579     .set_sysclk     = xlnx_formatter_set_sysclk,
0580     .open           = xlnx_formatter_pcm_open,
0581     .close          = xlnx_formatter_pcm_close,
0582     .hw_params      = xlnx_formatter_pcm_hw_params,
0583     .trigger        = xlnx_formatter_pcm_trigger,
0584     .pointer        = xlnx_formatter_pcm_pointer,
0585     .pcm_construct      = xlnx_formatter_pcm_new,
0586 };
0587 
0588 static int xlnx_formatter_pcm_probe(struct platform_device *pdev)
0589 {
0590     int ret;
0591     u32 val;
0592     struct xlnx_pcm_drv_data *aud_drv_data;
0593     struct device *dev = &pdev->dev;
0594 
0595     aud_drv_data = devm_kzalloc(dev, sizeof(*aud_drv_data), GFP_KERNEL);
0596     if (!aud_drv_data)
0597         return -ENOMEM;
0598 
0599     aud_drv_data->axi_clk = devm_clk_get(dev, "s_axi_lite_aclk");
0600     if (IS_ERR(aud_drv_data->axi_clk)) {
0601         ret = PTR_ERR(aud_drv_data->axi_clk);
0602         dev_err(dev, "failed to get s_axi_lite_aclk(%d)\n", ret);
0603         return ret;
0604     }
0605     ret = clk_prepare_enable(aud_drv_data->axi_clk);
0606     if (ret) {
0607         dev_err(dev,
0608             "failed to enable s_axi_lite_aclk(%d)\n", ret);
0609         return ret;
0610     }
0611 
0612     aud_drv_data->mmio = devm_platform_ioremap_resource(pdev, 0);
0613     if (IS_ERR(aud_drv_data->mmio)) {
0614         dev_err(dev, "audio formatter ioremap failed\n");
0615         ret = PTR_ERR(aud_drv_data->mmio);
0616         goto clk_err;
0617     }
0618 
0619     val = readl(aud_drv_data->mmio + XLNX_AUD_CORE_CONFIG);
0620     if (val & AUD_CFG_MM2S_MASK) {
0621         aud_drv_data->mm2s_presence = true;
0622         ret = xlnx_formatter_pcm_reset(aud_drv_data->mmio +
0623                            XLNX_MM2S_OFFSET);
0624         if (ret) {
0625             dev_err(dev, "audio formatter reset failed\n");
0626             goto clk_err;
0627         }
0628         xlnx_formatter_disable_irqs(aud_drv_data->mmio +
0629                         XLNX_MM2S_OFFSET,
0630                         SNDRV_PCM_STREAM_PLAYBACK);
0631 
0632         aud_drv_data->mm2s_irq = platform_get_irq_byname(pdev,
0633                                  "irq_mm2s");
0634         if (aud_drv_data->mm2s_irq < 0) {
0635             ret = aud_drv_data->mm2s_irq;
0636             goto clk_err;
0637         }
0638         ret = devm_request_irq(dev, aud_drv_data->mm2s_irq,
0639                        xlnx_mm2s_irq_handler, 0,
0640                        "xlnx_formatter_pcm_mm2s_irq", dev);
0641         if (ret) {
0642             dev_err(dev, "xlnx audio mm2s irq request failed\n");
0643             goto clk_err;
0644         }
0645     }
0646     if (val & AUD_CFG_S2MM_MASK) {
0647         aud_drv_data->s2mm_presence = true;
0648         ret = xlnx_formatter_pcm_reset(aud_drv_data->mmio +
0649                            XLNX_S2MM_OFFSET);
0650         if (ret) {
0651             dev_err(dev, "audio formatter reset failed\n");
0652             goto clk_err;
0653         }
0654         xlnx_formatter_disable_irqs(aud_drv_data->mmio +
0655                         XLNX_S2MM_OFFSET,
0656                         SNDRV_PCM_STREAM_CAPTURE);
0657 
0658         aud_drv_data->s2mm_irq = platform_get_irq_byname(pdev,
0659                                  "irq_s2mm");
0660         if (aud_drv_data->s2mm_irq < 0) {
0661             ret = aud_drv_data->s2mm_irq;
0662             goto clk_err;
0663         }
0664         ret = devm_request_irq(dev, aud_drv_data->s2mm_irq,
0665                        xlnx_s2mm_irq_handler, 0,
0666                        "xlnx_formatter_pcm_s2mm_irq",
0667                        dev);
0668         if (ret) {
0669             dev_err(dev, "xlnx audio s2mm irq request failed\n");
0670             goto clk_err;
0671         }
0672     }
0673 
0674     dev_set_drvdata(dev, aud_drv_data);
0675 
0676     ret = devm_snd_soc_register_component(dev, &xlnx_asoc_component,
0677                           NULL, 0);
0678     if (ret) {
0679         dev_err(dev, "pcm platform device register failed\n");
0680         goto clk_err;
0681     }
0682 
0683     return 0;
0684 
0685 clk_err:
0686     clk_disable_unprepare(aud_drv_data->axi_clk);
0687     return ret;
0688 }
0689 
0690 static int xlnx_formatter_pcm_remove(struct platform_device *pdev)
0691 {
0692     int ret = 0;
0693     struct xlnx_pcm_drv_data *adata = dev_get_drvdata(&pdev->dev);
0694 
0695     if (adata->s2mm_presence)
0696         ret = xlnx_formatter_pcm_reset(adata->mmio + XLNX_S2MM_OFFSET);
0697 
0698     /* Try MM2S reset, even if S2MM  reset fails */
0699     if (adata->mm2s_presence)
0700         ret = xlnx_formatter_pcm_reset(adata->mmio + XLNX_MM2S_OFFSET);
0701 
0702     if (ret)
0703         dev_err(&pdev->dev, "audio formatter reset failed\n");
0704 
0705     clk_disable_unprepare(adata->axi_clk);
0706     return 0;
0707 }
0708 
0709 static const struct of_device_id xlnx_formatter_pcm_of_match[] = {
0710     { .compatible = "xlnx,audio-formatter-1.0"},
0711     {},
0712 };
0713 MODULE_DEVICE_TABLE(of, xlnx_formatter_pcm_of_match);
0714 
0715 static struct platform_driver xlnx_formatter_pcm_driver = {
0716     .probe  = xlnx_formatter_pcm_probe,
0717     .remove = xlnx_formatter_pcm_remove,
0718     .driver = {
0719         .name   = DRV_NAME,
0720         .of_match_table = xlnx_formatter_pcm_of_match,
0721     },
0722 };
0723 
0724 module_platform_driver(xlnx_formatter_pcm_driver);
0725 MODULE_AUTHOR("Maruthi Srinivas Bayyavarapu <maruthis@xilinx.com>");
0726 MODULE_LICENSE("GPL v2");