linux/sound/soc/amd/raven/acp3x-pcm-dma.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0+
   2//
   3// AMD ALSA SoC PCM Driver
   4//
   5//Copyright 2016 Advanced Micro Devices, Inc.
   6
   7#include <linux/platform_device.h>
   8#include <linux/module.h>
   9#include <linux/err.h>
  10#include <linux/io.h>
  11#include <linux/pm_runtime.h>
  12#include <sound/pcm_params.h>
  13#include <sound/soc.h>
  14#include <sound/soc-dai.h>
  15
  16#include "acp3x.h"
  17
  18#define DRV_NAME "acp3x_rv_i2s_dma"
  19
  20static const struct snd_pcm_hardware acp3x_pcm_hardware_playback = {
  21        .info = SNDRV_PCM_INFO_INTERLEAVED |
  22                SNDRV_PCM_INFO_BLOCK_TRANSFER |
  23                SNDRV_PCM_INFO_BATCH |
  24                SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_MMAP_VALID |
  25                SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_RESUME,
  26        .formats = SNDRV_PCM_FMTBIT_S16_LE |  SNDRV_PCM_FMTBIT_S8 |
  27                   SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S24_LE |
  28                   SNDRV_PCM_FMTBIT_S32_LE,
  29        .channels_min = 2,
  30        .channels_max = 8,
  31        .rates = SNDRV_PCM_RATE_8000_96000,
  32        .rate_min = 8000,
  33        .rate_max = 96000,
  34        .buffer_bytes_max = PLAYBACK_MAX_NUM_PERIODS * PLAYBACK_MAX_PERIOD_SIZE,
  35        .period_bytes_min = PLAYBACK_MIN_PERIOD_SIZE,
  36        .period_bytes_max = PLAYBACK_MAX_PERIOD_SIZE,
  37        .periods_min = PLAYBACK_MIN_NUM_PERIODS,
  38        .periods_max = PLAYBACK_MAX_NUM_PERIODS,
  39};
  40
  41static const struct snd_pcm_hardware acp3x_pcm_hardware_capture = {
  42        .info = SNDRV_PCM_INFO_INTERLEAVED |
  43                SNDRV_PCM_INFO_BLOCK_TRANSFER |
  44                SNDRV_PCM_INFO_BATCH |
  45                SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_MMAP_VALID |
  46                SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_RESUME,
  47        .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S8 |
  48                   SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S24_LE |
  49                   SNDRV_PCM_FMTBIT_S32_LE,
  50        .channels_min = 2,
  51        .channels_max = 2,
  52        .rates = SNDRV_PCM_RATE_8000_48000,
  53        .rate_min = 8000,
  54        .rate_max = 48000,
  55        .buffer_bytes_max = CAPTURE_MAX_NUM_PERIODS * CAPTURE_MAX_PERIOD_SIZE,
  56        .period_bytes_min = CAPTURE_MIN_PERIOD_SIZE,
  57        .period_bytes_max = CAPTURE_MAX_PERIOD_SIZE,
  58        .periods_min = CAPTURE_MIN_NUM_PERIODS,
  59        .periods_max = CAPTURE_MAX_NUM_PERIODS,
  60};
  61
  62static irqreturn_t i2s_irq_handler(int irq, void *dev_id)
  63{
  64        struct i2s_dev_data *rv_i2s_data;
  65        u16 play_flag, cap_flag;
  66        u32 val;
  67
  68        rv_i2s_data = dev_id;
  69        if (!rv_i2s_data)
  70                return IRQ_NONE;
  71
  72        play_flag = 0;
  73        cap_flag = 0;
  74        val = rv_readl(rv_i2s_data->acp3x_base + mmACP_EXTERNAL_INTR_STAT);
  75        if ((val & BIT(BT_TX_THRESHOLD)) && rv_i2s_data->play_stream) {
  76                rv_writel(BIT(BT_TX_THRESHOLD), rv_i2s_data->acp3x_base +
  77                          mmACP_EXTERNAL_INTR_STAT);
  78                snd_pcm_period_elapsed(rv_i2s_data->play_stream);
  79                play_flag = 1;
  80        }
  81        if ((val & BIT(I2S_TX_THRESHOLD)) &&
  82                                rv_i2s_data->i2ssp_play_stream) {
  83                rv_writel(BIT(I2S_TX_THRESHOLD),
  84                        rv_i2s_data->acp3x_base + mmACP_EXTERNAL_INTR_STAT);
  85                snd_pcm_period_elapsed(rv_i2s_data->i2ssp_play_stream);
  86                play_flag = 1;
  87        }
  88
  89        if ((val & BIT(BT_RX_THRESHOLD)) && rv_i2s_data->capture_stream) {
  90                rv_writel(BIT(BT_RX_THRESHOLD), rv_i2s_data->acp3x_base +
  91                          mmACP_EXTERNAL_INTR_STAT);
  92                snd_pcm_period_elapsed(rv_i2s_data->capture_stream);
  93                cap_flag = 1;
  94        }
  95        if ((val & BIT(I2S_RX_THRESHOLD)) &&
  96                                rv_i2s_data->i2ssp_capture_stream) {
  97                rv_writel(BIT(I2S_RX_THRESHOLD),
  98                         rv_i2s_data->acp3x_base + mmACP_EXTERNAL_INTR_STAT);
  99                snd_pcm_period_elapsed(rv_i2s_data->i2ssp_capture_stream);
 100                cap_flag = 1;
 101        }
 102
 103        if (play_flag | cap_flag)
 104                return IRQ_HANDLED;
 105        else
 106                return IRQ_NONE;
 107}
 108
 109static void config_acp3x_dma(struct i2s_stream_instance *rtd, int direction)
 110{
 111        u16 page_idx;
 112        u32 low, high, val, acp_fifo_addr, reg_fifo_addr;
 113        u32 reg_dma_size, reg_fifo_size;
 114        dma_addr_t addr;
 115
 116        addr = rtd->dma_addr;
 117
 118        if (direction == SNDRV_PCM_STREAM_PLAYBACK) {
 119                switch (rtd->i2s_instance) {
 120                case I2S_BT_INSTANCE:
 121                        val = ACP_SRAM_BT_PB_PTE_OFFSET;
 122                        break;
 123                case I2S_SP_INSTANCE:
 124                default:
 125                        val = ACP_SRAM_SP_PB_PTE_OFFSET;
 126                }
 127        } else {
 128                switch (rtd->i2s_instance) {
 129                case I2S_BT_INSTANCE:
 130                        val = ACP_SRAM_BT_CP_PTE_OFFSET;
 131                        break;
 132                case I2S_SP_INSTANCE:
 133                default:
 134                        val = ACP_SRAM_SP_CP_PTE_OFFSET;
 135                }
 136        }
 137        /* Group Enable */
 138        rv_writel(ACP_SRAM_PTE_OFFSET | BIT(31), rtd->acp3x_base +
 139                  mmACPAXI2AXI_ATU_BASE_ADDR_GRP_1);
 140        rv_writel(PAGE_SIZE_4K_ENABLE, rtd->acp3x_base +
 141                  mmACPAXI2AXI_ATU_PAGE_SIZE_GRP_1);
 142
 143        for (page_idx = 0; page_idx < rtd->num_pages; page_idx++) {
 144                /* Load the low address of page int ACP SRAM through SRBM */
 145                low = lower_32_bits(addr);
 146                high = upper_32_bits(addr);
 147
 148                rv_writel(low, rtd->acp3x_base + mmACP_SCRATCH_REG_0 + val);
 149                high |= BIT(31);
 150                rv_writel(high, rtd->acp3x_base + mmACP_SCRATCH_REG_0 + val
 151                                + 4);
 152                /* Move to next physically contiguos page */
 153                val += 8;
 154                addr += PAGE_SIZE;
 155        }
 156
 157        if (direction == SNDRV_PCM_STREAM_PLAYBACK) {
 158                switch (rtd->i2s_instance) {
 159                case I2S_BT_INSTANCE:
 160                        reg_dma_size = mmACP_BT_TX_DMA_SIZE;
 161                        acp_fifo_addr = ACP_SRAM_PTE_OFFSET +
 162                                                BT_PB_FIFO_ADDR_OFFSET;
 163                        reg_fifo_addr = mmACP_BT_TX_FIFOADDR;
 164                        reg_fifo_size = mmACP_BT_TX_FIFOSIZE;
 165                        rv_writel(I2S_BT_TX_MEM_WINDOW_START,
 166                                rtd->acp3x_base + mmACP_BT_TX_RINGBUFADDR);
 167                        break;
 168
 169                case I2S_SP_INSTANCE:
 170                default:
 171                        reg_dma_size = mmACP_I2S_TX_DMA_SIZE;
 172                        acp_fifo_addr = ACP_SRAM_PTE_OFFSET +
 173                                                SP_PB_FIFO_ADDR_OFFSET;
 174                        reg_fifo_addr = mmACP_I2S_TX_FIFOADDR;
 175                        reg_fifo_size = mmACP_I2S_TX_FIFOSIZE;
 176                        rv_writel(I2S_SP_TX_MEM_WINDOW_START,
 177                                rtd->acp3x_base + mmACP_I2S_TX_RINGBUFADDR);
 178                }
 179        } else {
 180                switch (rtd->i2s_instance) {
 181                case I2S_BT_INSTANCE:
 182                        reg_dma_size = mmACP_BT_RX_DMA_SIZE;
 183                        acp_fifo_addr = ACP_SRAM_PTE_OFFSET +
 184                                                BT_CAPT_FIFO_ADDR_OFFSET;
 185                        reg_fifo_addr = mmACP_BT_RX_FIFOADDR;
 186                        reg_fifo_size = mmACP_BT_RX_FIFOSIZE;
 187                        rv_writel(I2S_BT_RX_MEM_WINDOW_START,
 188                                rtd->acp3x_base + mmACP_BT_RX_RINGBUFADDR);
 189                        break;
 190
 191                case I2S_SP_INSTANCE:
 192                default:
 193                        reg_dma_size = mmACP_I2S_RX_DMA_SIZE;
 194                        acp_fifo_addr = ACP_SRAM_PTE_OFFSET +
 195                                                SP_CAPT_FIFO_ADDR_OFFSET;
 196                        reg_fifo_addr = mmACP_I2S_RX_FIFOADDR;
 197                        reg_fifo_size = mmACP_I2S_RX_FIFOSIZE;
 198                        rv_writel(I2S_SP_RX_MEM_WINDOW_START,
 199                                rtd->acp3x_base + mmACP_I2S_RX_RINGBUFADDR);
 200                }
 201        }
 202        rv_writel(DMA_SIZE, rtd->acp3x_base + reg_dma_size);
 203        rv_writel(acp_fifo_addr, rtd->acp3x_base + reg_fifo_addr);
 204        rv_writel(FIFO_SIZE, rtd->acp3x_base + reg_fifo_size);
 205        rv_writel(BIT(I2S_RX_THRESHOLD) | BIT(BT_RX_THRESHOLD)
 206                | BIT(I2S_TX_THRESHOLD) | BIT(BT_TX_THRESHOLD),
 207                rtd->acp3x_base + mmACP_EXTERNAL_INTR_CNTL);
 208}
 209
 210static int acp3x_dma_open(struct snd_soc_component *component,
 211                          struct snd_pcm_substream *substream)
 212{
 213        struct snd_pcm_runtime *runtime;
 214        struct snd_soc_pcm_runtime *prtd;
 215        struct i2s_dev_data *adata;
 216        struct i2s_stream_instance *i2s_data;
 217        int ret;
 218
 219        runtime = substream->runtime;
 220        prtd = asoc_substream_to_rtd(substream);
 221        component = snd_soc_rtdcom_lookup(prtd, DRV_NAME);
 222        adata = dev_get_drvdata(component->dev);
 223        i2s_data = kzalloc(sizeof(*i2s_data), GFP_KERNEL);
 224        if (!i2s_data)
 225                return -EINVAL;
 226
 227        if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
 228                runtime->hw = acp3x_pcm_hardware_playback;
 229        else
 230                runtime->hw = acp3x_pcm_hardware_capture;
 231
 232        ret = snd_pcm_hw_constraint_integer(runtime,
 233                                            SNDRV_PCM_HW_PARAM_PERIODS);
 234        if (ret < 0) {
 235                dev_err(component->dev, "set integer constraint failed\n");
 236                kfree(i2s_data);
 237                return ret;
 238        }
 239
 240        if (!adata->play_stream && !adata->capture_stream &&
 241            !adata->i2ssp_play_stream && !adata->i2ssp_capture_stream)
 242                rv_writel(1, adata->acp3x_base + mmACP_EXTERNAL_INTR_ENB);
 243
 244        i2s_data->acp3x_base = adata->acp3x_base;
 245        runtime->private_data = i2s_data;
 246        return ret;
 247}
 248
 249
 250static int acp3x_dma_hw_params(struct snd_soc_component *component,
 251                               struct snd_pcm_substream *substream,
 252                               struct snd_pcm_hw_params *params)
 253{
 254        struct i2s_stream_instance *rtd;
 255        struct snd_soc_pcm_runtime *prtd;
 256        struct snd_soc_card *card;
 257        struct acp3x_platform_info *pinfo;
 258        struct i2s_dev_data *adata;
 259        u64 size;
 260
 261        prtd = asoc_substream_to_rtd(substream);
 262        card = prtd->card;
 263        pinfo = snd_soc_card_get_drvdata(card);
 264        adata = dev_get_drvdata(component->dev);
 265        rtd = substream->runtime->private_data;
 266        if (!rtd)
 267                return -EINVAL;
 268
 269        if (pinfo) {
 270                if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
 271                        rtd->i2s_instance = pinfo->play_i2s_instance;
 272                        switch (rtd->i2s_instance) {
 273                        case I2S_BT_INSTANCE:
 274                                adata->play_stream = substream;
 275                                break;
 276                        case I2S_SP_INSTANCE:
 277                        default:
 278                                adata->i2ssp_play_stream = substream;
 279                        }
 280                } else {
 281                        rtd->i2s_instance = pinfo->cap_i2s_instance;
 282                        switch (rtd->i2s_instance) {
 283                        case I2S_BT_INSTANCE:
 284                                adata->capture_stream = substream;
 285                                break;
 286                        case I2S_SP_INSTANCE:
 287                        default:
 288                                adata->i2ssp_capture_stream = substream;
 289                        }
 290                }
 291        } else {
 292                pr_err("pinfo failed\n");
 293        }
 294        size = params_buffer_bytes(params);
 295        rtd->dma_addr = substream->dma_buffer.addr;
 296        rtd->num_pages = (PAGE_ALIGN(size) >> PAGE_SHIFT);
 297        config_acp3x_dma(rtd, substream->stream);
 298        return 0;
 299}
 300
 301static snd_pcm_uframes_t acp3x_dma_pointer(struct snd_soc_component *component,
 302                                           struct snd_pcm_substream *substream)
 303{
 304        struct i2s_stream_instance *rtd;
 305        u32 pos;
 306        u32 buffersize;
 307        u64 bytescount;
 308
 309        rtd = substream->runtime->private_data;
 310
 311        buffersize = frames_to_bytes(substream->runtime,
 312                                     substream->runtime->buffer_size);
 313        bytescount = acp_get_byte_count(rtd, substream->stream);
 314        if (bytescount > rtd->bytescount)
 315                bytescount -= rtd->bytescount;
 316        pos = do_div(bytescount, buffersize);
 317        return bytes_to_frames(substream->runtime, pos);
 318}
 319
 320static int acp3x_dma_new(struct snd_soc_component *component,
 321                         struct snd_soc_pcm_runtime *rtd)
 322{
 323        struct device *parent = component->dev->parent;
 324        snd_pcm_set_managed_buffer_all(rtd->pcm, SNDRV_DMA_TYPE_DEV,
 325                                       parent, MIN_BUFFER, MAX_BUFFER);
 326        return 0;
 327}
 328
 329static int acp3x_dma_mmap(struct snd_soc_component *component,
 330                          struct snd_pcm_substream *substream,
 331                          struct vm_area_struct *vma)
 332{
 333        return snd_pcm_lib_default_mmap(substream, vma);
 334}
 335
 336static int acp3x_dma_close(struct snd_soc_component *component,
 337                           struct snd_pcm_substream *substream)
 338{
 339        struct snd_soc_pcm_runtime *prtd;
 340        struct i2s_dev_data *adata;
 341        struct i2s_stream_instance *ins;
 342
 343        prtd = asoc_substream_to_rtd(substream);
 344        component = snd_soc_rtdcom_lookup(prtd, DRV_NAME);
 345        adata = dev_get_drvdata(component->dev);
 346        ins = substream->runtime->private_data;
 347        if (!ins)
 348                return -EINVAL;
 349
 350        if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
 351                switch (ins->i2s_instance) {
 352                case I2S_BT_INSTANCE:
 353                        adata->play_stream = NULL;
 354                        break;
 355                case I2S_SP_INSTANCE:
 356                default:
 357                        adata->i2ssp_play_stream = NULL;
 358                }
 359        } else {
 360                switch (ins->i2s_instance) {
 361                case I2S_BT_INSTANCE:
 362                        adata->capture_stream = NULL;
 363                        break;
 364                case I2S_SP_INSTANCE:
 365                default:
 366                        adata->i2ssp_capture_stream = NULL;
 367                }
 368        }
 369
 370        /* Disable ACP irq, when the current stream is being closed and
 371         * another stream is also not active.
 372         */
 373        if (!adata->play_stream && !adata->capture_stream &&
 374                !adata->i2ssp_play_stream && !adata->i2ssp_capture_stream)
 375                rv_writel(0, adata->acp3x_base + mmACP_EXTERNAL_INTR_ENB);
 376        return 0;
 377}
 378
 379static const struct snd_soc_component_driver acp3x_i2s_component = {
 380        .name           = DRV_NAME,
 381        .open           = acp3x_dma_open,
 382        .close          = acp3x_dma_close,
 383        .hw_params      = acp3x_dma_hw_params,
 384        .pointer        = acp3x_dma_pointer,
 385        .mmap           = acp3x_dma_mmap,
 386        .pcm_construct  = acp3x_dma_new,
 387};
 388
 389static int acp3x_audio_probe(struct platform_device *pdev)
 390{
 391        struct resource *res;
 392        struct i2s_dev_data *adata;
 393        unsigned int irqflags;
 394        int status;
 395
 396        if (!pdev->dev.platform_data) {
 397                dev_err(&pdev->dev, "platform_data not retrieved\n");
 398                return -ENODEV;
 399        }
 400        irqflags = *((unsigned int *)(pdev->dev.platform_data));
 401
 402        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 403        if (!res) {
 404                dev_err(&pdev->dev, "IORESOURCE_MEM FAILED\n");
 405                return -ENODEV;
 406        }
 407
 408        adata = devm_kzalloc(&pdev->dev, sizeof(*adata), GFP_KERNEL);
 409        if (!adata)
 410                return -ENOMEM;
 411
 412        adata->acp3x_base = devm_ioremap(&pdev->dev, res->start,
 413                                         resource_size(res));
 414        if (!adata->acp3x_base)
 415                return -ENOMEM;
 416
 417        res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
 418        if (!res) {
 419                dev_err(&pdev->dev, "IORESOURCE_IRQ FAILED\n");
 420                return -ENODEV;
 421        }
 422
 423        adata->i2s_irq = res->start;
 424
 425        dev_set_drvdata(&pdev->dev, adata);
 426        status = devm_snd_soc_register_component(&pdev->dev,
 427                                                 &acp3x_i2s_component,
 428                                                 NULL, 0);
 429        if (status) {
 430                dev_err(&pdev->dev, "Fail to register acp i2s component\n");
 431                return -ENODEV;
 432        }
 433        status = devm_request_irq(&pdev->dev, adata->i2s_irq, i2s_irq_handler,
 434                                  irqflags, "ACP3x_I2S_IRQ", adata);
 435        if (status) {
 436                dev_err(&pdev->dev, "ACP3x I2S IRQ request failed\n");
 437                return -ENODEV;
 438        }
 439
 440        pm_runtime_set_autosuspend_delay(&pdev->dev, 2000);
 441        pm_runtime_use_autosuspend(&pdev->dev);
 442        pm_runtime_enable(&pdev->dev);
 443        pm_runtime_allow(&pdev->dev);
 444        return 0;
 445}
 446
 447static int acp3x_audio_remove(struct platform_device *pdev)
 448{
 449        pm_runtime_disable(&pdev->dev);
 450        return 0;
 451}
 452
 453static int acp3x_resume(struct device *dev)
 454{
 455        struct i2s_dev_data *adata;
 456        u32 val, reg_val, frmt_val;
 457
 458        reg_val = 0;
 459        frmt_val = 0;
 460        adata = dev_get_drvdata(dev);
 461
 462        if (adata->play_stream && adata->play_stream->runtime) {
 463                struct i2s_stream_instance *rtd =
 464                        adata->play_stream->runtime->private_data;
 465                config_acp3x_dma(rtd, SNDRV_PCM_STREAM_PLAYBACK);
 466                switch (rtd->i2s_instance) {
 467                case I2S_BT_INSTANCE:
 468                        reg_val = mmACP_BTTDM_ITER;
 469                        frmt_val = mmACP_BTTDM_TXFRMT;
 470                        break;
 471                case I2S_SP_INSTANCE:
 472                default:
 473                        reg_val = mmACP_I2STDM_ITER;
 474                        frmt_val = mmACP_I2STDM_TXFRMT;
 475                }
 476                rv_writel((rtd->xfer_resolution  << 3),
 477                          rtd->acp3x_base + reg_val);
 478        }
 479        if (adata->capture_stream && adata->capture_stream->runtime) {
 480                struct i2s_stream_instance *rtd =
 481                        adata->capture_stream->runtime->private_data;
 482                config_acp3x_dma(rtd, SNDRV_PCM_STREAM_CAPTURE);
 483                switch (rtd->i2s_instance) {
 484                case I2S_BT_INSTANCE:
 485                        reg_val = mmACP_BTTDM_IRER;
 486                        frmt_val = mmACP_BTTDM_RXFRMT;
 487                        break;
 488                case I2S_SP_INSTANCE:
 489                default:
 490                        reg_val = mmACP_I2STDM_IRER;
 491                        frmt_val = mmACP_I2STDM_RXFRMT;
 492                }
 493                rv_writel((rtd->xfer_resolution  << 3),
 494                          rtd->acp3x_base + reg_val);
 495        }
 496        if (adata->tdm_mode == TDM_ENABLE) {
 497                rv_writel(adata->tdm_fmt, adata->acp3x_base + frmt_val);
 498                val = rv_readl(adata->acp3x_base + reg_val);
 499                rv_writel(val | 0x2, adata->acp3x_base + reg_val);
 500        }
 501        rv_writel(1, adata->acp3x_base + mmACP_EXTERNAL_INTR_ENB);
 502        return 0;
 503}
 504
 505
 506static int acp3x_pcm_runtime_suspend(struct device *dev)
 507{
 508        struct i2s_dev_data *adata;
 509
 510        adata = dev_get_drvdata(dev);
 511
 512        rv_writel(0, adata->acp3x_base + mmACP_EXTERNAL_INTR_ENB);
 513
 514        return 0;
 515}
 516
 517static int acp3x_pcm_runtime_resume(struct device *dev)
 518{
 519        struct i2s_dev_data *adata;
 520
 521        adata = dev_get_drvdata(dev);
 522
 523        rv_writel(1, adata->acp3x_base + mmACP_EXTERNAL_INTR_ENB);
 524        return 0;
 525}
 526
 527static const struct dev_pm_ops acp3x_pm_ops = {
 528        .runtime_suspend = acp3x_pcm_runtime_suspend,
 529        .runtime_resume = acp3x_pcm_runtime_resume,
 530        .resume = acp3x_resume,
 531};
 532
 533static struct platform_driver acp3x_dma_driver = {
 534        .probe = acp3x_audio_probe,
 535        .remove = acp3x_audio_remove,
 536        .driver = {
 537                .name = "acp3x_rv_i2s_dma",
 538                .pm = &acp3x_pm_ops,
 539        },
 540};
 541
 542module_platform_driver(acp3x_dma_driver);
 543
 544MODULE_AUTHOR("Vishnuvardhanrao.Ravulapati@amd.com");
 545MODULE_AUTHOR("Maruthi.Bayyavarapu@amd.com");
 546MODULE_AUTHOR("Vijendar.Mukunda@amd.com");
 547MODULE_DESCRIPTION("AMD ACP 3.x PCM Driver");
 548MODULE_LICENSE("GPL v2");
 549MODULE_ALIAS("platform:"DRV_NAME);
 550