linux/sound/soc/xilinx/xlnx_formatter_pcm.c
<<
>>
Prefs
   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
  69enum bit_depth {
  70        BIT_DEPTH_8,
  71        BIT_DEPTH_16,
  72        BIT_DEPTH_20,
  73        BIT_DEPTH_24,
  74        BIT_DEPTH_32,
  75};
  76
  77struct 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 */
  96struct 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
 104static 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
 122enum {
 123        AES_TO_AES,
 124        AES_TO_PCM,
 125        PCM_TO_PCM,
 126        PCM_TO_AES
 127};
 128
 129static 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
 233log_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
 245static 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
 266static 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
 278static 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
 297static 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
 316static 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
 390static 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
 406err_reset:
 407        kfree(stream_data);
 408        return 0;
 409}
 410
 411static snd_pcm_uframes_t
 412xlnx_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
 426static 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
 503static int xlnx_formatter_pcm_hw_free(struct snd_pcm_substream *substream)
 504{
 505        return snd_pcm_lib_free_pages(substream);
 506}
 507
 508static 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
 535static 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
 546static 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
 556static 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
 562static 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                        dev_err(dev, "xlnx audio mm2s irq resource failed\n");
 617                        ret = aud_drv_data->mm2s_irq;
 618                        goto clk_err;
 619                }
 620                ret = devm_request_irq(dev, aud_drv_data->mm2s_irq,
 621                                       xlnx_mm2s_irq_handler, 0,
 622                                       "xlnx_formatter_pcm_mm2s_irq", dev);
 623                if (ret) {
 624                        dev_err(dev, "xlnx audio mm2s irq request failed\n");
 625                        goto clk_err;
 626                }
 627        }
 628        if (val & AUD_CFG_S2MM_MASK) {
 629                aud_drv_data->s2mm_presence = true;
 630                ret = xlnx_formatter_pcm_reset(aud_drv_data->mmio +
 631                                               XLNX_S2MM_OFFSET);
 632                if (ret) {
 633                        dev_err(dev, "audio formatter reset failed\n");
 634                        goto clk_err;
 635                }
 636                xlnx_formatter_disable_irqs(aud_drv_data->mmio +
 637                                            XLNX_S2MM_OFFSET,
 638                                            SNDRV_PCM_STREAM_CAPTURE);
 639
 640                aud_drv_data->s2mm_irq = platform_get_irq_byname(pdev,
 641                                                                 "irq_s2mm");
 642                if (aud_drv_data->s2mm_irq < 0) {
 643                        dev_err(dev, "xlnx audio s2mm irq resource failed\n");
 644                        ret = aud_drv_data->s2mm_irq;
 645                        goto clk_err;
 646                }
 647                ret = devm_request_irq(dev, aud_drv_data->s2mm_irq,
 648                                       xlnx_s2mm_irq_handler, 0,
 649                                       "xlnx_formatter_pcm_s2mm_irq",
 650                                       dev);
 651                if (ret) {
 652                        dev_err(dev, "xlnx audio s2mm irq request failed\n");
 653                        goto clk_err;
 654                }
 655        }
 656
 657        dev_set_drvdata(dev, aud_drv_data);
 658
 659        ret = devm_snd_soc_register_component(dev, &xlnx_asoc_component,
 660                                              NULL, 0);
 661        if (ret) {
 662                dev_err(dev, "pcm platform device register failed\n");
 663                goto clk_err;
 664        }
 665
 666        return 0;
 667
 668clk_err:
 669        clk_disable_unprepare(aud_drv_data->axi_clk);
 670        return ret;
 671}
 672
 673static int xlnx_formatter_pcm_remove(struct platform_device *pdev)
 674{
 675        int ret = 0;
 676        struct xlnx_pcm_drv_data *adata = dev_get_drvdata(&pdev->dev);
 677
 678        if (adata->s2mm_presence)
 679                ret = xlnx_formatter_pcm_reset(adata->mmio + XLNX_S2MM_OFFSET);
 680
 681        /* Try MM2S reset, even if S2MM  reset fails */
 682        if (adata->mm2s_presence)
 683                ret = xlnx_formatter_pcm_reset(adata->mmio + XLNX_MM2S_OFFSET);
 684
 685        if (ret)
 686                dev_err(&pdev->dev, "audio formatter reset failed\n");
 687
 688        clk_disable_unprepare(adata->axi_clk);
 689        return ret;
 690}
 691
 692static const struct of_device_id xlnx_formatter_pcm_of_match[] = {
 693        { .compatible = "xlnx,audio-formatter-1.0"},
 694        {},
 695};
 696MODULE_DEVICE_TABLE(of, xlnx_formatter_pcm_of_match);
 697
 698static struct platform_driver xlnx_formatter_pcm_driver = {
 699        .probe  = xlnx_formatter_pcm_probe,
 700        .remove = xlnx_formatter_pcm_remove,
 701        .driver = {
 702                .name   = DRV_NAME,
 703                .of_match_table = xlnx_formatter_pcm_of_match,
 704        },
 705};
 706
 707module_platform_driver(xlnx_formatter_pcm_driver);
 708MODULE_AUTHOR("Maruthi Srinivas Bayyavarapu <maruthis@xilinx.com>");
 709MODULE_LICENSE("GPL v2");
 710