xref: /linux/sound/xen/xen_snd_front_alsa.c (revision e9f0878c4b2004ac19581274c1ae4c61ae3ca70e)
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 }
823