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