linux/sound/soc/sof/pcm.c
<<
>>
Prefs
   1// SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause)
   2//
   3// This file is provided under a dual BSD/GPLv2 license.  When using or
   4// redistributing this file, you may do so under either license.
   5//
   6// Copyright(c) 2018 Intel Corporation. All rights reserved.
   7//
   8// Author: Liam Girdwood <liam.r.girdwood@linux.intel.com>
   9//
  10// PCM Layer, interface between ALSA and IPC.
  11//
  12
  13#include <linux/pm_runtime.h>
  14#include <sound/pcm_params.h>
  15#include <sound/sof.h>
  16#include "sof-priv.h"
  17#include "sof-audio.h"
  18#include "ops.h"
  19#if IS_ENABLED(CONFIG_SND_SOC_SOF_DEBUG_PROBES)
  20#include "sof-probes.h"
  21#endif
  22
  23/* Create DMA buffer page table for DSP */
  24static int create_page_table(struct snd_soc_component *component,
  25                             struct snd_pcm_substream *substream,
  26                             unsigned char *dma_area, size_t size)
  27{
  28        struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
  29        struct snd_sof_pcm *spcm;
  30        struct snd_dma_buffer *dmab = snd_pcm_get_dma_buf(substream);
  31        int stream = substream->stream;
  32
  33        spcm = snd_sof_find_spcm_dai(component, rtd);
  34        if (!spcm)
  35                return -EINVAL;
  36
  37        return snd_sof_create_page_table(component->dev, dmab,
  38                spcm->stream[stream].page_table.area, size);
  39}
  40
  41static int sof_pcm_dsp_params(struct snd_sof_pcm *spcm, struct snd_pcm_substream *substream,
  42                              const struct sof_ipc_pcm_params_reply *reply)
  43{
  44        struct snd_soc_component *scomp = spcm->scomp;
  45        struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(scomp);
  46
  47        /* validate offset */
  48        int ret = snd_sof_ipc_pcm_params(sdev, substream, reply);
  49
  50        if (ret < 0)
  51                dev_err(scomp->dev, "error: got wrong reply for PCM %d\n",
  52                        spcm->pcm.pcm_id);
  53
  54        return ret;
  55}
  56
  57/*
  58 * sof pcm period elapse work
  59 */
  60static void snd_sof_pcm_period_elapsed_work(struct work_struct *work)
  61{
  62        struct snd_sof_pcm_stream *sps =
  63                container_of(work, struct snd_sof_pcm_stream,
  64                             period_elapsed_work);
  65
  66        snd_pcm_period_elapsed(sps->substream);
  67}
  68
  69void snd_sof_pcm_init_elapsed_work(struct work_struct *work)
  70{
  71         INIT_WORK(work, snd_sof_pcm_period_elapsed_work);
  72}
  73
  74/*
  75 * sof pcm period elapse, this could be called at irq thread context.
  76 */
  77void snd_sof_pcm_period_elapsed(struct snd_pcm_substream *substream)
  78{
  79        struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
  80        struct snd_soc_component *component =
  81                snd_soc_rtdcom_lookup(rtd, SOF_AUDIO_PCM_DRV_NAME);
  82        struct snd_sof_pcm *spcm;
  83
  84        spcm = snd_sof_find_spcm_dai(component, rtd);
  85        if (!spcm) {
  86                dev_err(component->dev,
  87                        "error: period elapsed for unknown stream!\n");
  88                return;
  89        }
  90
  91        /*
  92         * snd_pcm_period_elapsed() can be called in interrupt context
  93         * before IRQ_HANDLED is returned. Inside snd_pcm_period_elapsed(),
  94         * when the PCM is done draining or xrun happened, a STOP IPC will
  95         * then be sent and this IPC will hit IPC timeout.
  96         * To avoid sending IPC before the previous IPC is handled, we
  97         * schedule delayed work here to call the snd_pcm_period_elapsed().
  98         */
  99        schedule_work(&spcm->stream[substream->stream].period_elapsed_work);
 100}
 101EXPORT_SYMBOL(snd_sof_pcm_period_elapsed);
 102
 103static int sof_pcm_dsp_pcm_free(struct snd_pcm_substream *substream,
 104                                struct snd_sof_dev *sdev,
 105                                struct snd_sof_pcm *spcm)
 106{
 107        struct sof_ipc_stream stream;
 108        struct sof_ipc_reply reply;
 109        int ret;
 110
 111        stream.hdr.size = sizeof(stream);
 112        stream.hdr.cmd = SOF_IPC_GLB_STREAM_MSG | SOF_IPC_STREAM_PCM_FREE;
 113        stream.comp_id = spcm->stream[substream->stream].comp_id;
 114
 115        /* send IPC to the DSP */
 116        ret = sof_ipc_tx_message(sdev->ipc, stream.hdr.cmd, &stream,
 117                                 sizeof(stream), &reply, sizeof(reply));
 118        if (!ret)
 119                spcm->prepared[substream->stream] = false;
 120
 121        return ret;
 122}
 123
 124static int sof_pcm_setup_connected_widgets(struct snd_sof_dev *sdev,
 125                                           struct snd_soc_pcm_runtime *rtd,
 126                                           struct snd_sof_pcm *spcm, int dir)
 127{
 128        struct snd_soc_dai *dai;
 129        int ret, j;
 130
 131        /* query DAPM for list of connected widgets and set them up */
 132        for_each_rtd_cpu_dais(rtd, j, dai) {
 133                struct snd_soc_dapm_widget_list *list;
 134
 135                ret = snd_soc_dapm_dai_get_connected_widgets(dai, dir, &list,
 136                                                             dpcm_end_walk_at_be);
 137                if (ret < 0) {
 138                        dev_err(sdev->dev, "error: dai %s has no valid %s path\n", dai->name,
 139                                dir == SNDRV_PCM_STREAM_PLAYBACK ? "playback" : "capture");
 140                        return ret;
 141                }
 142
 143                spcm->stream[dir].list = list;
 144
 145                ret = sof_widget_list_setup(sdev, spcm, dir);
 146                if (ret < 0) {
 147                        dev_err(sdev->dev, "error: failed widget list set up for pcm %d dir %d\n",
 148                                spcm->pcm.pcm_id, dir);
 149                        spcm->stream[dir].list = NULL;
 150                        snd_soc_dapm_dai_free_widgets(&list);
 151                        return ret;
 152                }
 153        }
 154
 155        return 0;
 156}
 157
 158static int sof_pcm_hw_params(struct snd_soc_component *component,
 159                             struct snd_pcm_substream *substream,
 160                             struct snd_pcm_hw_params *params)
 161{
 162        struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
 163        struct snd_pcm_runtime *runtime = substream->runtime;
 164        struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(component);
 165        struct snd_sof_pcm *spcm;
 166        struct sof_ipc_pcm_params pcm;
 167        struct sof_ipc_pcm_params_reply ipc_params_reply;
 168        int ret;
 169
 170        /* nothing to do for BE */
 171        if (rtd->dai_link->no_pcm)
 172                return 0;
 173
 174        spcm = snd_sof_find_spcm_dai(component, rtd);
 175        if (!spcm)
 176                return -EINVAL;
 177
 178        /*
 179         * Handle repeated calls to hw_params() without free_pcm() in
 180         * between. At least ALSA OSS emulation depends on this.
 181         */
 182        if (spcm->prepared[substream->stream]) {
 183                ret = sof_pcm_dsp_pcm_free(substream, sdev, spcm);
 184                if (ret < 0)
 185                        return ret;
 186        }
 187
 188        dev_dbg(component->dev, "pcm: hw params stream %d dir %d\n",
 189                spcm->pcm.pcm_id, substream->stream);
 190
 191        memset(&pcm, 0, sizeof(pcm));
 192
 193        /* create compressed page table for audio firmware */
 194        if (runtime->buffer_changed) {
 195                ret = create_page_table(component, substream, runtime->dma_area,
 196                                        runtime->dma_bytes);
 197                if (ret < 0)
 198                        return ret;
 199        }
 200
 201        /* number of pages should be rounded up */
 202        pcm.params.buffer.pages = PFN_UP(runtime->dma_bytes);
 203
 204        /* set IPC PCM parameters */
 205        pcm.hdr.size = sizeof(pcm);
 206        pcm.hdr.cmd = SOF_IPC_GLB_STREAM_MSG | SOF_IPC_STREAM_PCM_PARAMS;
 207        pcm.comp_id = spcm->stream[substream->stream].comp_id;
 208        pcm.params.hdr.size = sizeof(pcm.params);
 209        pcm.params.buffer.phy_addr =
 210                spcm->stream[substream->stream].page_table.addr;
 211        pcm.params.buffer.size = runtime->dma_bytes;
 212        pcm.params.direction = substream->stream;
 213        pcm.params.sample_valid_bytes = params_width(params) >> 3;
 214        pcm.params.buffer_fmt = SOF_IPC_BUFFER_INTERLEAVED;
 215        pcm.params.rate = params_rate(params);
 216        pcm.params.channels = params_channels(params);
 217        pcm.params.host_period_bytes = params_period_bytes(params);
 218
 219        /* container size */
 220        ret = snd_pcm_format_physical_width(params_format(params));
 221        if (ret < 0)
 222                return ret;
 223        pcm.params.sample_container_bytes = ret >> 3;
 224
 225        /* format */
 226        switch (params_format(params)) {
 227        case SNDRV_PCM_FORMAT_S16:
 228                pcm.params.frame_fmt = SOF_IPC_FRAME_S16_LE;
 229                break;
 230        case SNDRV_PCM_FORMAT_S24:
 231                pcm.params.frame_fmt = SOF_IPC_FRAME_S24_4LE;
 232                break;
 233        case SNDRV_PCM_FORMAT_S32:
 234                pcm.params.frame_fmt = SOF_IPC_FRAME_S32_LE;
 235                break;
 236        case SNDRV_PCM_FORMAT_FLOAT:
 237                pcm.params.frame_fmt = SOF_IPC_FRAME_FLOAT;
 238                break;
 239        default:
 240                return -EINVAL;
 241        }
 242
 243        /* firmware already configured host stream */
 244        ret = snd_sof_pcm_platform_hw_params(sdev,
 245                                             substream,
 246                                             params,
 247                                             &pcm.params);
 248        if (ret < 0) {
 249                dev_err(component->dev, "error: platform hw params failed\n");
 250                return ret;
 251        }
 252
 253        dev_dbg(component->dev, "stream_tag %d", pcm.params.stream_tag);
 254
 255        /* if this is a repeated hw_params without hw_free, skip setting up widgets */
 256        if (!spcm->stream[substream->stream].list) {
 257                ret = sof_pcm_setup_connected_widgets(sdev, rtd, spcm, substream->stream);
 258                if (ret < 0)
 259                        return ret;
 260        }
 261
 262        /* send hw_params IPC to the DSP */
 263        ret = sof_ipc_tx_message(sdev->ipc, pcm.hdr.cmd, &pcm, sizeof(pcm),
 264                                 &ipc_params_reply, sizeof(ipc_params_reply));
 265        if (ret < 0) {
 266                dev_err(component->dev, "error: hw params ipc failed for stream %d\n",
 267                        pcm.params.stream_tag);
 268                return ret;
 269        }
 270
 271        ret = sof_pcm_dsp_params(spcm, substream, &ipc_params_reply);
 272        if (ret < 0)
 273                return ret;
 274
 275        spcm->prepared[substream->stream] = true;
 276
 277        /* save pcm hw_params */
 278        memcpy(&spcm->params[substream->stream], params, sizeof(*params));
 279
 280        return ret;
 281}
 282
 283static int sof_pcm_hw_free(struct snd_soc_component *component,
 284                           struct snd_pcm_substream *substream)
 285{
 286        struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
 287        struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(component);
 288        struct snd_sof_pcm *spcm;
 289        int ret, err = 0;
 290
 291        /* nothing to do for BE */
 292        if (rtd->dai_link->no_pcm)
 293                return 0;
 294
 295        spcm = snd_sof_find_spcm_dai(component, rtd);
 296        if (!spcm)
 297                return -EINVAL;
 298
 299        dev_dbg(component->dev, "pcm: free stream %d dir %d\n",
 300                spcm->pcm.pcm_id, substream->stream);
 301
 302        if (spcm->prepared[substream->stream]) {
 303                ret = sof_pcm_dsp_pcm_free(substream, sdev, spcm);
 304                if (ret < 0)
 305                        err = ret;
 306        }
 307
 308        ret = sof_widget_list_free(sdev, spcm, substream->stream);
 309        if (ret < 0)
 310                err = ret;
 311
 312        cancel_work_sync(&spcm->stream[substream->stream].period_elapsed_work);
 313
 314        ret = snd_sof_pcm_platform_hw_free(sdev, substream);
 315        if (ret < 0) {
 316                dev_err(component->dev, "error: platform hw free failed\n");
 317                err = ret;
 318        }
 319
 320        return err;
 321}
 322
 323static int sof_pcm_prepare(struct snd_soc_component *component,
 324                           struct snd_pcm_substream *substream)
 325{
 326        struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
 327        struct snd_sof_pcm *spcm;
 328        int ret;
 329
 330        /* nothing to do for BE */
 331        if (rtd->dai_link->no_pcm)
 332                return 0;
 333
 334        spcm = snd_sof_find_spcm_dai(component, rtd);
 335        if (!spcm)
 336                return -EINVAL;
 337
 338        if (spcm->prepared[substream->stream])
 339                return 0;
 340
 341        dev_dbg(component->dev, "pcm: prepare stream %d dir %d\n",
 342                spcm->pcm.pcm_id, substream->stream);
 343
 344        /* set hw_params */
 345        ret = sof_pcm_hw_params(component,
 346                                substream, &spcm->params[substream->stream]);
 347        if (ret < 0) {
 348                dev_err(component->dev,
 349                        "error: set pcm hw_params after resume\n");
 350                return ret;
 351        }
 352
 353        return 0;
 354}
 355
 356/*
 357 * FE dai link trigger actions are always executed in non-atomic context because
 358 * they involve IPC's.
 359 */
 360static int sof_pcm_trigger(struct snd_soc_component *component,
 361                           struct snd_pcm_substream *substream, int cmd)
 362{
 363        struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
 364        struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(component);
 365        struct snd_sof_pcm *spcm;
 366        struct sof_ipc_stream stream;
 367        struct sof_ipc_reply reply;
 368        bool reset_hw_params = false;
 369        bool free_widget_list = false;
 370        bool ipc_first = false;
 371        int ret;
 372
 373        /* nothing to do for BE */
 374        if (rtd->dai_link->no_pcm)
 375                return 0;
 376
 377        spcm = snd_sof_find_spcm_dai(component, rtd);
 378        if (!spcm)
 379                return -EINVAL;
 380
 381        dev_dbg(component->dev, "pcm: trigger stream %d dir %d cmd %d\n",
 382                spcm->pcm.pcm_id, substream->stream, cmd);
 383
 384        stream.hdr.size = sizeof(stream);
 385        stream.hdr.cmd = SOF_IPC_GLB_STREAM_MSG;
 386        stream.comp_id = spcm->stream[substream->stream].comp_id;
 387
 388        switch (cmd) {
 389        case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
 390                stream.hdr.cmd |= SOF_IPC_STREAM_TRIG_PAUSE;
 391                ipc_first = true;
 392                break;
 393        case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
 394                stream.hdr.cmd |= SOF_IPC_STREAM_TRIG_RELEASE;
 395                break;
 396        case SNDRV_PCM_TRIGGER_RESUME:
 397                if (spcm->stream[substream->stream].suspend_ignored) {
 398                        /*
 399                         * this case will be triggered when INFO_RESUME is
 400                         * supported, no need to resume streams that remained
 401                         * enabled in D0ix.
 402                         */
 403                        spcm->stream[substream->stream].suspend_ignored = false;
 404                        return 0;
 405                }
 406
 407                /* set up hw_params */
 408                ret = sof_pcm_prepare(component, substream);
 409                if (ret < 0) {
 410                        dev_err(component->dev,
 411                                "error: failed to set up hw_params upon resume\n");
 412                        return ret;
 413                }
 414
 415                fallthrough;
 416        case SNDRV_PCM_TRIGGER_START:
 417                if (spcm->stream[substream->stream].suspend_ignored) {
 418                        /*
 419                         * This case will be triggered when INFO_RESUME is
 420                         * not supported, no need to re-start streams that
 421                         * remained enabled in D0ix.
 422                         */
 423                        spcm->stream[substream->stream].suspend_ignored = false;
 424                        return 0;
 425                }
 426                stream.hdr.cmd |= SOF_IPC_STREAM_TRIG_START;
 427                break;
 428        case SNDRV_PCM_TRIGGER_SUSPEND:
 429                if (sdev->system_suspend_target == SOF_SUSPEND_S0IX &&
 430                    spcm->stream[substream->stream].d0i3_compatible) {
 431                        /*
 432                         * trap the event, not sending trigger stop to
 433                         * prevent the FW pipelines from being stopped,
 434                         * and mark the flag to ignore the upcoming DAPM
 435                         * PM events.
 436                         */
 437                        spcm->stream[substream->stream].suspend_ignored = true;
 438                        return 0;
 439                }
 440                free_widget_list = true;
 441                fallthrough;
 442        case SNDRV_PCM_TRIGGER_STOP:
 443                stream.hdr.cmd |= SOF_IPC_STREAM_TRIG_STOP;
 444                ipc_first = true;
 445                reset_hw_params = true;
 446                break;
 447        default:
 448                dev_err(component->dev, "error: unhandled trigger cmd %d\n",
 449                        cmd);
 450                return -EINVAL;
 451        }
 452
 453        /*
 454         * DMA and IPC sequence is different for start and stop. Need to send
 455         * STOP IPC before stop DMA
 456         */
 457        if (!ipc_first)
 458                snd_sof_pcm_platform_trigger(sdev, substream, cmd);
 459
 460        /* send IPC to the DSP */
 461        ret = sof_ipc_tx_message(sdev->ipc, stream.hdr.cmd, &stream,
 462                                 sizeof(stream), &reply, sizeof(reply));
 463
 464        /* need to STOP DMA even if STOP IPC failed */
 465        if (ipc_first)
 466                snd_sof_pcm_platform_trigger(sdev, substream, cmd);
 467
 468        /* free PCM if reset_hw_params is set and the STOP IPC is successful */
 469        if (!ret && reset_hw_params) {
 470                ret = sof_pcm_dsp_pcm_free(substream, sdev, spcm);
 471                if (ret < 0)
 472                        return ret;
 473
 474                /* free widget list only for SUSPEND trigger */
 475                if (free_widget_list)
 476                        ret = sof_widget_list_free(sdev, spcm, substream->stream);
 477        }
 478
 479        return ret;
 480}
 481
 482static snd_pcm_uframes_t sof_pcm_pointer(struct snd_soc_component *component,
 483                                         struct snd_pcm_substream *substream)
 484{
 485        struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
 486        struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(component);
 487        struct snd_sof_pcm *spcm;
 488        snd_pcm_uframes_t host, dai;
 489
 490        /* nothing to do for BE */
 491        if (rtd->dai_link->no_pcm)
 492                return 0;
 493
 494        /* use dsp ops pointer callback directly if set */
 495        if (sof_ops(sdev)->pcm_pointer)
 496                return sof_ops(sdev)->pcm_pointer(sdev, substream);
 497
 498        spcm = snd_sof_find_spcm_dai(component, rtd);
 499        if (!spcm)
 500                return -EINVAL;
 501
 502        /* read position from DSP */
 503        host = bytes_to_frames(substream->runtime,
 504                               spcm->stream[substream->stream].posn.host_posn);
 505        dai = bytes_to_frames(substream->runtime,
 506                              spcm->stream[substream->stream].posn.dai_posn);
 507
 508        dev_vdbg(component->dev,
 509                 "PCM: stream %d dir %d DMA position %lu DAI position %lu\n",
 510                 spcm->pcm.pcm_id, substream->stream, host, dai);
 511
 512        return host;
 513}
 514
 515static int sof_pcm_open(struct snd_soc_component *component,
 516                        struct snd_pcm_substream *substream)
 517{
 518        struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
 519        struct snd_pcm_runtime *runtime = substream->runtime;
 520        struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(component);
 521        const struct snd_sof_dsp_ops *ops = sof_ops(sdev);
 522        struct snd_sof_pcm *spcm;
 523        struct snd_soc_tplg_stream_caps *caps;
 524        int ret;
 525
 526        /* nothing to do for BE */
 527        if (rtd->dai_link->no_pcm)
 528                return 0;
 529
 530        spcm = snd_sof_find_spcm_dai(component, rtd);
 531        if (!spcm)
 532                return -EINVAL;
 533
 534        dev_dbg(component->dev, "pcm: open stream %d dir %d\n",
 535                spcm->pcm.pcm_id, substream->stream);
 536
 537
 538        caps = &spcm->pcm.caps[substream->stream];
 539
 540        /* set runtime config */
 541        runtime->hw.info = ops->hw_info; /* platform-specific */
 542
 543        /* set any runtime constraints based on topology */
 544        runtime->hw.formats = le64_to_cpu(caps->formats);
 545        runtime->hw.period_bytes_min = le32_to_cpu(caps->period_size_min);
 546        runtime->hw.period_bytes_max = le32_to_cpu(caps->period_size_max);
 547        runtime->hw.periods_min = le32_to_cpu(caps->periods_min);
 548        runtime->hw.periods_max = le32_to_cpu(caps->periods_max);
 549
 550        /*
 551         * caps->buffer_size_min is not used since the
 552         * snd_pcm_hardware structure only defines buffer_bytes_max
 553         */
 554        runtime->hw.buffer_bytes_max = le32_to_cpu(caps->buffer_size_max);
 555
 556        dev_dbg(component->dev, "period min %zd max %zd bytes\n",
 557                runtime->hw.period_bytes_min,
 558                runtime->hw.period_bytes_max);
 559        dev_dbg(component->dev, "period count %d max %d\n",
 560                runtime->hw.periods_min,
 561                runtime->hw.periods_max);
 562        dev_dbg(component->dev, "buffer max %zd bytes\n",
 563                runtime->hw.buffer_bytes_max);
 564
 565        /* set wait time - TODO: come from topology */
 566        substream->wait_time = 500;
 567
 568        spcm->stream[substream->stream].posn.host_posn = 0;
 569        spcm->stream[substream->stream].posn.dai_posn = 0;
 570        spcm->stream[substream->stream].substream = substream;
 571        spcm->prepared[substream->stream] = false;
 572
 573        ret = snd_sof_pcm_platform_open(sdev, substream);
 574        if (ret < 0)
 575                dev_err(component->dev, "error: pcm open failed %d\n", ret);
 576
 577        return ret;
 578}
 579
 580static int sof_pcm_close(struct snd_soc_component *component,
 581                         struct snd_pcm_substream *substream)
 582{
 583        struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
 584        struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(component);
 585        struct snd_sof_pcm *spcm;
 586        int err;
 587
 588        /* nothing to do for BE */
 589        if (rtd->dai_link->no_pcm)
 590                return 0;
 591
 592        spcm = snd_sof_find_spcm_dai(component, rtd);
 593        if (!spcm)
 594                return -EINVAL;
 595
 596        dev_dbg(component->dev, "pcm: close stream %d dir %d\n",
 597                spcm->pcm.pcm_id, substream->stream);
 598
 599        err = snd_sof_pcm_platform_close(sdev, substream);
 600        if (err < 0) {
 601                dev_err(component->dev, "error: pcm close failed %d\n",
 602                        err);
 603                /*
 604                 * keep going, no point in preventing the close
 605                 * from happening
 606                 */
 607        }
 608
 609        return 0;
 610}
 611
 612/*
 613 * Pre-allocate playback/capture audio buffer pages.
 614 * no need to explicitly release memory preallocated by sof_pcm_new in pcm_free
 615 * snd_pcm_lib_preallocate_free_for_all() is called by the core.
 616 */
 617static int sof_pcm_new(struct snd_soc_component *component,
 618                       struct snd_soc_pcm_runtime *rtd)
 619{
 620        struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(component);
 621        struct snd_sof_pcm *spcm;
 622        struct snd_pcm *pcm = rtd->pcm;
 623        struct snd_soc_tplg_stream_caps *caps;
 624        int stream = SNDRV_PCM_STREAM_PLAYBACK;
 625
 626        /* find SOF PCM for this RTD */
 627        spcm = snd_sof_find_spcm_dai(component, rtd);
 628        if (!spcm) {
 629                dev_warn(component->dev, "warn: can't find PCM with DAI ID %d\n",
 630                         rtd->dai_link->id);
 631                return 0;
 632        }
 633
 634        dev_dbg(component->dev, "creating new PCM %s\n", spcm->pcm.pcm_name);
 635
 636        /* do we need to pre-allocate playback audio buffer pages */
 637        if (!spcm->pcm.playback)
 638                goto capture;
 639
 640        caps = &spcm->pcm.caps[stream];
 641
 642        /* pre-allocate playback audio buffer pages */
 643        dev_dbg(component->dev,
 644                "spcm: allocate %s playback DMA buffer size 0x%x max 0x%x\n",
 645                caps->name, caps->buffer_size_min, caps->buffer_size_max);
 646
 647        if (!pcm->streams[stream].substream) {
 648                dev_err(component->dev, "error: NULL playback substream!\n");
 649                return -EINVAL;
 650        }
 651
 652        snd_pcm_set_managed_buffer(pcm->streams[stream].substream,
 653                                   SNDRV_DMA_TYPE_DEV_SG, sdev->dev,
 654                                   0, le32_to_cpu(caps->buffer_size_max));
 655capture:
 656        stream = SNDRV_PCM_STREAM_CAPTURE;
 657
 658        /* do we need to pre-allocate capture audio buffer pages */
 659        if (!spcm->pcm.capture)
 660                return 0;
 661
 662        caps = &spcm->pcm.caps[stream];
 663
 664        /* pre-allocate capture audio buffer pages */
 665        dev_dbg(component->dev,
 666                "spcm: allocate %s capture DMA buffer size 0x%x max 0x%x\n",
 667                caps->name, caps->buffer_size_min, caps->buffer_size_max);
 668
 669        if (!pcm->streams[stream].substream) {
 670                dev_err(component->dev, "error: NULL capture substream!\n");
 671                return -EINVAL;
 672        }
 673
 674        snd_pcm_set_managed_buffer(pcm->streams[stream].substream,
 675                                   SNDRV_DMA_TYPE_DEV_SG, sdev->dev,
 676                                   0, le32_to_cpu(caps->buffer_size_max));
 677
 678        return 0;
 679}
 680
 681static void ssp_dai_config_pcm_params_match(struct snd_sof_dev *sdev, const char *link_name,
 682                                            struct snd_pcm_hw_params *params)
 683{
 684        struct sof_ipc_dai_config *config;
 685        struct snd_sof_dai *dai;
 686        int i;
 687
 688        /*
 689         * Search for all matching DAIs as we can have both playback and capture DAI
 690         * associated with the same link.
 691         */
 692        list_for_each_entry(dai, &sdev->dai_list, list) {
 693                if (!dai->name || strcmp(link_name, dai->name))
 694                        continue;
 695                for (i = 0; i < dai->number_configs; i++) {
 696                        config = &dai->dai_config[i];
 697                        if (config->ssp.fsync_rate == params_rate(params)) {
 698                                dev_dbg(sdev->dev, "DAI config %d matches pcm hw params\n", i);
 699                                dai->current_config = i;
 700                                break;
 701                        }
 702                }
 703        }
 704}
 705
 706/* fixup the BE DAI link to match any values from topology */
 707int sof_pcm_dai_link_fixup(struct snd_soc_pcm_runtime *rtd, struct snd_pcm_hw_params *params)
 708{
 709        struct snd_interval *rate = hw_param_interval(params,
 710                        SNDRV_PCM_HW_PARAM_RATE);
 711        struct snd_interval *channels = hw_param_interval(params,
 712                                                SNDRV_PCM_HW_PARAM_CHANNELS);
 713        struct snd_mask *fmt = hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT);
 714        struct snd_soc_component *component =
 715                snd_soc_rtdcom_lookup(rtd, SOF_AUDIO_PCM_DRV_NAME);
 716        struct snd_sof_dai *dai =
 717                snd_sof_find_dai(component, (char *)rtd->dai_link->name);
 718        struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(component);
 719        struct snd_soc_dpcm *dpcm;
 720
 721        /* no topology exists for this BE, try a common configuration */
 722        if (!dai) {
 723                dev_warn(component->dev,
 724                         "warning: no topology found for BE DAI %s config\n",
 725                         rtd->dai_link->name);
 726
 727                /*  set 48k, stereo, 16bits by default */
 728                rate->min = 48000;
 729                rate->max = 48000;
 730
 731                channels->min = 2;
 732                channels->max = 2;
 733
 734                snd_mask_none(fmt);
 735                snd_mask_set_format(fmt, SNDRV_PCM_FORMAT_S16_LE);
 736
 737                return 0;
 738        }
 739
 740        /* read format from topology */
 741        snd_mask_none(fmt);
 742
 743        switch (dai->comp_dai.config.frame_fmt) {
 744        case SOF_IPC_FRAME_S16_LE:
 745                snd_mask_set_format(fmt, SNDRV_PCM_FORMAT_S16_LE);
 746                break;
 747        case SOF_IPC_FRAME_S24_4LE:
 748                snd_mask_set_format(fmt, SNDRV_PCM_FORMAT_S24_LE);
 749                break;
 750        case SOF_IPC_FRAME_S32_LE:
 751                snd_mask_set_format(fmt, SNDRV_PCM_FORMAT_S32_LE);
 752                break;
 753        default:
 754                dev_err(component->dev, "error: No available DAI format!\n");
 755                return -EINVAL;
 756        }
 757
 758        /* read rate and channels from topology */
 759        switch (dai->dai_config->type) {
 760        case SOF_DAI_INTEL_SSP:
 761                /* search for config to pcm params match, if not found use default */
 762                ssp_dai_config_pcm_params_match(sdev, (char *)rtd->dai_link->name, params);
 763
 764                rate->min = dai->dai_config[dai->current_config].ssp.fsync_rate;
 765                rate->max = dai->dai_config[dai->current_config].ssp.fsync_rate;
 766                channels->min = dai->dai_config[dai->current_config].ssp.tdm_slots;
 767                channels->max = dai->dai_config[dai->current_config].ssp.tdm_slots;
 768
 769                dev_dbg(component->dev,
 770                        "rate_min: %d rate_max: %d\n", rate->min, rate->max);
 771                dev_dbg(component->dev,
 772                        "channels_min: %d channels_max: %d\n",
 773                        channels->min, channels->max);
 774
 775                break;
 776        case SOF_DAI_INTEL_DMIC:
 777                /* DMIC only supports 16 or 32 bit formats */
 778                if (dai->comp_dai.config.frame_fmt == SOF_IPC_FRAME_S24_4LE) {
 779                        dev_err(component->dev,
 780                                "error: invalid fmt %d for DAI type %d\n",
 781                                dai->comp_dai.config.frame_fmt,
 782                                dai->dai_config->type);
 783                }
 784                break;
 785        case SOF_DAI_INTEL_HDA:
 786                /*
 787                 * HDAudio does not follow the default trigger
 788                 * sequence due to firmware implementation
 789                 */
 790                for_each_dpcm_fe(rtd, SNDRV_PCM_STREAM_PLAYBACK, dpcm) {
 791                        struct snd_soc_pcm_runtime *fe = dpcm->fe;
 792
 793                        fe->dai_link->trigger[SNDRV_PCM_STREAM_PLAYBACK] =
 794                                SND_SOC_DPCM_TRIGGER_POST;
 795                }
 796                break;
 797        case SOF_DAI_INTEL_ALH:
 798                /*
 799                 * Dai could run with different channel count compared with
 800                 * front end, so get dai channel count from topology
 801                 */
 802                channels->min = dai->dai_config->alh.channels;
 803                channels->max = dai->dai_config->alh.channels;
 804                break;
 805        case SOF_DAI_IMX_ESAI:
 806                rate->min = dai->dai_config->esai.fsync_rate;
 807                rate->max = dai->dai_config->esai.fsync_rate;
 808                channels->min = dai->dai_config->esai.tdm_slots;
 809                channels->max = dai->dai_config->esai.tdm_slots;
 810
 811                dev_dbg(component->dev,
 812                        "rate_min: %d rate_max: %d\n", rate->min, rate->max);
 813                dev_dbg(component->dev,
 814                        "channels_min: %d channels_max: %d\n",
 815                        channels->min, channels->max);
 816                break;
 817        case SOF_DAI_IMX_SAI:
 818                rate->min = dai->dai_config->sai.fsync_rate;
 819                rate->max = dai->dai_config->sai.fsync_rate;
 820                channels->min = dai->dai_config->sai.tdm_slots;
 821                channels->max = dai->dai_config->sai.tdm_slots;
 822
 823                dev_dbg(component->dev,
 824                        "rate_min: %d rate_max: %d\n", rate->min, rate->max);
 825                dev_dbg(component->dev,
 826                        "channels_min: %d channels_max: %d\n",
 827                        channels->min, channels->max);
 828                break;
 829        default:
 830                dev_err(component->dev, "error: invalid DAI type %d\n",
 831                        dai->dai_config->type);
 832                break;
 833        }
 834
 835        return 0;
 836}
 837EXPORT_SYMBOL(sof_pcm_dai_link_fixup);
 838
 839static int sof_pcm_probe(struct snd_soc_component *component)
 840{
 841        struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(component);
 842        struct snd_sof_pdata *plat_data = sdev->pdata;
 843        const char *tplg_filename;
 844        int ret;
 845
 846        /* load the default topology */
 847        sdev->component = component;
 848
 849        tplg_filename = devm_kasprintf(sdev->dev, GFP_KERNEL,
 850                                       "%s/%s",
 851                                       plat_data->tplg_filename_prefix,
 852                                       plat_data->tplg_filename);
 853        if (!tplg_filename)
 854                return -ENOMEM;
 855
 856        ret = snd_sof_load_topology(component, tplg_filename);
 857        if (ret < 0) {
 858                dev_err(component->dev, "error: failed to load DSP topology %d\n",
 859                        ret);
 860                return ret;
 861        }
 862
 863        return ret;
 864}
 865
 866static void sof_pcm_remove(struct snd_soc_component *component)
 867{
 868        /* remove topology */
 869        snd_soc_tplg_component_remove(component);
 870}
 871
 872void snd_sof_new_platform_drv(struct snd_sof_dev *sdev)
 873{
 874        struct snd_soc_component_driver *pd = &sdev->plat_drv;
 875        struct snd_sof_pdata *plat_data = sdev->pdata;
 876        const char *drv_name;
 877
 878        drv_name = plat_data->machine->drv_name;
 879
 880        pd->name = "sof-audio-component";
 881        pd->probe = sof_pcm_probe;
 882        pd->remove = sof_pcm_remove;
 883        pd->open = sof_pcm_open;
 884        pd->close = sof_pcm_close;
 885        pd->hw_params = sof_pcm_hw_params;
 886        pd->prepare = sof_pcm_prepare;
 887        pd->hw_free = sof_pcm_hw_free;
 888        pd->trigger = sof_pcm_trigger;
 889        pd->pointer = sof_pcm_pointer;
 890
 891#if IS_ENABLED(CONFIG_SND_SOC_SOF_DEBUG_PROBES)
 892        pd->compress_ops = &sof_probe_compressed_ops;
 893#endif
 894        pd->pcm_construct = sof_pcm_new;
 895        pd->ignore_machine = drv_name;
 896        pd->be_hw_params_fixup = sof_pcm_dai_link_fixup;
 897        pd->be_pcm_base = SOF_BE_PCM_BASE;
 898        pd->use_dai_pcm_id = true;
 899        pd->topology_name_prefix = "sof";
 900
 901         /* increment module refcount when a pcm is opened */
 902        pd->module_get_upon_open = 1;
 903}
 904