root/sound/soc/xilinx/xlnx_formatter_pcm.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. xlnx_parse_aes_params
  2. xlnx_formatter_pcm_reset
  3. xlnx_formatter_disable_irqs
  4. xlnx_mm2s_irq_handler
  5. xlnx_s2mm_irq_handler
  6. xlnx_formatter_pcm_open
  7. xlnx_formatter_pcm_close
  8. xlnx_formatter_pcm_pointer
  9. xlnx_formatter_pcm_hw_params
  10. xlnx_formatter_pcm_hw_free
  11. xlnx_formatter_pcm_trigger
  12. xlnx_formatter_pcm_new
  13. xlnx_formatter_pcm_probe
  14. xlnx_formatter_pcm_remove

   1 // SPDX-License-Identifier: GPL-2.0
   2 //
   3 // Xilinx ASoC audio formatter support
   4 //
   5 // Copyright (C) 2018 Xilinx, Inc.
   6 //
   7 // Author: Maruthi Srinivas Bayyavarapu <maruthis@xilinx.com>
   8 
   9 #include <linux/clk.h>
  10 #include <linux/io.h>
  11 #include <linux/module.h>
  12 #include <linux/of_address.h>
  13 #include <linux/of_irq.h>
  14 #include <linux/sizes.h>
  15 
  16 #include <sound/asoundef.h>
  17 #include <sound/soc.h>
  18 #include <sound/pcm_params.h>
  19 
  20 #define DRV_NAME "xlnx_formatter_pcm"
  21 
  22 #define XLNX_S2MM_OFFSET        0
  23 #define XLNX_MM2S_OFFSET        0x100
  24 
  25 #define XLNX_AUD_CORE_CONFIG    0x4
  26 #define XLNX_AUD_CTRL           0x10
  27 #define XLNX_AUD_STS            0x14
  28 
  29 #define AUD_CTRL_RESET_MASK     BIT(1)
  30 #define AUD_CFG_MM2S_MASK       BIT(15)
  31 #define AUD_CFG_S2MM_MASK       BIT(31)
  32 
  33 #define XLNX_AUD_FS_MULTIPLIER  0x18
  34 #define XLNX_AUD_PERIOD_CONFIG  0x1C
  35 #define XLNX_AUD_BUFF_ADDR_LSB  0x20
  36 #define XLNX_AUD_BUFF_ADDR_MSB  0x24
  37 #define XLNX_AUD_XFER_COUNT     0x28
  38 #define XLNX_AUD_CH_STS_START   0x2C
  39 #define XLNX_BYTES_PER_CH       0x44
  40 
  41 #define AUD_STS_IOC_IRQ_MASK    BIT(31)
  42 #define AUD_STS_CH_STS_MASK     BIT(29)
  43 #define AUD_CTRL_IOC_IRQ_MASK   BIT(13)
  44 #define AUD_CTRL_TOUT_IRQ_MASK  BIT(14)
  45 #define AUD_CTRL_DMA_EN_MASK    BIT(0)
  46 
  47 #define CFG_MM2S_CH_MASK        GENMASK(11, 8)
  48 #define CFG_MM2S_CH_SHIFT       8
  49 #define CFG_MM2S_XFER_MASK      GENMASK(14, 13)
  50 #define CFG_MM2S_XFER_SHIFT     13
  51 #define CFG_MM2S_PKG_MASK       BIT(12)
  52 
  53 #define CFG_S2MM_CH_MASK        GENMASK(27, 24)
  54 #define CFG_S2MM_CH_SHIFT       24
  55 #define CFG_S2MM_XFER_MASK      GENMASK(30, 29)
  56 #define CFG_S2MM_XFER_SHIFT     29
  57 #define CFG_S2MM_PKG_MASK       BIT(28)
  58 
  59 #define AUD_CTRL_DATA_WIDTH_SHIFT       16
  60 #define AUD_CTRL_ACTIVE_CH_SHIFT        19
  61 #define PERIOD_CFG_PERIODS_SHIFT        16
  62 
  63 #define PERIODS_MIN             2
  64 #define PERIODS_MAX             6
  65 #define PERIOD_BYTES_MIN        192
  66 #define PERIOD_BYTES_MAX        (50 * 1024)
  67 #define XLNX_PARAM_UNKNOWN      0
  68 
  69 enum bit_depth {
  70         BIT_DEPTH_8,
  71         BIT_DEPTH_16,
  72         BIT_DEPTH_20,
  73         BIT_DEPTH_24,
  74         BIT_DEPTH_32,
  75 };
  76 
  77 struct xlnx_pcm_drv_data {
  78         void __iomem *mmio;
  79         bool s2mm_presence;
  80         bool mm2s_presence;
  81         int s2mm_irq;
  82         int mm2s_irq;
  83         struct snd_pcm_substream *play_stream;
  84         struct snd_pcm_substream *capture_stream;
  85         struct clk *axi_clk;
  86 };
  87 
  88 /*
  89  * struct xlnx_pcm_stream_param - stream configuration
  90  * @mmio: base address offset
  91  * @interleaved: audio channels arrangement in buffer
  92  * @xfer_mode: data formatting mode during transfer
  93  * @ch_limit: Maximum channels supported
  94  * @buffer_size: stream ring buffer size
  95  */
  96 struct xlnx_pcm_stream_param {
  97         void __iomem *mmio;
  98         bool interleaved;
  99         u32 xfer_mode;
 100         u32 ch_limit;
 101         u64 buffer_size;
 102 };
 103 
 104 static const struct snd_pcm_hardware xlnx_pcm_hardware = {
 105         .info = SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_BLOCK_TRANSFER |
 106                 SNDRV_PCM_INFO_BATCH | SNDRV_PCM_INFO_PAUSE |
 107                 SNDRV_PCM_INFO_RESUME,
 108         .formats = SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_S16_LE |
 109                    SNDRV_PCM_FMTBIT_S24_LE,
 110         .channels_min = 2,
 111         .channels_max = 2,
 112         .rates = SNDRV_PCM_RATE_8000_192000,
 113         .rate_min = 8000,
 114         .rate_max = 192000,
 115         .buffer_bytes_max = PERIODS_MAX * PERIOD_BYTES_MAX,
 116         .period_bytes_min = PERIOD_BYTES_MIN,
 117         .period_bytes_max = PERIOD_BYTES_MAX,
 118         .periods_min = PERIODS_MIN,
 119         .periods_max = PERIODS_MAX,
 120 };
 121 
 122 enum {
 123         AES_TO_AES,
 124         AES_TO_PCM,
 125         PCM_TO_PCM,
 126         PCM_TO_AES
 127 };
 128 
 129 static void xlnx_parse_aes_params(u32 chsts_reg1_val, u32 chsts_reg2_val,
 130                                   struct device *dev)
 131 {
 132         u32 padded, srate, bit_depth, status[2];
 133 
 134         if (chsts_reg1_val & IEC958_AES0_PROFESSIONAL) {
 135                 status[0] = chsts_reg1_val & 0xff;
 136                 status[1] = (chsts_reg1_val >> 16) & 0xff;
 137 
 138                 switch (status[0] & IEC958_AES0_PRO_FS) {
 139                 case IEC958_AES0_PRO_FS_44100:
 140                         srate = 44100;
 141                         break;
 142                 case IEC958_AES0_PRO_FS_48000:
 143                         srate = 48000;
 144                         break;
 145                 case IEC958_AES0_PRO_FS_32000:
 146                         srate = 32000;
 147                         break;
 148                 case IEC958_AES0_PRO_FS_NOTID:
 149                 default:
 150                         srate = XLNX_PARAM_UNKNOWN;
 151                         break;
 152                 }
 153 
 154                 switch (status[1] & IEC958_AES2_PRO_SBITS) {
 155                 case IEC958_AES2_PRO_WORDLEN_NOTID:
 156                 case IEC958_AES2_PRO_SBITS_20:
 157                         padded = 0;
 158                         break;
 159                 case IEC958_AES2_PRO_SBITS_24:
 160                         padded = 4;
 161                         break;
 162                 default:
 163                         bit_depth = XLNX_PARAM_UNKNOWN;
 164                         goto log_params;
 165                 }
 166 
 167                 switch (status[1] & IEC958_AES2_PRO_WORDLEN) {
 168                 case IEC958_AES2_PRO_WORDLEN_20_16:
 169                         bit_depth = 16 + padded;
 170                         break;
 171                 case IEC958_AES2_PRO_WORDLEN_22_18:
 172                         bit_depth = 18 + padded;
 173                         break;
 174                 case IEC958_AES2_PRO_WORDLEN_23_19:
 175                         bit_depth = 19 + padded;
 176                         break;
 177                 case IEC958_AES2_PRO_WORDLEN_24_20:
 178                         bit_depth = 20 + padded;
 179                         break;
 180                 case IEC958_AES2_PRO_WORDLEN_NOTID:
 181                 default:
 182                         bit_depth = XLNX_PARAM_UNKNOWN;
 183                         break;
 184                 }
 185 
 186         } else {
 187                 status[0] = (chsts_reg1_val >> 24) & 0xff;
 188                 status[1] = chsts_reg2_val & 0xff;
 189 
 190                 switch (status[0] & IEC958_AES3_CON_FS) {
 191                 case IEC958_AES3_CON_FS_44100:
 192                         srate = 44100;
 193                         break;
 194                 case IEC958_AES3_CON_FS_48000:
 195                         srate = 48000;
 196                         break;
 197                 case IEC958_AES3_CON_FS_32000:
 198                         srate = 32000;
 199                         break;
 200                 default:
 201                         srate = XLNX_PARAM_UNKNOWN;
 202                         break;
 203                 }
 204 
 205                 if (status[1] & IEC958_AES4_CON_MAX_WORDLEN_24)
 206                         padded = 4;
 207                 else
 208                         padded = 0;
 209 
 210                 switch (status[1] & IEC958_AES4_CON_WORDLEN) {
 211                 case IEC958_AES4_CON_WORDLEN_20_16:
 212                         bit_depth = 16 + padded;
 213                         break;
 214                 case IEC958_AES4_CON_WORDLEN_22_18:
 215                         bit_depth = 18 + padded;
 216                         break;
 217                 case IEC958_AES4_CON_WORDLEN_23_19:
 218                         bit_depth = 19 + padded;
 219                         break;
 220                 case IEC958_AES4_CON_WORDLEN_24_20:
 221                         bit_depth = 20 + padded;
 222                         break;
 223                 case IEC958_AES4_CON_WORDLEN_21_17:
 224                         bit_depth = 17 + padded;
 225                         break;
 226                 case IEC958_AES4_CON_WORDLEN_NOTID:
 227                 default:
 228                         bit_depth = XLNX_PARAM_UNKNOWN;
 229                         break;
 230                 }
 231         }
 232 
 233 log_params:
 234         if (srate != XLNX_PARAM_UNKNOWN)
 235                 dev_info(dev, "sample rate = %d\n", srate);
 236         else
 237                 dev_info(dev, "sample rate = unknown\n");
 238 
 239         if (bit_depth != XLNX_PARAM_UNKNOWN)
 240                 dev_info(dev, "bit_depth = %d\n", bit_depth);
 241         else
 242                 dev_info(dev, "bit_depth = unknown\n");
 243 }
 244 
 245 static int xlnx_formatter_pcm_reset(void __iomem *mmio_base)
 246 {
 247         u32 val, retries = 0;
 248 
 249         val = readl(mmio_base + XLNX_AUD_CTRL);
 250         val |= AUD_CTRL_RESET_MASK;
 251         writel(val, mmio_base + XLNX_AUD_CTRL);
 252 
 253         val = readl(mmio_base + XLNX_AUD_CTRL);
 254         /* Poll for maximum timeout of approximately 100ms (1 * 100)*/
 255         while ((val & AUD_CTRL_RESET_MASK) && (retries < 100)) {
 256                 mdelay(1);
 257                 retries++;
 258                 val = readl(mmio_base + XLNX_AUD_CTRL);
 259         }
 260         if (val & AUD_CTRL_RESET_MASK)
 261                 return -ENODEV;
 262 
 263         return 0;
 264 }
 265 
 266 static void xlnx_formatter_disable_irqs(void __iomem *mmio_base, int stream)
 267 {
 268         u32 val;
 269 
 270         val = readl(mmio_base + XLNX_AUD_CTRL);
 271         val &= ~AUD_CTRL_IOC_IRQ_MASK;
 272         if (stream == SNDRV_PCM_STREAM_CAPTURE)
 273                 val &= ~AUD_CTRL_TOUT_IRQ_MASK;
 274 
 275         writel(val, mmio_base + XLNX_AUD_CTRL);
 276 }
 277 
 278 static irqreturn_t xlnx_mm2s_irq_handler(int irq, void *arg)
 279 {
 280         u32 val;
 281         void __iomem *reg;
 282         struct device *dev = arg;
 283         struct xlnx_pcm_drv_data *adata = dev_get_drvdata(dev);
 284 
 285         reg = adata->mmio + XLNX_MM2S_OFFSET + XLNX_AUD_STS;
 286         val = readl(reg);
 287         if (val & AUD_STS_IOC_IRQ_MASK) {
 288                 writel(val & AUD_STS_IOC_IRQ_MASK, reg);
 289                 if (adata->play_stream)
 290                         snd_pcm_period_elapsed(adata->play_stream);
 291                 return IRQ_HANDLED;
 292         }
 293 
 294         return IRQ_NONE;
 295 }
 296 
 297 static irqreturn_t xlnx_s2mm_irq_handler(int irq, void *arg)
 298 {
 299         u32 val;
 300         void __iomem *reg;
 301         struct device *dev = arg;
 302         struct xlnx_pcm_drv_data *adata = dev_get_drvdata(dev);
 303 
 304         reg = adata->mmio + XLNX_S2MM_OFFSET + XLNX_AUD_STS;
 305         val = readl(reg);
 306         if (val & AUD_STS_IOC_IRQ_MASK) {
 307                 writel(val & AUD_STS_IOC_IRQ_MASK, reg);
 308                 if (adata->capture_stream)
 309                         snd_pcm_period_elapsed(adata->capture_stream);
 310                 return IRQ_HANDLED;
 311         }
 312 
 313         return IRQ_NONE;
 314 }
 315 
 316 static int xlnx_formatter_pcm_open(struct snd_pcm_substream *substream)
 317 {
 318         int err;
 319         u32 val, data_format_mode;
 320         u32 ch_count_mask, ch_count_shift, data_xfer_mode, data_xfer_shift;
 321         struct xlnx_pcm_stream_param *stream_data;
 322         struct snd_pcm_runtime *runtime = substream->runtime;
 323         struct snd_soc_pcm_runtime *prtd = substream->private_data;
 324         struct snd_soc_component *component = snd_soc_rtdcom_lookup(prtd,
 325                                                                     DRV_NAME);
 326         struct xlnx_pcm_drv_data *adata = dev_get_drvdata(component->dev);
 327 
 328         if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK &&
 329             !adata->mm2s_presence)
 330                 return -ENODEV;
 331         else if (substream->stream == SNDRV_PCM_STREAM_CAPTURE &&
 332                  !adata->s2mm_presence)
 333                 return -ENODEV;
 334 
 335         stream_data = kzalloc(sizeof(*stream_data), GFP_KERNEL);
 336         if (!stream_data)
 337                 return -ENOMEM;
 338 
 339         if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
 340                 ch_count_mask = CFG_MM2S_CH_MASK;
 341                 ch_count_shift = CFG_MM2S_CH_SHIFT;
 342                 data_xfer_mode = CFG_MM2S_XFER_MASK;
 343                 data_xfer_shift = CFG_MM2S_XFER_SHIFT;
 344                 data_format_mode = CFG_MM2S_PKG_MASK;
 345                 stream_data->mmio = adata->mmio + XLNX_MM2S_OFFSET;
 346                 adata->play_stream = substream;
 347 
 348         } else {
 349                 ch_count_mask = CFG_S2MM_CH_MASK;
 350                 ch_count_shift = CFG_S2MM_CH_SHIFT;
 351                 data_xfer_mode = CFG_S2MM_XFER_MASK;
 352                 data_xfer_shift = CFG_S2MM_XFER_SHIFT;
 353                 data_format_mode = CFG_S2MM_PKG_MASK;
 354                 stream_data->mmio = adata->mmio + XLNX_S2MM_OFFSET;
 355                 adata->capture_stream = substream;
 356         }
 357 
 358         val = readl(adata->mmio + XLNX_AUD_CORE_CONFIG);
 359 
 360         if (!(val & data_format_mode))
 361                 stream_data->interleaved = true;
 362 
 363         stream_data->xfer_mode = (val & data_xfer_mode) >> data_xfer_shift;
 364         stream_data->ch_limit = (val & ch_count_mask) >> ch_count_shift;
 365         dev_info(component->dev,
 366                  "stream %d : format = %d mode = %d ch_limit = %d\n",
 367                  substream->stream, stream_data->interleaved,
 368                  stream_data->xfer_mode, stream_data->ch_limit);
 369 
 370         snd_soc_set_runtime_hwparams(substream, &xlnx_pcm_hardware);
 371         runtime->private_data = stream_data;
 372 
 373         /* Resize the period size divisible by 64 */
 374         err = snd_pcm_hw_constraint_step(runtime, 0,
 375                                          SNDRV_PCM_HW_PARAM_PERIOD_BYTES, 64);
 376         if (err) {
 377                 dev_err(component->dev,
 378                         "unable to set constraint on period bytes\n");
 379                 return err;
 380         }
 381 
 382         /* enable DMA IOC irq */
 383         val = readl(stream_data->mmio + XLNX_AUD_CTRL);
 384         val |= AUD_CTRL_IOC_IRQ_MASK;
 385         writel(val, stream_data->mmio + XLNX_AUD_CTRL);
 386 
 387         return 0;
 388 }
 389 
 390 static int xlnx_formatter_pcm_close(struct snd_pcm_substream *substream)
 391 {
 392         int ret;
 393         struct xlnx_pcm_stream_param *stream_data =
 394                         substream->runtime->private_data;
 395         struct snd_soc_pcm_runtime *prtd = substream->private_data;
 396         struct snd_soc_component *component = snd_soc_rtdcom_lookup(prtd,
 397                                                                     DRV_NAME);
 398 
 399         ret = xlnx_formatter_pcm_reset(stream_data->mmio);
 400         if (ret) {
 401                 dev_err(component->dev, "audio formatter reset failed\n");
 402                 goto err_reset;
 403         }
 404         xlnx_formatter_disable_irqs(stream_data->mmio, substream->stream);
 405 
 406 err_reset:
 407         kfree(stream_data);
 408         return 0;
 409 }
 410 
 411 static snd_pcm_uframes_t
 412 xlnx_formatter_pcm_pointer(struct snd_pcm_substream *substream)
 413 {
 414         u32 pos;
 415         struct snd_pcm_runtime *runtime = substream->runtime;
 416         struct xlnx_pcm_stream_param *stream_data = runtime->private_data;
 417 
 418         pos = readl(stream_data->mmio + XLNX_AUD_XFER_COUNT);
 419 
 420         if (pos >= stream_data->buffer_size)
 421                 pos = 0;
 422 
 423         return bytes_to_frames(runtime, pos);
 424 }
 425 
 426 static int xlnx_formatter_pcm_hw_params(struct snd_pcm_substream *substream,
 427                                         struct snd_pcm_hw_params *params)
 428 {
 429         u32 low, high, active_ch, val, bytes_per_ch, bits_per_sample;
 430         u32 aes_reg1_val, aes_reg2_val;
 431         int status;
 432         u64 size;
 433         struct snd_soc_pcm_runtime *prtd = substream->private_data;
 434         struct snd_soc_component *component = snd_soc_rtdcom_lookup(prtd,
 435                                                                     DRV_NAME);
 436         struct snd_pcm_runtime *runtime = substream->runtime;
 437         struct xlnx_pcm_stream_param *stream_data = runtime->private_data;
 438 
 439         active_ch = params_channels(params);
 440         if (active_ch > stream_data->ch_limit)
 441                 return -EINVAL;
 442 
 443         if (substream->stream == SNDRV_PCM_STREAM_CAPTURE &&
 444             stream_data->xfer_mode == AES_TO_PCM) {
 445                 val = readl(stream_data->mmio + XLNX_AUD_STS);
 446                 if (val & AUD_STS_CH_STS_MASK) {
 447                         aes_reg1_val = readl(stream_data->mmio +
 448                                              XLNX_AUD_CH_STS_START);
 449                         aes_reg2_val = readl(stream_data->mmio +
 450                                              XLNX_AUD_CH_STS_START + 0x4);
 451 
 452                         xlnx_parse_aes_params(aes_reg1_val, aes_reg2_val,
 453                                               component->dev);
 454                 }
 455         }
 456 
 457         size = params_buffer_bytes(params);
 458         status = snd_pcm_lib_malloc_pages(substream, size);
 459         if (status < 0)
 460                 return status;
 461 
 462         stream_data->buffer_size = size;
 463 
 464         low = lower_32_bits(substream->dma_buffer.addr);
 465         high = upper_32_bits(substream->dma_buffer.addr);
 466         writel(low, stream_data->mmio + XLNX_AUD_BUFF_ADDR_LSB);
 467         writel(high, stream_data->mmio + XLNX_AUD_BUFF_ADDR_MSB);
 468 
 469         val = readl(stream_data->mmio + XLNX_AUD_CTRL);
 470         bits_per_sample = params_width(params);
 471         switch (bits_per_sample) {
 472         case 8:
 473                 val |= (BIT_DEPTH_8 << AUD_CTRL_DATA_WIDTH_SHIFT);
 474                 break;
 475         case 16:
 476                 val |= (BIT_DEPTH_16 << AUD_CTRL_DATA_WIDTH_SHIFT);
 477                 break;
 478         case 20:
 479                 val |= (BIT_DEPTH_20 << AUD_CTRL_DATA_WIDTH_SHIFT);
 480                 break;
 481         case 24:
 482                 val |= (BIT_DEPTH_24 << AUD_CTRL_DATA_WIDTH_SHIFT);
 483                 break;
 484         case 32:
 485                 val |= (BIT_DEPTH_32 << AUD_CTRL_DATA_WIDTH_SHIFT);
 486                 break;
 487         default:
 488                 return -EINVAL;
 489         }
 490 
 491         val |= active_ch << AUD_CTRL_ACTIVE_CH_SHIFT;
 492         writel(val, stream_data->mmio + XLNX_AUD_CTRL);
 493 
 494         val = (params_periods(params) << PERIOD_CFG_PERIODS_SHIFT)
 495                 | params_period_bytes(params);
 496         writel(val, stream_data->mmio + XLNX_AUD_PERIOD_CONFIG);
 497         bytes_per_ch = DIV_ROUND_UP(params_period_bytes(params), active_ch);
 498         writel(bytes_per_ch, stream_data->mmio + XLNX_BYTES_PER_CH);
 499 
 500         return 0;
 501 }
 502 
 503 static int xlnx_formatter_pcm_hw_free(struct snd_pcm_substream *substream)
 504 {
 505         return snd_pcm_lib_free_pages(substream);
 506 }
 507 
 508 static int xlnx_formatter_pcm_trigger(struct snd_pcm_substream *substream,
 509                                       int cmd)
 510 {
 511         u32 val;
 512         struct xlnx_pcm_stream_param *stream_data =
 513                         substream->runtime->private_data;
 514 
 515         switch (cmd) {
 516         case SNDRV_PCM_TRIGGER_START:
 517         case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
 518         case SNDRV_PCM_TRIGGER_RESUME:
 519                 val = readl(stream_data->mmio + XLNX_AUD_CTRL);
 520                 val |= AUD_CTRL_DMA_EN_MASK;
 521                 writel(val, stream_data->mmio + XLNX_AUD_CTRL);
 522                 break;
 523         case SNDRV_PCM_TRIGGER_STOP:
 524         case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
 525         case SNDRV_PCM_TRIGGER_SUSPEND:
 526                 val = readl(stream_data->mmio + XLNX_AUD_CTRL);
 527                 val &= ~AUD_CTRL_DMA_EN_MASK;
 528                 writel(val, stream_data->mmio + XLNX_AUD_CTRL);
 529                 break;
 530         }
 531 
 532         return 0;
 533 }
 534 
 535 static int xlnx_formatter_pcm_new(struct snd_soc_pcm_runtime *rtd)
 536 {
 537         struct snd_soc_component *component = snd_soc_rtdcom_lookup(rtd,
 538                                                                     DRV_NAME);
 539         snd_pcm_lib_preallocate_pages_for_all(rtd->pcm,
 540                         SNDRV_DMA_TYPE_DEV, component->dev,
 541                         xlnx_pcm_hardware.buffer_bytes_max,
 542                         xlnx_pcm_hardware.buffer_bytes_max);
 543         return 0;
 544 }
 545 
 546 static const struct snd_pcm_ops xlnx_formatter_pcm_ops = {
 547         .open = xlnx_formatter_pcm_open,
 548         .close = xlnx_formatter_pcm_close,
 549         .ioctl = snd_pcm_lib_ioctl,
 550         .hw_params = xlnx_formatter_pcm_hw_params,
 551         .hw_free = xlnx_formatter_pcm_hw_free,
 552         .trigger = xlnx_formatter_pcm_trigger,
 553         .pointer = xlnx_formatter_pcm_pointer,
 554 };
 555 
 556 static const struct snd_soc_component_driver xlnx_asoc_component = {
 557         .name = DRV_NAME,
 558         .ops = &xlnx_formatter_pcm_ops,
 559         .pcm_new = xlnx_formatter_pcm_new,
 560 };
 561 
 562 static int xlnx_formatter_pcm_probe(struct platform_device *pdev)
 563 {
 564         int ret;
 565         u32 val;
 566         struct xlnx_pcm_drv_data *aud_drv_data;
 567         struct resource *res;
 568         struct device *dev = &pdev->dev;
 569 
 570         aud_drv_data = devm_kzalloc(dev, sizeof(*aud_drv_data), GFP_KERNEL);
 571         if (!aud_drv_data)
 572                 return -ENOMEM;
 573 
 574         aud_drv_data->axi_clk = devm_clk_get(dev, "s_axi_lite_aclk");
 575         if (IS_ERR(aud_drv_data->axi_clk)) {
 576                 ret = PTR_ERR(aud_drv_data->axi_clk);
 577                 dev_err(dev, "failed to get s_axi_lite_aclk(%d)\n", ret);
 578                 return ret;
 579         }
 580         ret = clk_prepare_enable(aud_drv_data->axi_clk);
 581         if (ret) {
 582                 dev_err(dev,
 583                         "failed to enable s_axi_lite_aclk(%d)\n", ret);
 584                 return ret;
 585         }
 586 
 587         res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 588         if (!res) {
 589                 dev_err(dev, "audio formatter node:addr to resource failed\n");
 590                 ret = -ENXIO;
 591                 goto clk_err;
 592         }
 593         aud_drv_data->mmio = devm_ioremap_resource(dev, res);
 594         if (IS_ERR(aud_drv_data->mmio)) {
 595                 dev_err(dev, "audio formatter ioremap failed\n");
 596                 ret = PTR_ERR(aud_drv_data->mmio);
 597                 goto clk_err;
 598         }
 599 
 600         val = readl(aud_drv_data->mmio + XLNX_AUD_CORE_CONFIG);
 601         if (val & AUD_CFG_MM2S_MASK) {
 602                 aud_drv_data->mm2s_presence = true;
 603                 ret = xlnx_formatter_pcm_reset(aud_drv_data->mmio +
 604                                                XLNX_MM2S_OFFSET);
 605                 if (ret) {
 606                         dev_err(dev, "audio formatter reset failed\n");
 607                         goto clk_err;
 608                 }
 609                 xlnx_formatter_disable_irqs(aud_drv_data->mmio +
 610                                             XLNX_MM2S_OFFSET,
 611                                             SNDRV_PCM_STREAM_PLAYBACK);
 612 
 613                 aud_drv_data->mm2s_irq = platform_get_irq_byname(pdev,
 614                                                                  "irq_mm2s");
 615                 if (aud_drv_data->mm2s_irq < 0) {
 616                         ret = aud_drv_data->mm2s_irq;
 617                         goto clk_err;
 618                 }
 619                 ret = devm_request_irq(dev, aud_drv_data->mm2s_irq,
 620                                        xlnx_mm2s_irq_handler, 0,
 621                                        "xlnx_formatter_pcm_mm2s_irq", dev);
 622                 if (ret) {
 623                         dev_err(dev, "xlnx audio mm2s irq request failed\n");
 624                         goto clk_err;
 625                 }
 626         }
 627         if (val & AUD_CFG_S2MM_MASK) {
 628                 aud_drv_data->s2mm_presence = true;
 629                 ret = xlnx_formatter_pcm_reset(aud_drv_data->mmio +
 630                                                XLNX_S2MM_OFFSET);
 631                 if (ret) {
 632                         dev_err(dev, "audio formatter reset failed\n");
 633                         goto clk_err;
 634                 }
 635                 xlnx_formatter_disable_irqs(aud_drv_data->mmio +
 636                                             XLNX_S2MM_OFFSET,
 637                                             SNDRV_PCM_STREAM_CAPTURE);
 638 
 639                 aud_drv_data->s2mm_irq = platform_get_irq_byname(pdev,
 640                                                                  "irq_s2mm");
 641                 if (aud_drv_data->s2mm_irq < 0) {
 642                         ret = aud_drv_data->s2mm_irq;
 643                         goto clk_err;
 644                 }
 645                 ret = devm_request_irq(dev, aud_drv_data->s2mm_irq,
 646                                        xlnx_s2mm_irq_handler, 0,
 647                                        "xlnx_formatter_pcm_s2mm_irq",
 648                                        dev);
 649                 if (ret) {
 650                         dev_err(dev, "xlnx audio s2mm irq request failed\n");
 651                         goto clk_err;
 652                 }
 653         }
 654 
 655         dev_set_drvdata(dev, aud_drv_data);
 656 
 657         ret = devm_snd_soc_register_component(dev, &xlnx_asoc_component,
 658                                               NULL, 0);
 659         if (ret) {
 660                 dev_err(dev, "pcm platform device register failed\n");
 661                 goto clk_err;
 662         }
 663 
 664         return 0;
 665 
 666 clk_err:
 667         clk_disable_unprepare(aud_drv_data->axi_clk);
 668         return ret;
 669 }
 670 
 671 static int xlnx_formatter_pcm_remove(struct platform_device *pdev)
 672 {
 673         int ret = 0;
 674         struct xlnx_pcm_drv_data *adata = dev_get_drvdata(&pdev->dev);
 675 
 676         if (adata->s2mm_presence)
 677                 ret = xlnx_formatter_pcm_reset(adata->mmio + XLNX_S2MM_OFFSET);
 678 
 679         /* Try MM2S reset, even if S2MM  reset fails */
 680         if (adata->mm2s_presence)
 681                 ret = xlnx_formatter_pcm_reset(adata->mmio + XLNX_MM2S_OFFSET);
 682 
 683         if (ret)
 684                 dev_err(&pdev->dev, "audio formatter reset failed\n");
 685 
 686         clk_disable_unprepare(adata->axi_clk);
 687         return ret;
 688 }
 689 
 690 static const struct of_device_id xlnx_formatter_pcm_of_match[] = {
 691         { .compatible = "xlnx,audio-formatter-1.0"},
 692         {},
 693 };
 694 MODULE_DEVICE_TABLE(of, xlnx_formatter_pcm_of_match);
 695 
 696 static struct platform_driver xlnx_formatter_pcm_driver = {
 697         .probe  = xlnx_formatter_pcm_probe,
 698         .remove = xlnx_formatter_pcm_remove,
 699         .driver = {
 700                 .name   = DRV_NAME,
 701                 .of_match_table = xlnx_formatter_pcm_of_match,
 702         },
 703 };
 704 
 705 module_platform_driver(xlnx_formatter_pcm_driver);
 706 MODULE_AUTHOR("Maruthi Srinivas Bayyavarapu <maruthis@xilinx.com>");
 707 MODULE_LICENSE("GPL v2");

/* [<][>][^][v][top][bottom][index][help] */