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.h>
  13#include <sound/pcm_params.h>
  14#include <sound/soc.h>
  15#include <sound/soc-dai.h>
  16
  17#include "acp3x.h"
  18
  19#define DRV_NAME "acp3x-i2s-audio"
  20
  21struct i2s_dev_data {
  22        bool tdm_mode;
  23        unsigned int i2s_irq;
  24        u32 tdm_fmt;
  25        void __iomem *acp3x_base;
  26        struct snd_pcm_substream *play_stream;
  27        struct snd_pcm_substream *capture_stream;
  28};
  29
  30struct i2s_stream_instance {
  31        u16 num_pages;
  32        u16 channels;
  33        u32 xfer_resolution;
  34        u64 bytescount;
  35        dma_addr_t dma_addr;
  36        void __iomem *acp3x_base;
  37};
  38
  39static const struct snd_pcm_hardware acp3x_pcm_hardware_playback = {
  40        .info = SNDRV_PCM_INFO_INTERLEAVED |
  41                SNDRV_PCM_INFO_BLOCK_TRANSFER |
  42                SNDRV_PCM_INFO_BATCH |
  43                SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_RESUME,
  44        .formats = SNDRV_PCM_FMTBIT_S16_LE |  SNDRV_PCM_FMTBIT_S8 |
  45                   SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S24_LE |
  46                   SNDRV_PCM_FMTBIT_S32_LE,
  47        .channels_min = 2,
  48        .channels_max = 8,
  49        .rates = SNDRV_PCM_RATE_8000_96000,
  50        .rate_min = 8000,
  51        .rate_max = 96000,
  52        .buffer_bytes_max = PLAYBACK_MAX_NUM_PERIODS * PLAYBACK_MAX_PERIOD_SIZE,
  53        .period_bytes_min = PLAYBACK_MIN_PERIOD_SIZE,
  54        .period_bytes_max = PLAYBACK_MAX_PERIOD_SIZE,
  55        .periods_min = PLAYBACK_MIN_NUM_PERIODS,
  56        .periods_max = PLAYBACK_MAX_NUM_PERIODS,
  57};
  58
  59static const struct snd_pcm_hardware acp3x_pcm_hardware_capture = {
  60        .info = SNDRV_PCM_INFO_INTERLEAVED |
  61                SNDRV_PCM_INFO_BLOCK_TRANSFER |
  62                SNDRV_PCM_INFO_BATCH |
  63            SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_RESUME,
  64        .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S8 |
  65                   SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S24_LE |
  66                   SNDRV_PCM_FMTBIT_S32_LE,
  67        .channels_min = 2,
  68        .channels_max = 2,
  69        .rates = SNDRV_PCM_RATE_8000_48000,
  70        .rate_min = 8000,
  71        .rate_max = 48000,
  72        .buffer_bytes_max = CAPTURE_MAX_NUM_PERIODS * CAPTURE_MAX_PERIOD_SIZE,
  73        .period_bytes_min = CAPTURE_MIN_PERIOD_SIZE,
  74        .period_bytes_max = CAPTURE_MAX_PERIOD_SIZE,
  75        .periods_min = CAPTURE_MIN_NUM_PERIODS,
  76        .periods_max = CAPTURE_MAX_NUM_PERIODS,
  77};
  78
  79static int acp3x_power_on(void __iomem *acp3x_base, bool on)
  80{
  81        u16 val, mask;
  82        u32 timeout;
  83
  84        if (on == true) {
  85                val = 1;
  86                mask = ACP3x_POWER_ON;
  87        } else {
  88                val = 0;
  89                mask = ACP3x_POWER_OFF;
  90        }
  91
  92        rv_writel(val, acp3x_base + mmACP_PGFSM_CONTROL);
  93        timeout = 0;
  94        while (true) {
  95                val = rv_readl(acp3x_base + mmACP_PGFSM_STATUS);
  96                if ((val & ACP3x_POWER_OFF_IN_PROGRESS) == mask)
  97                        break;
  98                if (timeout > 100) {
  99                        pr_err("ACP3x power state change failure\n");
 100                        return -ENODEV;
 101                }
 102                timeout++;
 103                cpu_relax();
 104        }
 105        return 0;
 106}
 107
 108static int acp3x_reset(void __iomem *acp3x_base)
 109{
 110        u32 val, timeout;
 111
 112        rv_writel(1, acp3x_base + mmACP_SOFT_RESET);
 113        timeout = 0;
 114        while (true) {
 115                val = rv_readl(acp3x_base + mmACP_SOFT_RESET);
 116                if ((val & ACP3x_SOFT_RESET__SoftResetAudDone_MASK) ||
 117                     timeout > 100) {
 118                        if (val & ACP3x_SOFT_RESET__SoftResetAudDone_MASK)
 119                                break;
 120                        return -ENODEV;
 121                }
 122                timeout++;
 123                cpu_relax();
 124        }
 125
 126        rv_writel(0, acp3x_base + mmACP_SOFT_RESET);
 127        timeout = 0;
 128        while (true) {
 129                val = rv_readl(acp3x_base + mmACP_SOFT_RESET);
 130                if (!val || timeout > 100) {
 131                        if (!val)
 132                                break;
 133                        return -ENODEV;
 134                }
 135                timeout++;
 136                cpu_relax();
 137        }
 138        return 0;
 139}
 140
 141static int acp3x_init(void __iomem *acp3x_base)
 142{
 143        int ret;
 144
 145        /* power on */
 146        ret = acp3x_power_on(acp3x_base, true);
 147        if (ret) {
 148                pr_err("ACP3x power on failed\n");
 149                return ret;
 150        }
 151        /* Reset */
 152        ret = acp3x_reset(acp3x_base);
 153        if (ret) {
 154                pr_err("ACP3x reset failed\n");
 155                return ret;
 156        }
 157        return 0;
 158}
 159
 160static int acp3x_deinit(void __iomem *acp3x_base)
 161{
 162        int ret;
 163
 164        /* Reset */
 165        ret = acp3x_reset(acp3x_base);
 166        if (ret) {
 167                pr_err("ACP3x reset failed\n");
 168                return ret;
 169        }
 170        /* power off */
 171        ret = acp3x_power_on(acp3x_base, false);
 172        if (ret) {
 173                pr_err("ACP3x power off failed\n");
 174                return ret;
 175        }
 176        return 0;
 177}
 178
 179static irqreturn_t i2s_irq_handler(int irq, void *dev_id)
 180{
 181        u16 play_flag, cap_flag;
 182        u32 val;
 183        struct i2s_dev_data *rv_i2s_data = dev_id;
 184
 185        if (!rv_i2s_data)
 186                return IRQ_NONE;
 187
 188        play_flag = 0;
 189        cap_flag = 0;
 190        val = rv_readl(rv_i2s_data->acp3x_base + mmACP_EXTERNAL_INTR_STAT);
 191        if ((val & BIT(BT_TX_THRESHOLD)) && rv_i2s_data->play_stream) {
 192                rv_writel(BIT(BT_TX_THRESHOLD), rv_i2s_data->acp3x_base +
 193                          mmACP_EXTERNAL_INTR_STAT);
 194                snd_pcm_period_elapsed(rv_i2s_data->play_stream);
 195                play_flag = 1;
 196        }
 197
 198        if ((val & BIT(BT_RX_THRESHOLD)) && rv_i2s_data->capture_stream) {
 199                rv_writel(BIT(BT_RX_THRESHOLD), rv_i2s_data->acp3x_base +
 200                          mmACP_EXTERNAL_INTR_STAT);
 201                snd_pcm_period_elapsed(rv_i2s_data->capture_stream);
 202                cap_flag = 1;
 203        }
 204
 205        if (play_flag | cap_flag)
 206                return IRQ_HANDLED;
 207        else
 208                return IRQ_NONE;
 209}
 210
 211static void config_acp3x_dma(struct i2s_stream_instance *rtd, int direction)
 212{
 213        u16 page_idx;
 214        u32 low, high, val, acp_fifo_addr;
 215        dma_addr_t addr = rtd->dma_addr;
 216
 217        /* 8 scratch registers used to map one 64 bit address */
 218        if (direction == SNDRV_PCM_STREAM_PLAYBACK)
 219                val = 0;
 220        else
 221                val = rtd->num_pages * 8;
 222
 223        /* Group Enable */
 224        rv_writel(ACP_SRAM_PTE_OFFSET | BIT(31), rtd->acp3x_base +
 225                  mmACPAXI2AXI_ATU_BASE_ADDR_GRP_1);
 226        rv_writel(PAGE_SIZE_4K_ENABLE, rtd->acp3x_base +
 227                  mmACPAXI2AXI_ATU_PAGE_SIZE_GRP_1);
 228
 229        for (page_idx = 0; page_idx < rtd->num_pages; page_idx++) {
 230                /* Load the low address of page int ACP SRAM through SRBM */
 231                low = lower_32_bits(addr);
 232                high = upper_32_bits(addr);
 233
 234                rv_writel(low, rtd->acp3x_base + mmACP_SCRATCH_REG_0 + val);
 235                high |= BIT(31);
 236                rv_writel(high, rtd->acp3x_base + mmACP_SCRATCH_REG_0 + val
 237                                + 4);
 238                /* Move to next physically contiguos page */
 239                val += 8;
 240                addr += PAGE_SIZE;
 241        }
 242
 243        if (direction == SNDRV_PCM_STREAM_PLAYBACK) {
 244                /* Config ringbuffer */
 245                rv_writel(MEM_WINDOW_START, rtd->acp3x_base +
 246                          mmACP_BT_TX_RINGBUFADDR);
 247                rv_writel(MAX_BUFFER, rtd->acp3x_base +
 248                          mmACP_BT_TX_RINGBUFSIZE);
 249                rv_writel(DMA_SIZE, rtd->acp3x_base + mmACP_BT_TX_DMA_SIZE);
 250
 251                /* Config audio fifo */
 252                acp_fifo_addr = ACP_SRAM_PTE_OFFSET + (rtd->num_pages * 8)
 253                                + PLAYBACK_FIFO_ADDR_OFFSET;
 254                rv_writel(acp_fifo_addr, rtd->acp3x_base +
 255                          mmACP_BT_TX_FIFOADDR);
 256                rv_writel(FIFO_SIZE, rtd->acp3x_base + mmACP_BT_TX_FIFOSIZE);
 257        } else {
 258                /* Config ringbuffer */
 259                rv_writel(MEM_WINDOW_START + MAX_BUFFER, rtd->acp3x_base +
 260                          mmACP_BT_RX_RINGBUFADDR);
 261                rv_writel(MAX_BUFFER, rtd->acp3x_base +
 262                          mmACP_BT_RX_RINGBUFSIZE);
 263                rv_writel(DMA_SIZE, rtd->acp3x_base + mmACP_BT_RX_DMA_SIZE);
 264
 265                /* Config audio fifo */
 266                acp_fifo_addr = ACP_SRAM_PTE_OFFSET +
 267                                (rtd->num_pages * 8) + CAPTURE_FIFO_ADDR_OFFSET;
 268                rv_writel(acp_fifo_addr, rtd->acp3x_base +
 269                          mmACP_BT_RX_FIFOADDR);
 270                rv_writel(FIFO_SIZE, rtd->acp3x_base + mmACP_BT_RX_FIFOSIZE);
 271        }
 272
 273        /* Enable  watermark/period interrupt to host */
 274        rv_writel(BIT(BT_TX_THRESHOLD) | BIT(BT_RX_THRESHOLD),
 275                  rtd->acp3x_base + mmACP_EXTERNAL_INTR_CNTL);
 276}
 277
 278static int acp3x_dma_open(struct snd_pcm_substream *substream)
 279{
 280        int ret = 0;
 281
 282        struct snd_pcm_runtime *runtime = substream->runtime;
 283        struct snd_soc_pcm_runtime *prtd = substream->private_data;
 284        struct snd_soc_component *component = snd_soc_rtdcom_lookup(prtd,
 285                                                                    DRV_NAME);
 286        struct i2s_dev_data *adata = dev_get_drvdata(component->dev);
 287
 288        struct i2s_stream_instance *i2s_data = kzalloc(sizeof(struct i2s_stream_instance),
 289                                                       GFP_KERNEL);
 290        if (!i2s_data)
 291                return -EINVAL;
 292
 293        if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
 294                runtime->hw = acp3x_pcm_hardware_playback;
 295        else
 296                runtime->hw = acp3x_pcm_hardware_capture;
 297
 298        ret = snd_pcm_hw_constraint_integer(runtime,
 299                                            SNDRV_PCM_HW_PARAM_PERIODS);
 300        if (ret < 0) {
 301                dev_err(component->dev, "set integer constraint failed\n");
 302                kfree(i2s_data);
 303                return ret;
 304        }
 305
 306        if (!adata->play_stream && !adata->capture_stream)
 307                rv_writel(1, adata->acp3x_base + mmACP_EXTERNAL_INTR_ENB);
 308
 309        if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
 310                adata->play_stream = substream;
 311        else
 312                adata->capture_stream = substream;
 313
 314        i2s_data->acp3x_base = adata->acp3x_base;
 315        runtime->private_data = i2s_data;
 316        return 0;
 317}
 318
 319static u64 acp_get_byte_count(struct i2s_stream_instance *rtd, int direction)
 320{
 321        u64 byte_count;
 322
 323        if (direction == SNDRV_PCM_STREAM_PLAYBACK) {
 324                byte_count = rv_readl(rtd->acp3x_base +
 325                                      mmACP_BT_TX_LINEARPOSITIONCNTR_HIGH);
 326                byte_count |= rv_readl(rtd->acp3x_base +
 327                                       mmACP_BT_TX_LINEARPOSITIONCNTR_LOW);
 328        } else {
 329                byte_count = rv_readl(rtd->acp3x_base +
 330                                      mmACP_BT_RX_LINEARPOSITIONCNTR_HIGH);
 331                byte_count |= rv_readl(rtd->acp3x_base +
 332                                       mmACP_BT_RX_LINEARPOSITIONCNTR_LOW);
 333        }
 334        return byte_count;
 335}
 336
 337static int acp3x_dma_hw_params(struct snd_pcm_substream *substream,
 338                               struct snd_pcm_hw_params *params)
 339{
 340        int status;
 341        u64 size;
 342        struct snd_pcm_runtime *runtime = substream->runtime;
 343        struct i2s_stream_instance *rtd = runtime->private_data;
 344
 345        if (!rtd)
 346                return -EINVAL;
 347
 348        size = params_buffer_bytes(params);
 349        status = snd_pcm_lib_malloc_pages(substream, size);
 350        if (status < 0)
 351                return status;
 352
 353        memset(substream->runtime->dma_area, 0, params_buffer_bytes(params));
 354        if (substream->dma_buffer.area) {
 355                rtd->dma_addr = substream->dma_buffer.addr;
 356                rtd->num_pages = (PAGE_ALIGN(size) >> PAGE_SHIFT);
 357                config_acp3x_dma(rtd, substream->stream);
 358                status = 0;
 359        } else {
 360                status = -ENOMEM;
 361        }
 362        return status;
 363}
 364
 365static snd_pcm_uframes_t acp3x_dma_pointer(struct snd_pcm_substream *substream)
 366{
 367        u32 pos = 0;
 368        u32 buffersize = 0;
 369        u64 bytescount = 0;
 370        struct i2s_stream_instance *rtd =
 371                substream->runtime->private_data;
 372
 373        buffersize = frames_to_bytes(substream->runtime,
 374                                     substream->runtime->buffer_size);
 375        bytescount = acp_get_byte_count(rtd, substream->stream);
 376        if (bytescount > rtd->bytescount)
 377                bytescount -= rtd->bytescount;
 378        pos = do_div(bytescount, buffersize);
 379        return bytes_to_frames(substream->runtime, pos);
 380}
 381
 382static int acp3x_dma_new(struct snd_soc_pcm_runtime *rtd)
 383{
 384        struct snd_soc_component *component = snd_soc_rtdcom_lookup(rtd,
 385                                                                    DRV_NAME);
 386        struct device *parent = component->dev->parent;
 387        snd_pcm_lib_preallocate_pages_for_all(rtd->pcm, SNDRV_DMA_TYPE_DEV,
 388                                              parent, MIN_BUFFER, MAX_BUFFER);
 389        return 0;
 390}
 391
 392static int acp3x_dma_hw_free(struct snd_pcm_substream *substream)
 393{
 394        return snd_pcm_lib_free_pages(substream);
 395}
 396
 397static int acp3x_dma_mmap(struct snd_pcm_substream *substream,
 398                          struct vm_area_struct *vma)
 399{
 400        return snd_pcm_lib_default_mmap(substream, vma);
 401}
 402
 403static int acp3x_dma_close(struct snd_pcm_substream *substream)
 404{
 405        struct snd_soc_pcm_runtime *prtd = substream->private_data;
 406        struct i2s_stream_instance *rtd = substream->runtime->private_data;
 407        struct snd_soc_component *component = snd_soc_rtdcom_lookup(prtd,
 408                                                                    DRV_NAME);
 409        struct i2s_dev_data *adata = dev_get_drvdata(component->dev);
 410
 411        if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
 412                adata->play_stream = NULL;
 413        else
 414                adata->capture_stream = NULL;
 415
 416        /* Disable ACP irq, when the current stream is being closed and
 417         * another stream is also not active.
 418         */
 419        if (!adata->play_stream && !adata->capture_stream)
 420                rv_writel(0, adata->acp3x_base + mmACP_EXTERNAL_INTR_ENB);
 421        kfree(rtd);
 422        return 0;
 423}
 424
 425static struct snd_pcm_ops acp3x_dma_ops = {
 426        .open = acp3x_dma_open,
 427        .close = acp3x_dma_close,
 428        .ioctl = snd_pcm_lib_ioctl,
 429        .hw_params = acp3x_dma_hw_params,
 430        .hw_free = acp3x_dma_hw_free,
 431        .pointer = acp3x_dma_pointer,
 432        .mmap = acp3x_dma_mmap,
 433};
 434
 435
 436static int acp3x_dai_i2s_set_fmt(struct snd_soc_dai *cpu_dai, unsigned int fmt)
 437{
 438
 439        struct i2s_dev_data *adata = snd_soc_dai_get_drvdata(cpu_dai);
 440
 441        switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
 442        case SND_SOC_DAIFMT_I2S:
 443                adata->tdm_mode = false;
 444                break;
 445        case SND_SOC_DAIFMT_DSP_A:
 446                adata->tdm_mode = true;
 447                break;
 448        default:
 449                return -EINVAL;
 450        }
 451
 452        return 0;
 453}
 454
 455static int acp3x_dai_set_tdm_slot(struct snd_soc_dai *cpu_dai, u32 tx_mask,
 456                                  u32 rx_mask, int slots, int slot_width)
 457{
 458        u32 val = 0;
 459        u16 slot_len;
 460
 461        struct i2s_dev_data *adata = snd_soc_dai_get_drvdata(cpu_dai);
 462
 463        switch (slot_width) {
 464        case SLOT_WIDTH_8:
 465                slot_len = 8;
 466                break;
 467        case SLOT_WIDTH_16:
 468                slot_len = 16;
 469                break;
 470        case SLOT_WIDTH_24:
 471                slot_len = 24;
 472                break;
 473        case SLOT_WIDTH_32:
 474                slot_len = 0;
 475                break;
 476        default:
 477                return -EINVAL;
 478        }
 479
 480        val = rv_readl(adata->acp3x_base + mmACP_BTTDM_ITER);
 481        rv_writel((val | 0x2), adata->acp3x_base + mmACP_BTTDM_ITER);
 482        val = rv_readl(adata->acp3x_base + mmACP_BTTDM_IRER);
 483        rv_writel((val | 0x2), adata->acp3x_base + mmACP_BTTDM_IRER);
 484
 485        val = (FRM_LEN | (slots << 15) | (slot_len << 18));
 486        rv_writel(val, adata->acp3x_base + mmACP_BTTDM_TXFRMT);
 487        rv_writel(val, adata->acp3x_base + mmACP_BTTDM_RXFRMT);
 488
 489        adata->tdm_fmt = val;
 490        return 0;
 491}
 492
 493static int acp3x_dai_i2s_hwparams(struct snd_pcm_substream *substream,
 494                                  struct snd_pcm_hw_params *params,
 495                                  struct snd_soc_dai *dai)
 496{
 497        u32 val = 0;
 498        struct i2s_stream_instance *rtd = substream->runtime->private_data;
 499
 500        switch (params_format(params)) {
 501        case SNDRV_PCM_FORMAT_U8:
 502        case SNDRV_PCM_FORMAT_S8:
 503                rtd->xfer_resolution = 0x0;
 504                break;
 505        case SNDRV_PCM_FORMAT_S16_LE:
 506                rtd->xfer_resolution = 0x02;
 507                break;
 508        case SNDRV_PCM_FORMAT_S24_LE:
 509                rtd->xfer_resolution = 0x04;
 510                break;
 511        case SNDRV_PCM_FORMAT_S32_LE:
 512                rtd->xfer_resolution = 0x05;
 513                break;
 514        default:
 515                return -EINVAL;
 516        }
 517        val = rv_readl(rtd->acp3x_base + mmACP_BTTDM_ITER);
 518        val = val | (rtd->xfer_resolution  << 3);
 519        if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
 520                rv_writel(val, rtd->acp3x_base + mmACP_BTTDM_ITER);
 521        else
 522                rv_writel(val, rtd->acp3x_base + mmACP_BTTDM_IRER);
 523
 524        return 0;
 525}
 526
 527static int acp3x_dai_i2s_trigger(struct snd_pcm_substream *substream,
 528                                 int cmd, struct snd_soc_dai *dai)
 529{
 530        int ret = 0;
 531        struct i2s_stream_instance *rtd = substream->runtime->private_data;
 532        u32 val, period_bytes;
 533
 534        period_bytes = frames_to_bytes(substream->runtime,
 535                                       substream->runtime->period_size);
 536        switch (cmd) {
 537        case SNDRV_PCM_TRIGGER_START:
 538        case SNDRV_PCM_TRIGGER_RESUME:
 539        case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
 540                rtd->bytescount = acp_get_byte_count(rtd, substream->stream);
 541                if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
 542                        rv_writel(period_bytes, rtd->acp3x_base +
 543                                  mmACP_BT_TX_INTR_WATERMARK_SIZE);
 544                        val = rv_readl(rtd->acp3x_base + mmACP_BTTDM_ITER);
 545                        val = val | BIT(0);
 546                        rv_writel(val, rtd->acp3x_base + mmACP_BTTDM_ITER);
 547                } else {
 548                        rv_writel(period_bytes, rtd->acp3x_base +
 549                                  mmACP_BT_RX_INTR_WATERMARK_SIZE);
 550                        val = rv_readl(rtd->acp3x_base + mmACP_BTTDM_IRER);
 551                        val = val | BIT(0);
 552                        rv_writel(val, rtd->acp3x_base + mmACP_BTTDM_IRER);
 553                }
 554                rv_writel(1, rtd->acp3x_base + mmACP_BTTDM_IER);
 555                break;
 556        case SNDRV_PCM_TRIGGER_STOP:
 557        case SNDRV_PCM_TRIGGER_SUSPEND:
 558        case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
 559                if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
 560                        val = rv_readl(rtd->acp3x_base + mmACP_BTTDM_ITER);
 561                        val = val & ~BIT(0);
 562                        rv_writel(val, rtd->acp3x_base + mmACP_BTTDM_ITER);
 563                } else {
 564                        val = rv_readl(rtd->acp3x_base + mmACP_BTTDM_IRER);
 565                        val = val & ~BIT(0);
 566                        rv_writel(val, rtd->acp3x_base + mmACP_BTTDM_IRER);
 567                }
 568                rv_writel(0, rtd->acp3x_base + mmACP_BTTDM_IER);
 569                break;
 570        default:
 571                ret = -EINVAL;
 572                break;
 573        }
 574
 575        return ret;
 576}
 577
 578static struct snd_soc_dai_ops acp3x_dai_i2s_ops = {
 579        .hw_params = acp3x_dai_i2s_hwparams,
 580        .trigger   = acp3x_dai_i2s_trigger,
 581        .set_fmt = acp3x_dai_i2s_set_fmt,
 582        .set_tdm_slot = acp3x_dai_set_tdm_slot,
 583};
 584
 585static struct snd_soc_dai_driver acp3x_i2s_dai_driver = {
 586        .playback = {
 587                .rates = SNDRV_PCM_RATE_8000_96000,
 588                .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S8 |
 589                                        SNDRV_PCM_FMTBIT_U8 |
 590                                        SNDRV_PCM_FMTBIT_S24_LE |
 591                                        SNDRV_PCM_FMTBIT_S32_LE,
 592                .channels_min = 2,
 593                .channels_max = 8,
 594
 595                .rate_min = 8000,
 596                .rate_max = 96000,
 597        },
 598        .capture = {
 599                .rates = SNDRV_PCM_RATE_8000_48000,
 600                .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S8 |
 601                                        SNDRV_PCM_FMTBIT_U8 |
 602                                        SNDRV_PCM_FMTBIT_S24_LE |
 603                                        SNDRV_PCM_FMTBIT_S32_LE,
 604                .channels_min = 2,
 605                .channels_max = 2,
 606                .rate_min = 8000,
 607                .rate_max = 48000,
 608        },
 609        .ops = &acp3x_dai_i2s_ops,
 610};
 611
 612static const struct snd_soc_component_driver acp3x_i2s_component = {
 613        .name           = DRV_NAME,
 614        .ops            = &acp3x_dma_ops,
 615        .pcm_new        = acp3x_dma_new,
 616};
 617
 618static int acp3x_audio_probe(struct platform_device *pdev)
 619{
 620        int status;
 621        struct resource *res;
 622        struct i2s_dev_data *adata;
 623        unsigned int irqflags;
 624
 625        if (!pdev->dev.platform_data) {
 626                dev_err(&pdev->dev, "platform_data not retrieved\n");
 627                return -ENODEV;
 628        }
 629        irqflags = *((unsigned int *)(pdev->dev.platform_data));
 630
 631        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 632        if (!res) {
 633                dev_err(&pdev->dev, "IORESOURCE_IRQ FAILED\n");
 634                        return -ENODEV;
 635        }
 636
 637        adata = devm_kzalloc(&pdev->dev, sizeof(*adata), GFP_KERNEL);
 638        if (!adata)
 639                return -ENOMEM;
 640
 641        adata->acp3x_base = devm_ioremap(&pdev->dev, res->start,
 642                                         resource_size(res));
 643
 644        res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
 645        if (!res) {
 646                dev_err(&pdev->dev, "IORESOURCE_IRQ FAILED\n");
 647                return -ENODEV;
 648        }
 649
 650        adata->i2s_irq = res->start;
 651        adata->play_stream = NULL;
 652        adata->capture_stream = NULL;
 653
 654        dev_set_drvdata(&pdev->dev, adata);
 655        /* Initialize ACP */
 656        status = acp3x_init(adata->acp3x_base);
 657        if (status)
 658                return -ENODEV;
 659        status = devm_snd_soc_register_component(&pdev->dev,
 660                                                 &acp3x_i2s_component,
 661                                                 &acp3x_i2s_dai_driver, 1);
 662        if (status) {
 663                dev_err(&pdev->dev, "Fail to register acp i2s dai\n");
 664                goto dev_err;
 665        }
 666        status = devm_request_irq(&pdev->dev, adata->i2s_irq, i2s_irq_handler,
 667                                  irqflags, "ACP3x_I2S_IRQ", adata);
 668        if (status) {
 669                dev_err(&pdev->dev, "ACP3x I2S IRQ request failed\n");
 670                goto dev_err;
 671        }
 672
 673        pm_runtime_set_autosuspend_delay(&pdev->dev, 10000);
 674        pm_runtime_use_autosuspend(&pdev->dev);
 675        pm_runtime_enable(&pdev->dev);
 676        return 0;
 677dev_err:
 678        status = acp3x_deinit(adata->acp3x_base);
 679        if (status)
 680                dev_err(&pdev->dev, "ACP de-init failed\n");
 681        else
 682                dev_info(&pdev->dev, "ACP de-initialized\n");
 683        /*ignore device status and return driver probe error*/
 684        return -ENODEV;
 685}
 686
 687static int acp3x_audio_remove(struct platform_device *pdev)
 688{
 689        int ret;
 690        struct i2s_dev_data *adata = dev_get_drvdata(&pdev->dev);
 691
 692        ret = acp3x_deinit(adata->acp3x_base);
 693        if (ret)
 694                dev_err(&pdev->dev, "ACP de-init failed\n");
 695        else
 696                dev_info(&pdev->dev, "ACP de-initialized\n");
 697
 698        pm_runtime_disable(&pdev->dev);
 699        return 0;
 700}
 701
 702static int acp3x_resume(struct device *dev)
 703{
 704        int status;
 705        u32 val;
 706        struct i2s_dev_data *adata = dev_get_drvdata(dev);
 707
 708        status = acp3x_init(adata->acp3x_base);
 709        if (status)
 710                return -ENODEV;
 711
 712        if (adata->play_stream && adata->play_stream->runtime) {
 713                struct i2s_stream_instance *rtd =
 714                        adata->play_stream->runtime->private_data;
 715                config_acp3x_dma(rtd, SNDRV_PCM_STREAM_PLAYBACK);
 716                rv_writel((rtd->xfer_resolution  << 3),
 717                          rtd->acp3x_base + mmACP_BTTDM_ITER);
 718                if (adata->tdm_mode == true) {
 719                        rv_writel(adata->tdm_fmt, adata->acp3x_base +
 720                                  mmACP_BTTDM_TXFRMT);
 721                        val = rv_readl(adata->acp3x_base + mmACP_BTTDM_ITER);
 722                        rv_writel((val | 0x2), adata->acp3x_base +
 723                                  mmACP_BTTDM_ITER);
 724                }
 725        }
 726
 727        if (adata->capture_stream && adata->capture_stream->runtime) {
 728                struct i2s_stream_instance *rtd =
 729                        adata->capture_stream->runtime->private_data;
 730                config_acp3x_dma(rtd, SNDRV_PCM_STREAM_CAPTURE);
 731                rv_writel((rtd->xfer_resolution  << 3),
 732                          rtd->acp3x_base + mmACP_BTTDM_IRER);
 733                if (adata->tdm_mode == true) {
 734                        rv_writel(adata->tdm_fmt, adata->acp3x_base +
 735                                  mmACP_BTTDM_RXFRMT);
 736                        val = rv_readl(adata->acp3x_base + mmACP_BTTDM_IRER);
 737                        rv_writel((val | 0x2), adata->acp3x_base +
 738                                  mmACP_BTTDM_IRER);
 739                }
 740        }
 741
 742        rv_writel(1, adata->acp3x_base + mmACP_EXTERNAL_INTR_ENB);
 743        return 0;
 744}
 745
 746
 747static int acp3x_pcm_runtime_suspend(struct device *dev)
 748{
 749        int status;
 750        struct i2s_dev_data *adata = dev_get_drvdata(dev);
 751
 752        status = acp3x_deinit(adata->acp3x_base);
 753        if (status)
 754                dev_err(dev, "ACP de-init failed\n");
 755        else
 756                dev_info(dev, "ACP de-initialized\n");
 757
 758        rv_writel(0, adata->acp3x_base + mmACP_EXTERNAL_INTR_ENB);
 759
 760        return 0;
 761}
 762
 763static int acp3x_pcm_runtime_resume(struct device *dev)
 764{
 765        int status;
 766        struct i2s_dev_data *adata = dev_get_drvdata(dev);
 767
 768        status = acp3x_init(adata->acp3x_base);
 769        if (status)
 770                return -ENODEV;
 771        rv_writel(1, adata->acp3x_base + mmACP_EXTERNAL_INTR_ENB);
 772        return 0;
 773}
 774
 775static const struct dev_pm_ops acp3x_pm_ops = {
 776        .runtime_suspend = acp3x_pcm_runtime_suspend,
 777        .runtime_resume = acp3x_pcm_runtime_resume,
 778        .resume = acp3x_resume,
 779};
 780
 781static struct platform_driver acp3x_dma_driver = {
 782        .probe = acp3x_audio_probe,
 783        .remove = acp3x_audio_remove,
 784        .driver = {
 785                .name = "acp3x_rv_i2s",
 786                .pm = &acp3x_pm_ops,
 787        },
 788};
 789
 790module_platform_driver(acp3x_dma_driver);
 791
 792MODULE_AUTHOR("Maruthi.Bayyavarapu@amd.com");
 793MODULE_AUTHOR("Vijendar.Mukunda@amd.com");
 794MODULE_DESCRIPTION("AMD ACP 3.x PCM Driver");
 795MODULE_LICENSE("GPL v2");
 796MODULE_ALIAS("platform:" DRV_NAME);
 797