linux/sound/soc/sof/compress.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) 2019-2020 Intel Corporation. All rights reserved.
   7//
   8// Author: Cezary Rojewski <cezary.rojewski@intel.com>
   9//
  10
  11#include <sound/soc.h>
  12#include "compress.h"
  13#include "ops.h"
  14#include "probe.h"
  15
  16const struct snd_compress_ops sof_probe_compressed_ops = {
  17        .copy           = sof_probe_compr_copy,
  18};
  19EXPORT_SYMBOL(sof_probe_compressed_ops);
  20
  21int sof_probe_compr_open(struct snd_compr_stream *cstream,
  22                struct snd_soc_dai *dai)
  23{
  24        struct snd_sof_dev *sdev =
  25                                snd_soc_component_get_drvdata(dai->component);
  26        int ret;
  27
  28        ret = snd_sof_probe_compr_assign(sdev, cstream, dai);
  29        if (ret < 0) {
  30                dev_err(dai->dev, "Failed to assign probe stream: %d\n", ret);
  31                return ret;
  32        }
  33
  34        sdev->extractor_stream_tag = ret;
  35        return 0;
  36}
  37EXPORT_SYMBOL(sof_probe_compr_open);
  38
  39int sof_probe_compr_free(struct snd_compr_stream *cstream,
  40                struct snd_soc_dai *dai)
  41{
  42        struct snd_sof_dev *sdev =
  43                                snd_soc_component_get_drvdata(dai->component);
  44        struct sof_probe_point_desc *desc;
  45        size_t num_desc;
  46        int i, ret;
  47
  48        /* disconnect all probe points */
  49        ret = sof_ipc_probe_points_info(sdev, &desc, &num_desc);
  50        if (ret < 0) {
  51                dev_err(dai->dev, "Failed to get probe points: %d\n", ret);
  52                goto exit;
  53        }
  54
  55        for (i = 0; i < num_desc; i++)
  56                sof_ipc_probe_points_remove(sdev, &desc[i].buffer_id, 1);
  57        kfree(desc);
  58
  59exit:
  60        ret = sof_ipc_probe_deinit(sdev);
  61        if (ret < 0)
  62                dev_err(dai->dev, "Failed to deinit probe: %d\n", ret);
  63
  64        sdev->extractor_stream_tag = SOF_PROBE_INVALID_NODE_ID;
  65        snd_compr_free_pages(cstream);
  66
  67        return snd_sof_probe_compr_free(sdev, cstream, dai);
  68}
  69EXPORT_SYMBOL(sof_probe_compr_free);
  70
  71int sof_probe_compr_set_params(struct snd_compr_stream *cstream,
  72                struct snd_compr_params *params, struct snd_soc_dai *dai)
  73{
  74        struct snd_compr_runtime *rtd = cstream->runtime;
  75        struct snd_sof_dev *sdev =
  76                                snd_soc_component_get_drvdata(dai->component);
  77        int ret;
  78
  79        cstream->dma_buffer.dev.type = SNDRV_DMA_TYPE_DEV_SG;
  80        cstream->dma_buffer.dev.dev = sdev->dev;
  81        ret = snd_compr_malloc_pages(cstream, rtd->buffer_size);
  82        if (ret < 0)
  83                return ret;
  84
  85        ret = snd_sof_probe_compr_set_params(sdev, cstream, params, dai);
  86        if (ret < 0)
  87                return ret;
  88
  89        ret = sof_ipc_probe_init(sdev, sdev->extractor_stream_tag,
  90                                 rtd->dma_bytes);
  91        if (ret < 0) {
  92                dev_err(dai->dev, "Failed to init probe: %d\n", ret);
  93                return ret;
  94        }
  95
  96        return 0;
  97}
  98EXPORT_SYMBOL(sof_probe_compr_set_params);
  99
 100int sof_probe_compr_trigger(struct snd_compr_stream *cstream, int cmd,
 101                struct snd_soc_dai *dai)
 102{
 103        struct snd_sof_dev *sdev =
 104                                snd_soc_component_get_drvdata(dai->component);
 105
 106        return snd_sof_probe_compr_trigger(sdev, cstream, cmd, dai);
 107}
 108EXPORT_SYMBOL(sof_probe_compr_trigger);
 109
 110int sof_probe_compr_pointer(struct snd_compr_stream *cstream,
 111                struct snd_compr_tstamp *tstamp, struct snd_soc_dai *dai)
 112{
 113        struct snd_sof_dev *sdev =
 114                                snd_soc_component_get_drvdata(dai->component);
 115
 116        return snd_sof_probe_compr_pointer(sdev, cstream, tstamp, dai);
 117}
 118EXPORT_SYMBOL(sof_probe_compr_pointer);
 119
 120int sof_probe_compr_copy(struct snd_soc_component *component,
 121                         struct snd_compr_stream *cstream,
 122                         char __user *buf, size_t count)
 123{
 124        struct snd_compr_runtime *rtd = cstream->runtime;
 125        unsigned int offset, n;
 126        void *ptr;
 127        int ret;
 128
 129        if (count > rtd->buffer_size)
 130                count = rtd->buffer_size;
 131
 132        div_u64_rem(rtd->total_bytes_transferred, rtd->buffer_size, &offset);
 133        ptr = rtd->dma_area + offset;
 134        n = rtd->buffer_size - offset;
 135
 136        if (count < n) {
 137                ret = copy_to_user(buf, ptr, count);
 138        } else {
 139                ret = copy_to_user(buf, ptr, n);
 140                ret += copy_to_user(buf + n, rtd->dma_area, count - n);
 141        }
 142
 143        if (ret)
 144                return count - ret;
 145        return count;
 146}
 147EXPORT_SYMBOL(sof_probe_compr_copy);
 148