66// Amadeusz Slawinski <[email protected] > 77//
88
9+ #include <sound/compress_driver.h>
10+ #include <sound/hdaudio_ext.h>
11+ #include <sound/hdaudio.h>
12+ #include <sound/soc.h>
913#include "avs.h"
1014#include "messages.h"
1115
12- __maybe_unused
1316static int avs_dsp_init_probe (struct avs_dev * adev , union avs_connector_node_id node_id ,
1417 size_t buffer_size )
15-
1618{
1719 struct avs_probe_cfg cfg = {{0 }};
1820 struct avs_module_entry mentry ;
@@ -34,7 +36,6 @@ static int avs_dsp_init_probe(struct avs_dev *adev, union avs_connector_node_id
3436 sizeof (cfg ), & dummy );
3537}
3638
37- __maybe_unused
3839static void avs_dsp_delete_probe (struct avs_dev * adev )
3940{
4041 struct avs_module_entry mentry ;
@@ -44,3 +45,220 @@ static void avs_dsp_delete_probe(struct avs_dev *adev)
4445 /* There is only ever one probe module instance. */
4546 avs_dsp_delete_module (adev , mentry .module_id , 0 , INVALID_PIPELINE_ID , 0 );
4647}
48+
49+ static inline struct hdac_ext_stream * avs_compr_get_host_stream (struct snd_compr_stream * cstream )
50+ {
51+ return cstream -> runtime -> private_data ;
52+ }
53+
54+ static int avs_probe_compr_open (struct snd_compr_stream * cstream , struct snd_soc_dai * dai )
55+ {
56+ struct avs_dev * adev = to_avs_dev (dai -> dev );
57+ struct hdac_bus * bus = & adev -> base .core ;
58+ struct hdac_ext_stream * host_stream ;
59+
60+ if (adev -> extractor ) {
61+ dev_err (dai -> dev , "Cannot open more than one extractor stream\n" );
62+ return - EEXIST ;
63+ }
64+
65+ host_stream = snd_hdac_ext_cstream_assign (bus , cstream );
66+ if (!host_stream ) {
67+ dev_err (dai -> dev , "Failed to assign HDAudio stream for extraction\n" );
68+ return - EBUSY ;
69+ }
70+
71+ adev -> extractor = host_stream ;
72+ hdac_stream (host_stream )-> curr_pos = 0 ;
73+ cstream -> runtime -> private_data = host_stream ;
74+
75+ return 0 ;
76+ }
77+
78+ static int avs_probe_compr_free (struct snd_compr_stream * cstream , struct snd_soc_dai * dai )
79+ {
80+ struct hdac_ext_stream * host_stream = avs_compr_get_host_stream (cstream );
81+ struct avs_dev * adev = to_avs_dev (dai -> dev );
82+ struct avs_probe_point_desc * desc ;
83+ /* Extractor node identifier. */
84+ unsigned int vindex = INVALID_NODE_ID .vindex ;
85+ size_t num_desc ;
86+ int i , ret ;
87+
88+ /* Disconnect all probe points. */
89+ ret = avs_ipc_probe_get_points (adev , & desc , & num_desc );
90+ if (ret ) {
91+ dev_err (dai -> dev , "get probe points failed: %d\n" , ret );
92+ ret = AVS_IPC_RET (ret );
93+ goto exit ;
94+ }
95+
96+ for (i = 0 ; i < num_desc ; i ++ )
97+ if (desc [i ].node_id .vindex == vindex )
98+ avs_ipc_probe_disconnect_points (adev , & desc [i ].id , 1 );
99+ kfree (desc );
100+
101+ exit :
102+ if (adev -> num_probe_streams ) {
103+ adev -> num_probe_streams -- ;
104+ if (!adev -> num_probe_streams ) {
105+ avs_dsp_delete_probe (adev );
106+ avs_dsp_enable_d0ix (adev );
107+ }
108+ }
109+
110+ snd_hdac_stream_cleanup (hdac_stream (host_stream ));
111+ hdac_stream (host_stream )-> prepared = 0 ;
112+ snd_hdac_ext_stream_release (host_stream , HDAC_EXT_STREAM_TYPE_HOST );
113+
114+ snd_compr_free_pages (cstream );
115+ adev -> extractor = NULL ;
116+
117+ return ret ;
118+ }
119+
120+ static int avs_probe_compr_set_params (struct snd_compr_stream * cstream ,
121+ struct snd_compr_params * params , struct snd_soc_dai * dai )
122+ {
123+ struct hdac_ext_stream * host_stream = avs_compr_get_host_stream (cstream );
124+ struct snd_compr_runtime * rtd = cstream -> runtime ;
125+ struct avs_dev * adev = to_avs_dev (dai -> dev );
126+ /* compr params do not store bit depth, default to S32_LE. */
127+ snd_pcm_format_t format = SNDRV_PCM_FORMAT_S32_LE ;
128+ unsigned int format_val ;
129+ int bps , ret ;
130+
131+ hdac_stream (host_stream )-> bufsize = 0 ;
132+ hdac_stream (host_stream )-> period_bytes = 0 ;
133+ hdac_stream (host_stream )-> format_val = 0 ;
134+ cstream -> dma_buffer .dev .type = SNDRV_DMA_TYPE_DEV_SG ;
135+ cstream -> dma_buffer .dev .dev = adev -> dev ;
136+
137+ ret = snd_compr_malloc_pages (cstream , rtd -> buffer_size );
138+ if (ret < 0 )
139+ return ret ;
140+ bps = snd_pcm_format_physical_width (format );
141+ if (bps < 0 )
142+ return bps ;
143+ format_val = snd_hdac_calc_stream_format (params -> codec .sample_rate , params -> codec .ch_out ,
144+ format , bps , 0 );
145+ ret = snd_hdac_stream_set_params (hdac_stream (host_stream ), format_val );
146+ if (ret < 0 )
147+ return ret ;
148+ ret = snd_hdac_stream_setup (hdac_stream (host_stream ));
149+ if (ret < 0 )
150+ return ret ;
151+
152+ hdac_stream (host_stream )-> prepared = 1 ;
153+
154+ if (!adev -> num_probe_streams ) {
155+ union avs_connector_node_id node_id ;
156+
157+ /* D0ix not allowed during probing. */
158+ ret = avs_dsp_disable_d0ix (adev );
159+ if (ret )
160+ return ret ;
161+
162+ node_id .vindex = hdac_stream (host_stream )-> stream_tag - 1 ;
163+ node_id .dma_type = AVS_DMA_HDA_HOST_INPUT ;
164+
165+ ret = avs_dsp_init_probe (adev , node_id , rtd -> dma_bytes );
166+ if (ret < 0 ) {
167+ dev_err (dai -> dev , "probe init failed: %d\n" , ret );
168+ avs_dsp_enable_d0ix (adev );
169+ return ret ;
170+ }
171+ }
172+
173+ adev -> num_probe_streams ++ ;
174+ return 0 ;
175+ }
176+
177+ static int avs_probe_compr_trigger (struct snd_compr_stream * cstream , int cmd ,
178+ struct snd_soc_dai * dai )
179+ {
180+ struct hdac_ext_stream * host_stream = avs_compr_get_host_stream (cstream );
181+ struct avs_dev * adev = to_avs_dev (dai -> dev );
182+ struct hdac_bus * bus = & adev -> base .core ;
183+ unsigned long cookie ;
184+
185+ if (!hdac_stream (host_stream )-> prepared )
186+ return - EPIPE ;
187+
188+ switch (cmd ) {
189+ case SNDRV_PCM_TRIGGER_START :
190+ case SNDRV_PCM_TRIGGER_PAUSE_RELEASE :
191+ case SNDRV_PCM_TRIGGER_RESUME :
192+ spin_lock_irqsave (& bus -> reg_lock , cookie );
193+ snd_hdac_stream_start (hdac_stream (host_stream ), true);
194+ spin_unlock_irqrestore (& bus -> reg_lock , cookie );
195+ break ;
196+
197+ case SNDRV_PCM_TRIGGER_PAUSE_PUSH :
198+ case SNDRV_PCM_TRIGGER_SUSPEND :
199+ case SNDRV_PCM_TRIGGER_STOP :
200+ spin_lock_irqsave (& bus -> reg_lock , cookie );
201+ snd_hdac_stream_stop (hdac_stream (host_stream ));
202+ spin_unlock_irqrestore (& bus -> reg_lock , cookie );
203+ break ;
204+
205+ default :
206+ return - EINVAL ;
207+ }
208+
209+ return 0 ;
210+ }
211+
212+ static int avs_probe_compr_pointer (struct snd_compr_stream * cstream ,
213+ struct snd_compr_tstamp * tstamp , struct snd_soc_dai * dai )
214+ {
215+ struct hdac_ext_stream * host_stream = avs_compr_get_host_stream (cstream );
216+ struct snd_soc_pcm_stream * pstream ;
217+
218+ pstream = & dai -> driver -> capture ;
219+ tstamp -> copied_total = hdac_stream (host_stream )-> curr_pos ;
220+ tstamp -> sampling_rate = snd_pcm_rate_bit_to_rate (pstream -> rates );
221+
222+ return 0 ;
223+ }
224+
225+ static int avs_probe_compr_copy (struct snd_soc_component * comp , struct snd_compr_stream * cstream ,
226+ char __user * buf , size_t count )
227+ {
228+ struct snd_compr_runtime * rtd = cstream -> runtime ;
229+ unsigned int offset , n ;
230+ void * ptr ;
231+ int ret ;
232+
233+ if (count > rtd -> buffer_size )
234+ count = rtd -> buffer_size ;
235+
236+ div_u64_rem (rtd -> total_bytes_transferred , rtd -> buffer_size , & offset );
237+ ptr = rtd -> dma_area + offset ;
238+ n = rtd -> buffer_size - offset ;
239+
240+ if (count < n ) {
241+ ret = copy_to_user (buf , ptr , count );
242+ } else {
243+ ret = copy_to_user (buf , ptr , n );
244+ ret += copy_to_user (buf + n , rtd -> dma_area , count - n );
245+ }
246+
247+ if (ret )
248+ return count - ret ;
249+ return count ;
250+ }
251+
252+ __maybe_unused
253+ static const struct snd_soc_cdai_ops avs_probe_dai_ops = {
254+ .startup = avs_probe_compr_open ,
255+ .shutdown = avs_probe_compr_free ,
256+ .set_params = avs_probe_compr_set_params ,
257+ .trigger = avs_probe_compr_trigger ,
258+ .pointer = avs_probe_compr_pointer ,
259+ };
260+
261+ __maybe_unused
262+ static const struct snd_compress_ops avs_probe_compress_ops = {
263+ .copy = avs_probe_compr_copy ,
264+ };
0 commit comments