0001
0002
0003
0004
0005
0006
0007
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
0092
0093
0094
0095
0096
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
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
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
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
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
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
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");