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