GNU Linux-libre 4.19.211-gnu1
[releases.git] / sound / xen / xen_snd_front_alsa.c
1 // SPDX-License-Identifier: GPL-2.0 OR MIT
2
3 /*
4  * Xen para-virtual sound device
5  *
6  * Copyright (C) 2016-2018 EPAM Systems Inc.
7  *
8  * Author: Oleksandr Andrushchenko <oleksandr_andrushchenko@epam.com>
9  */
10
11 #include <linux/platform_device.h>
12
13 #include <sound/core.h>
14 #include <sound/pcm.h>
15 #include <sound/pcm_params.h>
16
17 #include <xen/xenbus.h>
18
19 #include "xen_snd_front.h"
20 #include "xen_snd_front_alsa.h"
21 #include "xen_snd_front_cfg.h"
22 #include "xen_snd_front_evtchnl.h"
23 #include "xen_snd_front_shbuf.h"
24
25 struct xen_snd_front_pcm_stream_info {
26         struct xen_snd_front_info *front_info;
27         struct xen_snd_front_evtchnl_pair *evt_pair;
28         struct xen_snd_front_shbuf sh_buf;
29         int index;
30
31         bool is_open;
32         struct snd_pcm_hardware pcm_hw;
33
34         /* Number of processed frames as reported by the backend. */
35         snd_pcm_uframes_t be_cur_frame;
36         /* Current HW pointer to be reported via .period callback. */
37         atomic_t hw_ptr;
38         /* Modulo of the number of processed frames - for period detection. */
39         u32 out_frames;
40 };
41
42 struct xen_snd_front_pcm_instance_info {
43         struct xen_snd_front_card_info *card_info;
44         struct snd_pcm *pcm;
45         struct snd_pcm_hardware pcm_hw;
46         int num_pcm_streams_pb;
47         struct xen_snd_front_pcm_stream_info *streams_pb;
48         int num_pcm_streams_cap;
49         struct xen_snd_front_pcm_stream_info *streams_cap;
50 };
51
52 struct xen_snd_front_card_info {
53         struct xen_snd_front_info *front_info;
54         struct snd_card *card;
55         struct snd_pcm_hardware pcm_hw;
56         int num_pcm_instances;
57         struct xen_snd_front_pcm_instance_info *pcm_instances;
58 };
59
60 struct alsa_sndif_sample_format {
61         u8 sndif;
62         snd_pcm_format_t alsa;
63 };
64
65 struct alsa_sndif_hw_param {
66         u8 sndif;
67         snd_pcm_hw_param_t alsa;
68 };
69
70 static const struct alsa_sndif_sample_format ALSA_SNDIF_FORMATS[] = {
71         {
72                 .sndif = XENSND_PCM_FORMAT_U8,
73                 .alsa = SNDRV_PCM_FORMAT_U8
74         },
75         {
76                 .sndif = XENSND_PCM_FORMAT_S8,
77                 .alsa = SNDRV_PCM_FORMAT_S8
78         },
79         {
80                 .sndif = XENSND_PCM_FORMAT_U16_LE,
81                 .alsa = SNDRV_PCM_FORMAT_U16_LE
82         },
83         {
84                 .sndif = XENSND_PCM_FORMAT_U16_BE,
85                 .alsa = SNDRV_PCM_FORMAT_U16_BE
86         },
87         {
88                 .sndif = XENSND_PCM_FORMAT_S16_LE,
89                 .alsa = SNDRV_PCM_FORMAT_S16_LE
90         },
91         {
92                 .sndif = XENSND_PCM_FORMAT_S16_BE,
93                 .alsa = SNDRV_PCM_FORMAT_S16_BE
94         },
95         {
96                 .sndif = XENSND_PCM_FORMAT_U24_LE,
97                 .alsa = SNDRV_PCM_FORMAT_U24_LE
98         },
99         {
100                 .sndif = XENSND_PCM_FORMAT_U24_BE,
101                 .alsa = SNDRV_PCM_FORMAT_U24_BE
102         },
103         {
104                 .sndif = XENSND_PCM_FORMAT_S24_LE,
105                 .alsa = SNDRV_PCM_FORMAT_S24_LE
106         },
107         {
108                 .sndif = XENSND_PCM_FORMAT_S24_BE,
109                 .alsa = SNDRV_PCM_FORMAT_S24_BE
110         },
111         {
112                 .sndif = XENSND_PCM_FORMAT_U32_LE,
113                 .alsa = SNDRV_PCM_FORMAT_U32_LE
114         },
115         {
116                 .sndif = XENSND_PCM_FORMAT_U32_BE,
117                 .alsa = SNDRV_PCM_FORMAT_U32_BE
118         },
119         {
120                 .sndif = XENSND_PCM_FORMAT_S32_LE,
121                 .alsa = SNDRV_PCM_FORMAT_S32_LE
122         },
123         {
124                 .sndif = XENSND_PCM_FORMAT_S32_BE,
125                 .alsa = SNDRV_PCM_FORMAT_S32_BE
126         },
127         {
128                 .sndif = XENSND_PCM_FORMAT_A_LAW,
129                 .alsa = SNDRV_PCM_FORMAT_A_LAW
130         },
131         {
132                 .sndif = XENSND_PCM_FORMAT_MU_LAW,
133                 .alsa = SNDRV_PCM_FORMAT_MU_LAW
134         },
135         {
136                 .sndif = XENSND_PCM_FORMAT_F32_LE,
137                 .alsa = SNDRV_PCM_FORMAT_FLOAT_LE
138         },
139         {
140                 .sndif = XENSND_PCM_FORMAT_F32_BE,
141                 .alsa = SNDRV_PCM_FORMAT_FLOAT_BE
142         },
143         {
144                 .sndif = XENSND_PCM_FORMAT_F64_LE,
145                 .alsa = SNDRV_PCM_FORMAT_FLOAT64_LE
146         },
147         {
148                 .sndif = XENSND_PCM_FORMAT_F64_BE,
149                 .alsa = SNDRV_PCM_FORMAT_FLOAT64_BE
150         },
151         {
152                 .sndif = XENSND_PCM_FORMAT_IEC958_SUBFRAME_LE,
153                 .alsa = SNDRV_PCM_FORMAT_IEC958_SUBFRAME_LE
154         },
155         {
156                 .sndif = XENSND_PCM_FORMAT_IEC958_SUBFRAME_BE,
157                 .alsa = SNDRV_PCM_FORMAT_IEC958_SUBFRAME_BE
158         },
159         {
160                 .sndif = XENSND_PCM_FORMAT_IMA_ADPCM,
161                 .alsa = SNDRV_PCM_FORMAT_IMA_ADPCM
162         },
163         {
164                 .sndif = XENSND_PCM_FORMAT_MPEG,
165                 .alsa = SNDRV_PCM_FORMAT_MPEG
166         },
167         {
168                 .sndif = XENSND_PCM_FORMAT_GSM,
169                 .alsa = SNDRV_PCM_FORMAT_GSM
170         },
171 };
172
173 static int to_sndif_format(snd_pcm_format_t format)
174 {
175         int i;
176
177         for (i = 0; i < ARRAY_SIZE(ALSA_SNDIF_FORMATS); i++)
178                 if (ALSA_SNDIF_FORMATS[i].alsa == format)
179                         return ALSA_SNDIF_FORMATS[i].sndif;
180
181         return -EINVAL;
182 }
183
184 static u64 to_sndif_formats_mask(u64 alsa_formats)
185 {
186         u64 mask;
187         int i;
188
189         mask = 0;
190         for (i = 0; i < ARRAY_SIZE(ALSA_SNDIF_FORMATS); i++)
191                 if (pcm_format_to_bits(ALSA_SNDIF_FORMATS[i].alsa) & alsa_formats)
192                         mask |= 1 << ALSA_SNDIF_FORMATS[i].sndif;
193
194         return mask;
195 }
196
197 static u64 to_alsa_formats_mask(u64 sndif_formats)
198 {
199         u64 mask;
200         int i;
201
202         mask = 0;
203         for (i = 0; i < ARRAY_SIZE(ALSA_SNDIF_FORMATS); i++)
204                 if (1 << ALSA_SNDIF_FORMATS[i].sndif & sndif_formats)
205                         mask |= pcm_format_to_bits(ALSA_SNDIF_FORMATS[i].alsa);
206
207         return mask;
208 }
209
210 static void stream_clear(struct xen_snd_front_pcm_stream_info *stream)
211 {
212         stream->is_open = false;
213         stream->be_cur_frame = 0;
214         stream->out_frames = 0;
215         atomic_set(&stream->hw_ptr, 0);
216         xen_snd_front_evtchnl_pair_clear(stream->evt_pair);
217         xen_snd_front_shbuf_clear(&stream->sh_buf);
218 }
219
220 static void stream_free(struct xen_snd_front_pcm_stream_info *stream)
221 {
222         xen_snd_front_shbuf_free(&stream->sh_buf);
223         stream_clear(stream);
224 }
225
226 static struct xen_snd_front_pcm_stream_info *
227 stream_get(struct snd_pcm_substream *substream)
228 {
229         struct xen_snd_front_pcm_instance_info *pcm_instance =
230                         snd_pcm_substream_chip(substream);
231         struct xen_snd_front_pcm_stream_info *stream;
232
233         if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
234                 stream = &pcm_instance->streams_pb[substream->number];
235         else
236                 stream = &pcm_instance->streams_cap[substream->number];
237
238         return stream;
239 }
240
241 static int alsa_hw_rule(struct snd_pcm_hw_params *params,
242                         struct snd_pcm_hw_rule *rule)
243 {
244         struct xen_snd_front_pcm_stream_info *stream = rule->private;
245         struct device *dev = &stream->front_info->xb_dev->dev;
246         struct snd_mask *formats =
247                         hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT);
248         struct snd_interval *rates =
249                         hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE);
250         struct snd_interval *channels =
251                         hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS);
252         struct snd_interval *period =
253                         hw_param_interval(params,
254                                           SNDRV_PCM_HW_PARAM_PERIOD_SIZE);
255         struct snd_interval *buffer =
256                         hw_param_interval(params,
257                                           SNDRV_PCM_HW_PARAM_BUFFER_SIZE);
258         struct xensnd_query_hw_param req;
259         struct xensnd_query_hw_param resp;
260         struct snd_interval interval;
261         struct snd_mask mask;
262         u64 sndif_formats;
263         int changed, ret;
264
265         /* Collect all the values we need for the query. */
266
267         req.formats = to_sndif_formats_mask((u64)formats->bits[0] |
268                                             (u64)(formats->bits[1]) << 32);
269
270         req.rates.min = rates->min;
271         req.rates.max = rates->max;
272
273         req.channels.min = channels->min;
274         req.channels.max = channels->max;
275
276         req.buffer.min = buffer->min;
277         req.buffer.max = buffer->max;
278
279         req.period.min = period->min;
280         req.period.max = period->max;
281
282         ret = xen_snd_front_stream_query_hw_param(&stream->evt_pair->req,
283                                                   &req, &resp);
284         if (ret < 0) {
285                 /* Check if this is due to backend communication error. */
286                 if (ret == -EIO || ret == -ETIMEDOUT)
287                         dev_err(dev, "Failed to query ALSA HW parameters\n");
288                 return ret;
289         }
290
291         /* Refine HW parameters after the query. */
292         changed  = 0;
293
294         sndif_formats = to_alsa_formats_mask(resp.formats);
295         snd_mask_none(&mask);
296         mask.bits[0] = (u32)sndif_formats;
297         mask.bits[1] = (u32)(sndif_formats >> 32);
298         ret = snd_mask_refine(formats, &mask);
299         if (ret < 0)
300                 return ret;
301         changed |= ret;
302
303         interval.openmin = 0;
304         interval.openmax = 0;
305         interval.integer = 1;
306
307         interval.min = resp.rates.min;
308         interval.max = resp.rates.max;
309         ret = snd_interval_refine(rates, &interval);
310         if (ret < 0)
311                 return ret;
312         changed |= ret;
313
314         interval.min = resp.channels.min;
315         interval.max = resp.channels.max;
316         ret = snd_interval_refine(channels, &interval);
317         if (ret < 0)
318                 return ret;
319         changed |= ret;
320
321         interval.min = resp.buffer.min;
322         interval.max = resp.buffer.max;
323         ret = snd_interval_refine(buffer, &interval);
324         if (ret < 0)
325                 return ret;
326         changed |= ret;
327
328         interval.min = resp.period.min;
329         interval.max = resp.period.max;
330         ret = snd_interval_refine(period, &interval);
331         if (ret < 0)
332                 return ret;
333         changed |= ret;
334
335         return changed;
336 }
337
338 static int alsa_open(struct snd_pcm_substream *substream)
339 {
340         struct xen_snd_front_pcm_instance_info *pcm_instance =
341                         snd_pcm_substream_chip(substream);
342         struct xen_snd_front_pcm_stream_info *stream = stream_get(substream);
343         struct snd_pcm_runtime *runtime = substream->runtime;
344         struct xen_snd_front_info *front_info =
345                         pcm_instance->card_info->front_info;
346         struct device *dev = &front_info->xb_dev->dev;
347         int ret;
348
349         /*
350          * Return our HW properties: override defaults with those configured
351          * via XenStore.
352          */
353         runtime->hw = stream->pcm_hw;
354         runtime->hw.info &= ~(SNDRV_PCM_INFO_MMAP |
355                               SNDRV_PCM_INFO_MMAP_VALID |
356                               SNDRV_PCM_INFO_DOUBLE |
357                               SNDRV_PCM_INFO_BATCH |
358                               SNDRV_PCM_INFO_NONINTERLEAVED |
359                               SNDRV_PCM_INFO_RESUME |
360                               SNDRV_PCM_INFO_PAUSE);
361         runtime->hw.info |= SNDRV_PCM_INFO_INTERLEAVED;
362
363         stream->evt_pair = &front_info->evt_pairs[stream->index];
364
365         stream->front_info = front_info;
366
367         stream->evt_pair->evt.u.evt.substream = substream;
368
369         stream_clear(stream);
370
371         xen_snd_front_evtchnl_pair_set_connected(stream->evt_pair, true);
372
373         ret = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_FORMAT,
374                                   alsa_hw_rule, stream,
375                                   SNDRV_PCM_HW_PARAM_FORMAT, -1);
376         if (ret) {
377                 dev_err(dev, "Failed to add HW rule for SNDRV_PCM_HW_PARAM_FORMAT\n");
378                 return ret;
379         }
380
381         ret = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_RATE,
382                                   alsa_hw_rule, stream,
383                                   SNDRV_PCM_HW_PARAM_RATE, -1);
384         if (ret) {
385                 dev_err(dev, "Failed to add HW rule for SNDRV_PCM_HW_PARAM_RATE\n");
386                 return ret;
387         }
388
389         ret = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS,
390                                   alsa_hw_rule, stream,
391                                   SNDRV_PCM_HW_PARAM_CHANNELS, -1);
392         if (ret) {
393                 dev_err(dev, "Failed to add HW rule for SNDRV_PCM_HW_PARAM_CHANNELS\n");
394                 return ret;
395         }
396
397         ret = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_SIZE,
398                                   alsa_hw_rule, stream,
399                                   SNDRV_PCM_HW_PARAM_PERIOD_SIZE, -1);
400         if (ret) {
401                 dev_err(dev, "Failed to add HW rule for SNDRV_PCM_HW_PARAM_PERIOD_SIZE\n");
402                 return ret;
403         }
404
405         ret = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_BUFFER_SIZE,
406                                   alsa_hw_rule, stream,
407                                   SNDRV_PCM_HW_PARAM_BUFFER_SIZE, -1);
408         if (ret) {
409                 dev_err(dev, "Failed to add HW rule for SNDRV_PCM_HW_PARAM_BUFFER_SIZE\n");
410                 return ret;
411         }
412
413         return 0;
414 }
415
416 static int alsa_close(struct snd_pcm_substream *substream)
417 {
418         struct xen_snd_front_pcm_stream_info *stream = stream_get(substream);
419
420         xen_snd_front_evtchnl_pair_set_connected(stream->evt_pair, false);
421         return 0;
422 }
423
424 static int alsa_hw_params(struct snd_pcm_substream *substream,
425                           struct snd_pcm_hw_params *params)
426 {
427         struct xen_snd_front_pcm_stream_info *stream = stream_get(substream);
428         int ret;
429
430         /*
431          * This callback may be called multiple times,
432          * so free the previously allocated shared buffer if any.
433          */
434         stream_free(stream);
435
436         ret = xen_snd_front_shbuf_alloc(stream->front_info->xb_dev,
437                                         &stream->sh_buf,
438                                         params_buffer_bytes(params));
439         if (ret < 0) {
440                 stream_free(stream);
441                 dev_err(&stream->front_info->xb_dev->dev,
442                         "Failed to allocate buffers for stream with index %d\n",
443                         stream->index);
444                 return ret;
445         }
446
447         return 0;
448 }
449
450 static int alsa_hw_free(struct snd_pcm_substream *substream)
451 {
452         struct xen_snd_front_pcm_stream_info *stream = stream_get(substream);
453         int ret;
454
455         ret = xen_snd_front_stream_close(&stream->evt_pair->req);
456         stream_free(stream);
457         return ret;
458 }
459
460 static int alsa_prepare(struct snd_pcm_substream *substream)
461 {
462         struct xen_snd_front_pcm_stream_info *stream = stream_get(substream);
463
464         if (!stream->is_open) {
465                 struct snd_pcm_runtime *runtime = substream->runtime;
466                 u8 sndif_format;
467                 int ret;
468
469                 ret = to_sndif_format(runtime->format);
470                 if (ret < 0) {
471                         dev_err(&stream->front_info->xb_dev->dev,
472                                 "Unsupported sample format: %d\n",
473                                 runtime->format);
474                         return ret;
475                 }
476                 sndif_format = ret;
477
478                 ret = xen_snd_front_stream_prepare(&stream->evt_pair->req,
479                                                    &stream->sh_buf,
480                                                    sndif_format,
481                                                    runtime->channels,
482                                                    runtime->rate,
483                                                    snd_pcm_lib_buffer_bytes(substream),
484                                                    snd_pcm_lib_period_bytes(substream));
485                 if (ret < 0)
486                         return ret;
487
488                 stream->is_open = true;
489         }
490
491         return 0;
492 }
493
494 static int alsa_trigger(struct snd_pcm_substream *substream, int cmd)
495 {
496         struct xen_snd_front_pcm_stream_info *stream = stream_get(substream);
497         int type;
498
499         switch (cmd) {
500         case SNDRV_PCM_TRIGGER_START:
501                 type = XENSND_OP_TRIGGER_START;
502                 break;
503
504         case SNDRV_PCM_TRIGGER_RESUME:
505                 type = XENSND_OP_TRIGGER_RESUME;
506                 break;
507
508         case SNDRV_PCM_TRIGGER_STOP:
509                 type = XENSND_OP_TRIGGER_STOP;
510                 break;
511
512         case SNDRV_PCM_TRIGGER_SUSPEND:
513                 type = XENSND_OP_TRIGGER_PAUSE;
514                 break;
515
516         default:
517                 return -EINVAL;
518         }
519
520         return xen_snd_front_stream_trigger(&stream->evt_pair->req, type);
521 }
522
523 void xen_snd_front_alsa_handle_cur_pos(struct xen_snd_front_evtchnl *evtchnl,
524                                        u64 pos_bytes)
525 {
526         struct snd_pcm_substream *substream = evtchnl->u.evt.substream;
527         struct xen_snd_front_pcm_stream_info *stream = stream_get(substream);
528         snd_pcm_uframes_t delta, new_hw_ptr, cur_frame;
529
530         cur_frame = bytes_to_frames(substream->runtime, pos_bytes);
531
532         delta = cur_frame - stream->be_cur_frame;
533         stream->be_cur_frame = cur_frame;
534
535         new_hw_ptr = (snd_pcm_uframes_t)atomic_read(&stream->hw_ptr);
536         new_hw_ptr = (new_hw_ptr + delta) % substream->runtime->buffer_size;
537         atomic_set(&stream->hw_ptr, (int)new_hw_ptr);
538
539         stream->out_frames += delta;
540         if (stream->out_frames > substream->runtime->period_size) {
541                 stream->out_frames %= substream->runtime->period_size;
542                 snd_pcm_period_elapsed(substream);
543         }
544 }
545
546 static snd_pcm_uframes_t alsa_pointer(struct snd_pcm_substream *substream)
547 {
548         struct xen_snd_front_pcm_stream_info *stream = stream_get(substream);
549
550         return (snd_pcm_uframes_t)atomic_read(&stream->hw_ptr);
551 }
552
553 static int alsa_pb_copy_user(struct snd_pcm_substream *substream,
554                              int channel, unsigned long pos, void __user *src,
555                              unsigned long count)
556 {
557         struct xen_snd_front_pcm_stream_info *stream = stream_get(substream);
558
559         if (unlikely(pos + count > stream->sh_buf.buffer_sz))
560                 return -EINVAL;
561
562         if (copy_from_user(stream->sh_buf.buffer + pos, src, count))
563                 return -EFAULT;
564
565         return xen_snd_front_stream_write(&stream->evt_pair->req, pos, count);
566 }
567
568 static int alsa_pb_copy_kernel(struct snd_pcm_substream *substream,
569                                int channel, unsigned long pos, void *src,
570                                unsigned long count)
571 {
572         struct xen_snd_front_pcm_stream_info *stream = stream_get(substream);
573
574         if (unlikely(pos + count > stream->sh_buf.buffer_sz))
575                 return -EINVAL;
576
577         memcpy(stream->sh_buf.buffer + pos, src, count);
578
579         return xen_snd_front_stream_write(&stream->evt_pair->req, pos, count);
580 }
581
582 static int alsa_cap_copy_user(struct snd_pcm_substream *substream,
583                               int channel, unsigned long pos, void __user *dst,
584                               unsigned long count)
585 {
586         struct xen_snd_front_pcm_stream_info *stream = stream_get(substream);
587         int ret;
588
589         if (unlikely(pos + count > stream->sh_buf.buffer_sz))
590                 return -EINVAL;
591
592         ret = xen_snd_front_stream_read(&stream->evt_pair->req, pos, count);
593         if (ret < 0)
594                 return ret;
595
596         return copy_to_user(dst, stream->sh_buf.buffer + pos, count) ?
597                 -EFAULT : 0;
598 }
599
600 static int alsa_cap_copy_kernel(struct snd_pcm_substream *substream,
601                                 int channel, unsigned long pos, void *dst,
602                                 unsigned long count)
603 {
604         struct xen_snd_front_pcm_stream_info *stream = stream_get(substream);
605         int ret;
606
607         if (unlikely(pos + count > stream->sh_buf.buffer_sz))
608                 return -EINVAL;
609
610         ret = xen_snd_front_stream_read(&stream->evt_pair->req, pos, count);
611         if (ret < 0)
612                 return ret;
613
614         memcpy(dst, stream->sh_buf.buffer + pos, count);
615
616         return 0;
617 }
618
619 static int alsa_pb_fill_silence(struct snd_pcm_substream *substream,
620                                 int channel, unsigned long pos,
621                                 unsigned long count)
622 {
623         struct xen_snd_front_pcm_stream_info *stream = stream_get(substream);
624
625         if (unlikely(pos + count > stream->sh_buf.buffer_sz))
626                 return -EINVAL;
627
628         memset(stream->sh_buf.buffer + pos, 0, count);
629
630         return xen_snd_front_stream_write(&stream->evt_pair->req, pos, count);
631 }
632
633 /*
634  * FIXME: The mmaped data transfer is asynchronous and there is no
635  * ack signal from user-space when it is done. This is the
636  * reason it is not implemented in the PV driver as we do need
637  * to know when the buffer can be transferred to the backend.
638  */
639
640 static struct snd_pcm_ops snd_drv_alsa_playback_ops = {
641         .open = alsa_open,
642         .close = alsa_close,
643         .ioctl = snd_pcm_lib_ioctl,
644         .hw_params = alsa_hw_params,
645         .hw_free = alsa_hw_free,
646         .prepare = alsa_prepare,
647         .trigger = alsa_trigger,
648         .pointer = alsa_pointer,
649         .copy_user = alsa_pb_copy_user,
650         .copy_kernel = alsa_pb_copy_kernel,
651         .fill_silence = alsa_pb_fill_silence,
652 };
653
654 static struct snd_pcm_ops snd_drv_alsa_capture_ops = {
655         .open = alsa_open,
656         .close = alsa_close,
657         .ioctl = snd_pcm_lib_ioctl,
658         .hw_params = alsa_hw_params,
659         .hw_free = alsa_hw_free,
660         .prepare = alsa_prepare,
661         .trigger = alsa_trigger,
662         .pointer = alsa_pointer,
663         .copy_user = alsa_cap_copy_user,
664         .copy_kernel = alsa_cap_copy_kernel,
665 };
666
667 static int new_pcm_instance(struct xen_snd_front_card_info *card_info,
668                             struct xen_front_cfg_pcm_instance *instance_cfg,
669                             struct xen_snd_front_pcm_instance_info *pcm_instance_info)
670 {
671         struct snd_pcm *pcm;
672         int ret, i;
673
674         dev_dbg(&card_info->front_info->xb_dev->dev,
675                 "New PCM device \"%s\" with id %d playback %d capture %d",
676                 instance_cfg->name,
677                 instance_cfg->device_id,
678                 instance_cfg->num_streams_pb,
679                 instance_cfg->num_streams_cap);
680
681         pcm_instance_info->card_info = card_info;
682
683         pcm_instance_info->pcm_hw = instance_cfg->pcm_hw;
684
685         if (instance_cfg->num_streams_pb) {
686                 pcm_instance_info->streams_pb =
687                                 devm_kcalloc(&card_info->card->card_dev,
688                                              instance_cfg->num_streams_pb,
689                                              sizeof(struct xen_snd_front_pcm_stream_info),
690                                              GFP_KERNEL);
691                 if (!pcm_instance_info->streams_pb)
692                         return -ENOMEM;
693         }
694
695         if (instance_cfg->num_streams_cap) {
696                 pcm_instance_info->streams_cap =
697                                 devm_kcalloc(&card_info->card->card_dev,
698                                              instance_cfg->num_streams_cap,
699                                              sizeof(struct xen_snd_front_pcm_stream_info),
700                                              GFP_KERNEL);
701                 if (!pcm_instance_info->streams_cap)
702                         return -ENOMEM;
703         }
704
705         pcm_instance_info->num_pcm_streams_pb =
706                         instance_cfg->num_streams_pb;
707         pcm_instance_info->num_pcm_streams_cap =
708                         instance_cfg->num_streams_cap;
709
710         for (i = 0; i < pcm_instance_info->num_pcm_streams_pb; i++) {
711                 pcm_instance_info->streams_pb[i].pcm_hw =
712                         instance_cfg->streams_pb[i].pcm_hw;
713                 pcm_instance_info->streams_pb[i].index =
714                         instance_cfg->streams_pb[i].index;
715         }
716
717         for (i = 0; i < pcm_instance_info->num_pcm_streams_cap; i++) {
718                 pcm_instance_info->streams_cap[i].pcm_hw =
719                         instance_cfg->streams_cap[i].pcm_hw;
720                 pcm_instance_info->streams_cap[i].index =
721                         instance_cfg->streams_cap[i].index;
722         }
723
724         ret = snd_pcm_new(card_info->card, instance_cfg->name,
725                           instance_cfg->device_id,
726                           instance_cfg->num_streams_pb,
727                           instance_cfg->num_streams_cap,
728                           &pcm);
729         if (ret < 0)
730                 return ret;
731
732         pcm->private_data = pcm_instance_info;
733         pcm->info_flags = 0;
734         /* we want to handle all PCM operations in non-atomic context */
735         pcm->nonatomic = true;
736         strncpy(pcm->name, "Virtual card PCM", sizeof(pcm->name));
737
738         if (instance_cfg->num_streams_pb)
739                 snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK,
740                                 &snd_drv_alsa_playback_ops);
741
742         if (instance_cfg->num_streams_cap)
743                 snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE,
744                                 &snd_drv_alsa_capture_ops);
745
746         pcm_instance_info->pcm = pcm;
747         return 0;
748 }
749
750 int xen_snd_front_alsa_init(struct xen_snd_front_info *front_info)
751 {
752         struct device *dev = &front_info->xb_dev->dev;
753         struct xen_front_cfg_card *cfg = &front_info->cfg;
754         struct xen_snd_front_card_info *card_info;
755         struct snd_card *card;
756         int ret, i;
757
758         dev_dbg(dev, "Creating virtual sound card\n");
759
760         ret = snd_card_new(dev, 0, XENSND_DRIVER_NAME, THIS_MODULE,
761                            sizeof(struct xen_snd_front_card_info), &card);
762         if (ret < 0)
763                 return ret;
764
765         card_info = card->private_data;
766         card_info->front_info = front_info;
767         front_info->card_info = card_info;
768         card_info->card = card;
769         card_info->pcm_instances =
770                         devm_kcalloc(dev, cfg->num_pcm_instances,
771                                      sizeof(struct xen_snd_front_pcm_instance_info),
772                                      GFP_KERNEL);
773         if (!card_info->pcm_instances) {
774                 ret = -ENOMEM;
775                 goto fail;
776         }
777
778         card_info->num_pcm_instances = cfg->num_pcm_instances;
779         card_info->pcm_hw = cfg->pcm_hw;
780
781         for (i = 0; i < cfg->num_pcm_instances; i++) {
782                 ret = new_pcm_instance(card_info, &cfg->pcm_instances[i],
783                                        &card_info->pcm_instances[i]);
784                 if (ret < 0)
785                         goto fail;
786         }
787
788         strncpy(card->driver, XENSND_DRIVER_NAME, sizeof(card->driver));
789         strncpy(card->shortname, cfg->name_short, sizeof(card->shortname));
790         strncpy(card->longname, cfg->name_long, sizeof(card->longname));
791
792         ret = snd_card_register(card);
793         if (ret < 0)
794                 goto fail;
795
796         return 0;
797
798 fail:
799         snd_card_free(card);
800         return ret;
801 }
802
803 void xen_snd_front_alsa_fini(struct xen_snd_front_info *front_info)
804 {
805         struct xen_snd_front_card_info *card_info;
806         struct snd_card *card;
807
808         card_info = front_info->card_info;
809         if (!card_info)
810                 return;
811
812         card = card_info->card;
813         if (!card)
814                 return;
815
816         dev_dbg(&front_info->xb_dev->dev, "Removing virtual sound card %d\n",
817                 card->number);
818         snd_card_free(card);
819
820         /* Card_info will be freed when destroying front_info->xb_dev->dev. */
821         card_info->card = NULL;
822 }