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