linux/sound/soc/sprd/sprd-pcm-dma.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0
   2// Copyright (C) 2019 Spreadtrum Communications Inc.
   3
   4#include <linux/dma-mapping.h>
   5#include <linux/dmaengine.h>
   6#include <linux/dma/sprd-dma.h>
   7#include <linux/kernel.h>
   8#include <linux/module.h>
   9#include <linux/of_reserved_mem.h>
  10#include <linux/platform_device.h>
  11#include <sound/pcm.h>
  12#include <sound/pcm_params.h>
  13#include <sound/soc.h>
  14
  15#include "sprd-pcm-dma.h"
  16
  17#define SPRD_PCM_DMA_LINKLIST_SIZE      64
  18#define SPRD_PCM_DMA_BRUST_LEN          640
  19
  20struct sprd_pcm_dma_data {
  21        struct dma_chan *chan;
  22        struct dma_async_tx_descriptor *desc;
  23        dma_cookie_t cookie;
  24        dma_addr_t phys;
  25        void *virt;
  26        int pre_pointer;
  27};
  28
  29struct sprd_pcm_dma_private {
  30        struct snd_pcm_substream *substream;
  31        struct sprd_pcm_dma_params *params;
  32        struct sprd_pcm_dma_data data[SPRD_PCM_CHANNEL_MAX];
  33        int hw_chan;
  34        int dma_addr_offset;
  35};
  36
  37static const struct snd_pcm_hardware sprd_pcm_hardware = {
  38        .info = SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_MMAP_VALID |
  39                SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_PAUSE |
  40                SNDRV_PCM_INFO_RESUME | SNDRV_PCM_INFO_NO_PERIOD_WAKEUP,
  41        .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE,
  42        .period_bytes_min = 1,
  43        .period_bytes_max = 64 * 1024,
  44        .periods_min = 1,
  45        .periods_max = PAGE_SIZE / SPRD_PCM_DMA_LINKLIST_SIZE,
  46        .buffer_bytes_max = 64 * 1024,
  47};
  48
  49static int sprd_pcm_open(struct snd_soc_component *component,
  50                         struct snd_pcm_substream *substream)
  51{
  52        struct snd_pcm_runtime *runtime = substream->runtime;
  53        struct device *dev = component->dev;
  54        struct sprd_pcm_dma_private *dma_private;
  55        int hw_chan = SPRD_PCM_CHANNEL_MAX;
  56        int size, ret, i;
  57
  58        snd_soc_set_runtime_hwparams(substream, &sprd_pcm_hardware);
  59
  60        ret = snd_pcm_hw_constraint_step(runtime, 0,
  61                                         SNDRV_PCM_HW_PARAM_PERIOD_BYTES,
  62                                         SPRD_PCM_DMA_BRUST_LEN);
  63        if (ret < 0)
  64                return ret;
  65
  66        ret = snd_pcm_hw_constraint_step(runtime, 0,
  67                                         SNDRV_PCM_HW_PARAM_BUFFER_BYTES,
  68                                         SPRD_PCM_DMA_BRUST_LEN);
  69        if (ret < 0)
  70                return ret;
  71
  72        ret = snd_pcm_hw_constraint_integer(runtime,
  73                                            SNDRV_PCM_HW_PARAM_PERIODS);
  74        if (ret < 0)
  75                return ret;
  76
  77        dma_private = devm_kzalloc(dev, sizeof(*dma_private), GFP_KERNEL);
  78        if (!dma_private)
  79                return -ENOMEM;
  80
  81        size = runtime->hw.periods_max * SPRD_PCM_DMA_LINKLIST_SIZE;
  82
  83        for (i = 0; i < hw_chan; i++) {
  84                struct sprd_pcm_dma_data *data = &dma_private->data[i];
  85
  86                data->virt = dmam_alloc_coherent(dev, size, &data->phys,
  87                                                 GFP_KERNEL);
  88                if (!data->virt) {
  89                        ret = -ENOMEM;
  90                        goto error;
  91                }
  92        }
  93
  94        dma_private->hw_chan = hw_chan;
  95        runtime->private_data = dma_private;
  96        dma_private->substream = substream;
  97
  98        return 0;
  99
 100error:
 101        for (i = 0; i < hw_chan; i++) {
 102                struct sprd_pcm_dma_data *data = &dma_private->data[i];
 103
 104                if (data->virt)
 105                        dmam_free_coherent(dev, size, data->virt, data->phys);
 106        }
 107
 108        devm_kfree(dev, dma_private);
 109        return ret;
 110}
 111
 112static int sprd_pcm_close(struct snd_soc_component *component,
 113                          struct snd_pcm_substream *substream)
 114{
 115        struct snd_pcm_runtime *runtime = substream->runtime;
 116        struct sprd_pcm_dma_private *dma_private = runtime->private_data;
 117        struct device *dev = component->dev;
 118        int size = runtime->hw.periods_max * SPRD_PCM_DMA_LINKLIST_SIZE;
 119        int i;
 120
 121        for (i = 0; i < dma_private->hw_chan; i++) {
 122                struct sprd_pcm_dma_data *data = &dma_private->data[i];
 123
 124                dmam_free_coherent(dev, size, data->virt, data->phys);
 125        }
 126
 127        devm_kfree(dev, dma_private);
 128
 129        return 0;
 130}
 131
 132static void sprd_pcm_dma_complete(void *data)
 133{
 134        struct sprd_pcm_dma_private *dma_private = data;
 135        struct snd_pcm_substream *substream = dma_private->substream;
 136
 137        snd_pcm_period_elapsed(substream);
 138}
 139
 140static void sprd_pcm_release_dma_channel(struct snd_pcm_substream *substream)
 141{
 142        struct snd_pcm_runtime *runtime = substream->runtime;
 143        struct sprd_pcm_dma_private *dma_private = runtime->private_data;
 144        int i;
 145
 146        for (i = 0; i < SPRD_PCM_CHANNEL_MAX; i++) {
 147                struct sprd_pcm_dma_data *data = &dma_private->data[i];
 148
 149                if (data->chan) {
 150                        dma_release_channel(data->chan);
 151                        data->chan = NULL;
 152                }
 153        }
 154}
 155
 156static int sprd_pcm_request_dma_channel(struct snd_soc_component *component,
 157                                        struct snd_pcm_substream *substream,
 158                                        int channels)
 159{
 160        struct snd_pcm_runtime *runtime = substream->runtime;
 161        struct sprd_pcm_dma_private *dma_private = runtime->private_data;
 162        struct device *dev = component->dev;
 163        struct sprd_pcm_dma_params *dma_params = dma_private->params;
 164        int i;
 165
 166        if (channels > SPRD_PCM_CHANNEL_MAX) {
 167                dev_err(dev, "invalid dma channel number:%d\n", channels);
 168                return -EINVAL;
 169        }
 170
 171        for (i = 0; i < channels; i++) {
 172                struct sprd_pcm_dma_data *data = &dma_private->data[i];
 173
 174                data->chan = dma_request_slave_channel(dev,
 175                                                       dma_params->chan_name[i]);
 176                if (!data->chan) {
 177                        dev_err(dev, "failed to request dma channel:%s\n",
 178                                dma_params->chan_name[i]);
 179                        sprd_pcm_release_dma_channel(substream);
 180                        return -ENODEV;
 181                }
 182        }
 183
 184        return 0;
 185}
 186
 187static int sprd_pcm_hw_params(struct snd_soc_component *component,
 188                              struct snd_pcm_substream *substream,
 189                              struct snd_pcm_hw_params *params)
 190{
 191        struct snd_pcm_runtime *runtime = substream->runtime;
 192        struct sprd_pcm_dma_private *dma_private = runtime->private_data;
 193        struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
 194        struct sprd_pcm_dma_params *dma_params;
 195        size_t totsize = params_buffer_bytes(params);
 196        size_t period = params_period_bytes(params);
 197        int channels = params_channels(params);
 198        int is_playback = substream->stream == SNDRV_PCM_STREAM_PLAYBACK;
 199        struct scatterlist *sg;
 200        unsigned long flags;
 201        int ret, i, j, sg_num;
 202
 203        dma_params = snd_soc_dai_get_dma_data(asoc_rtd_to_cpu(rtd, 0), substream);
 204        if (!dma_params) {
 205                dev_warn(component->dev, "no dma parameters setting\n");
 206                dma_private->params = NULL;
 207                return 0;
 208        }
 209
 210        if (!dma_private->params) {
 211                dma_private->params = dma_params;
 212                ret = sprd_pcm_request_dma_channel(component,
 213                                                   substream, channels);
 214                if (ret)
 215                        return ret;
 216        }
 217
 218        sg_num = totsize / period;
 219        dma_private->dma_addr_offset = totsize / channels;
 220
 221        sg = devm_kcalloc(component->dev, sg_num, sizeof(*sg), GFP_KERNEL);
 222        if (!sg) {
 223                ret = -ENOMEM;
 224                goto sg_err;
 225        }
 226
 227        for (i = 0; i < channels; i++) {
 228                struct sprd_pcm_dma_data *data = &dma_private->data[i];
 229                struct dma_chan *chan = data->chan;
 230                struct dma_slave_config config = { };
 231                struct sprd_dma_linklist link = { };
 232                enum dma_transfer_direction dir;
 233                struct scatterlist *sgt = sg;
 234
 235                config.src_maxburst = dma_params->fragment_len[i];
 236                config.src_addr_width = dma_params->datawidth[i];
 237                config.dst_addr_width = dma_params->datawidth[i];
 238                if (is_playback) {
 239                        config.src_addr = runtime->dma_addr +
 240                                i * dma_private->dma_addr_offset;
 241                        config.dst_addr = dma_params->dev_phys[i];
 242                        dir = DMA_MEM_TO_DEV;
 243                } else {
 244                        config.src_addr = dma_params->dev_phys[i];
 245                        config.dst_addr = runtime->dma_addr +
 246                                i * dma_private->dma_addr_offset;
 247                        dir = DMA_DEV_TO_MEM;
 248                }
 249
 250                sg_init_table(sgt, sg_num);
 251                for (j = 0; j < sg_num; j++, sgt++) {
 252                        u32 sg_len = period / channels;
 253
 254                        sg_dma_len(sgt) = sg_len;
 255                        sg_dma_address(sgt) = runtime->dma_addr +
 256                                i * dma_private->dma_addr_offset + sg_len * j;
 257                }
 258
 259                /*
 260                 * Configure the link-list address for the DMA engine link-list
 261                 * mode.
 262                 */
 263                link.virt_addr = (unsigned long)data->virt;
 264                link.phy_addr = data->phys;
 265
 266                ret = dmaengine_slave_config(chan, &config);
 267                if (ret) {
 268                        dev_err(component->dev,
 269                                "failed to set slave configuration: %d\n", ret);
 270                        goto config_err;
 271                }
 272
 273                /*
 274                 * We configure the DMA request mode, interrupt mode, channel
 275                 * mode and channel trigger mode by the flags.
 276                 */
 277                flags = SPRD_DMA_FLAGS(SPRD_DMA_CHN_MODE_NONE, SPRD_DMA_NO_TRG,
 278                                       SPRD_DMA_FRAG_REQ, SPRD_DMA_TRANS_INT);
 279                data->desc = chan->device->device_prep_slave_sg(chan, sg,
 280                                                                sg_num, dir,
 281                                                                flags, &link);
 282                if (!data->desc) {
 283                        dev_err(component->dev, "failed to prepare slave sg\n");
 284                        ret = -ENOMEM;
 285                        goto config_err;
 286                }
 287
 288                if (!runtime->no_period_wakeup) {
 289                        data->desc->callback = sprd_pcm_dma_complete;
 290                        data->desc->callback_param = dma_private;
 291                }
 292        }
 293
 294        devm_kfree(component->dev, sg);
 295
 296        return 0;
 297
 298config_err:
 299        devm_kfree(component->dev, sg);
 300sg_err:
 301        sprd_pcm_release_dma_channel(substream);
 302        return ret;
 303}
 304
 305static int sprd_pcm_hw_free(struct snd_soc_component *component,
 306                            struct snd_pcm_substream *substream)
 307{
 308        sprd_pcm_release_dma_channel(substream);
 309
 310        return 0;
 311}
 312
 313static int sprd_pcm_trigger(struct snd_soc_component *component,
 314                            struct snd_pcm_substream *substream, int cmd)
 315{
 316        struct sprd_pcm_dma_private *dma_private =
 317                substream->runtime->private_data;
 318        int ret = 0, i;
 319
 320        switch (cmd) {
 321        case SNDRV_PCM_TRIGGER_START:
 322                for (i = 0; i < dma_private->hw_chan; i++) {
 323                        struct sprd_pcm_dma_data *data = &dma_private->data[i];
 324
 325                        if (!data->desc)
 326                                continue;
 327
 328                        data->cookie = dmaengine_submit(data->desc);
 329                        ret = dma_submit_error(data->cookie);
 330                        if (ret) {
 331                                dev_err(component->dev,
 332                                        "failed to submit dma request: %d\n",
 333                                        ret);
 334                                return ret;
 335                        }
 336
 337                        dma_async_issue_pending(data->chan);
 338                }
 339
 340                break;
 341        case SNDRV_PCM_TRIGGER_RESUME:
 342        case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
 343                for (i = 0; i < dma_private->hw_chan; i++) {
 344                        struct sprd_pcm_dma_data *data = &dma_private->data[i];
 345
 346                        if (data->chan)
 347                                dmaengine_resume(data->chan);
 348                }
 349
 350                break;
 351        case SNDRV_PCM_TRIGGER_STOP:
 352                for (i = 0; i < dma_private->hw_chan; i++) {
 353                        struct sprd_pcm_dma_data *data = &dma_private->data[i];
 354
 355                        if (data->chan)
 356                                dmaengine_terminate_async(data->chan);
 357                }
 358
 359                break;
 360        case SNDRV_PCM_TRIGGER_SUSPEND:
 361        case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
 362                for (i = 0; i < dma_private->hw_chan; i++) {
 363                        struct sprd_pcm_dma_data *data = &dma_private->data[i];
 364
 365                        if (data->chan)
 366                                dmaengine_pause(data->chan);
 367                }
 368
 369                break;
 370        default:
 371                ret = -EINVAL;
 372        }
 373
 374        return ret;
 375}
 376
 377static snd_pcm_uframes_t sprd_pcm_pointer(struct snd_soc_component *component,
 378                                          struct snd_pcm_substream *substream)
 379{
 380        struct snd_pcm_runtime *runtime = substream->runtime;
 381        struct sprd_pcm_dma_private *dma_private = runtime->private_data;
 382        int pointer[SPRD_PCM_CHANNEL_MAX];
 383        int bytes_of_pointer = 0, sel_max = 0, i;
 384        snd_pcm_uframes_t x;
 385        struct dma_tx_state state;
 386        enum dma_status status;
 387
 388        for (i = 0; i < dma_private->hw_chan; i++) {
 389                struct sprd_pcm_dma_data *data = &dma_private->data[i];
 390
 391                if (!data->chan)
 392                        continue;
 393
 394                status = dmaengine_tx_status(data->chan, data->cookie, &state);
 395                if (status == DMA_ERROR) {
 396                        dev_err(component->dev,
 397                                "failed to get dma channel %d status\n", i);
 398                        return 0;
 399                }
 400
 401                /*
 402                 * We just get current transfer address from the DMA engine, so
 403                 * we need convert to current pointer.
 404                 */
 405                pointer[i] = state.residue - runtime->dma_addr -
 406                        i * dma_private->dma_addr_offset;
 407
 408                if (i == 0) {
 409                        bytes_of_pointer = pointer[i];
 410                        sel_max = pointer[i] < data->pre_pointer ? 1 : 0;
 411                } else {
 412                        sel_max ^= pointer[i] < data->pre_pointer ? 1 : 0;
 413
 414                        if (sel_max)
 415                                bytes_of_pointer =
 416                                        max(pointer[i], pointer[i - 1]) << 1;
 417                        else
 418                                bytes_of_pointer =
 419                                        min(pointer[i], pointer[i - 1]) << 1;
 420                }
 421
 422                data->pre_pointer = pointer[i];
 423        }
 424
 425        x = bytes_to_frames(runtime, bytes_of_pointer);
 426        if (x == runtime->buffer_size)
 427                x = 0;
 428
 429        return x;
 430}
 431
 432static int sprd_pcm_new(struct snd_soc_component *component,
 433                        struct snd_soc_pcm_runtime *rtd)
 434{
 435        struct snd_card *card = rtd->card->snd_card;
 436        struct snd_pcm *pcm = rtd->pcm;
 437        int ret;
 438
 439        ret = dma_coerce_mask_and_coherent(card->dev, DMA_BIT_MASK(32));
 440        if (ret)
 441                return ret;
 442
 443        return snd_pcm_set_fixed_buffer_all(pcm, SNDRV_DMA_TYPE_DEV,
 444                                            card->dev,
 445                                            sprd_pcm_hardware.buffer_bytes_max);
 446}
 447
 448static const struct snd_soc_component_driver sprd_soc_component = {
 449        .name           = DRV_NAME,
 450        .open           = sprd_pcm_open,
 451        .close          = sprd_pcm_close,
 452        .hw_params      = sprd_pcm_hw_params,
 453        .hw_free        = sprd_pcm_hw_free,
 454        .trigger        = sprd_pcm_trigger,
 455        .pointer        = sprd_pcm_pointer,
 456        .pcm_construct  = sprd_pcm_new,
 457        .compress_ops   = &sprd_platform_compress_ops,
 458};
 459
 460static int sprd_soc_platform_probe(struct platform_device *pdev)
 461{
 462        struct device_node *np = pdev->dev.of_node;
 463        int ret;
 464
 465        ret = of_reserved_mem_device_init_by_idx(&pdev->dev, np, 0);
 466        if (ret)
 467                dev_warn(&pdev->dev,
 468                         "no reserved DMA memory for audio platform device\n");
 469
 470        ret = devm_snd_soc_register_component(&pdev->dev, &sprd_soc_component,
 471                                              NULL, 0);
 472        if (ret)
 473                dev_err(&pdev->dev, "could not register platform:%d\n", ret);
 474
 475        return ret;
 476}
 477
 478static const struct of_device_id sprd_pcm_of_match[] = {
 479        { .compatible = "sprd,pcm-platform", },
 480        { },
 481};
 482MODULE_DEVICE_TABLE(of, sprd_pcm_of_match);
 483
 484static struct platform_driver sprd_pcm_driver = {
 485        .driver = {
 486                .name = "sprd-pcm-audio",
 487                .of_match_table = sprd_pcm_of_match,
 488        },
 489
 490        .probe = sprd_soc_platform_probe,
 491};
 492
 493module_platform_driver(sprd_pcm_driver);
 494
 495MODULE_DESCRIPTION("Spreadtrum ASoC PCM DMA");
 496MODULE_LICENSE("GPL v2");
 497MODULE_ALIAS("platform:sprd-audio");
 498