most_snd.c (19133B)
1// SPDX-License-Identifier: GPL-2.0 2/* 3 * sound.c - Sound component for Mostcore 4 * 5 * Copyright (C) 2015 Microchip Technology Germany II GmbH & Co. KG 6 */ 7 8#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 9 10#include <linux/module.h> 11#include <linux/printk.h> 12#include <linux/kernel.h> 13#include <linux/slab.h> 14#include <linux/init.h> 15#include <sound/core.h> 16#include <sound/pcm.h> 17#include <sound/pcm_params.h> 18#include <linux/sched.h> 19#include <linux/kthread.h> 20#include <linux/most.h> 21 22#define DRIVER_NAME "sound" 23#define STRING_SIZE 80 24 25static struct most_component comp; 26 27/** 28 * struct channel - private structure to keep channel specific data 29 * @substream: stores the substream structure 30 * @iface: interface for which the channel belongs to 31 * @cfg: channel configuration 32 * @card: registered sound card 33 * @list: list for private use 34 * @id: channel index 35 * @period_pos: current period position (ring buffer) 36 * @buffer_pos: current buffer position (ring buffer) 37 * @is_stream_running: identifies whether a stream is running or not 38 * @opened: set when the stream is opened 39 * @playback_task: playback thread 40 * @playback_waitq: waitq used by playback thread 41 */ 42struct channel { 43 struct snd_pcm_substream *substream; 44 struct snd_pcm_hardware pcm_hardware; 45 struct most_interface *iface; 46 struct most_channel_config *cfg; 47 struct snd_card *card; 48 struct list_head list; 49 int id; 50 unsigned int period_pos; 51 unsigned int buffer_pos; 52 bool is_stream_running; 53 struct task_struct *playback_task; 54 wait_queue_head_t playback_waitq; 55 void (*copy_fn)(void *alsa, void *most, unsigned int bytes); 56}; 57 58struct sound_adapter { 59 struct list_head dev_list; 60 struct most_interface *iface; 61 struct snd_card *card; 62 struct list_head list; 63 bool registered; 64 int pcm_dev_idx; 65}; 66 67static struct list_head adpt_list; 68 69#define MOST_PCM_INFO (SNDRV_PCM_INFO_MMAP | \ 70 SNDRV_PCM_INFO_MMAP_VALID | \ 71 SNDRV_PCM_INFO_BATCH | \ 72 SNDRV_PCM_INFO_INTERLEAVED | \ 73 SNDRV_PCM_INFO_BLOCK_TRANSFER) 74 75static void swap_copy16(u16 *dest, const u16 *source, unsigned int bytes) 76{ 77 unsigned int i = 0; 78 79 while (i < (bytes / 2)) { 80 dest[i] = swab16(source[i]); 81 i++; 82 } 83} 84 85static void swap_copy24(u8 *dest, const u8 *source, unsigned int bytes) 86{ 87 unsigned int i = 0; 88 89 if (bytes < 2) 90 return; 91 while (i < bytes - 2) { 92 dest[i] = source[i + 2]; 93 dest[i + 1] = source[i + 1]; 94 dest[i + 2] = source[i]; 95 i += 3; 96 } 97} 98 99static void swap_copy32(u32 *dest, const u32 *source, unsigned int bytes) 100{ 101 unsigned int i = 0; 102 103 while (i < bytes / 4) { 104 dest[i] = swab32(source[i]); 105 i++; 106 } 107} 108 109static void alsa_to_most_memcpy(void *alsa, void *most, unsigned int bytes) 110{ 111 memcpy(most, alsa, bytes); 112} 113 114static void alsa_to_most_copy16(void *alsa, void *most, unsigned int bytes) 115{ 116 swap_copy16(most, alsa, bytes); 117} 118 119static void alsa_to_most_copy24(void *alsa, void *most, unsigned int bytes) 120{ 121 swap_copy24(most, alsa, bytes); 122} 123 124static void alsa_to_most_copy32(void *alsa, void *most, unsigned int bytes) 125{ 126 swap_copy32(most, alsa, bytes); 127} 128 129static void most_to_alsa_memcpy(void *alsa, void *most, unsigned int bytes) 130{ 131 memcpy(alsa, most, bytes); 132} 133 134static void most_to_alsa_copy16(void *alsa, void *most, unsigned int bytes) 135{ 136 swap_copy16(alsa, most, bytes); 137} 138 139static void most_to_alsa_copy24(void *alsa, void *most, unsigned int bytes) 140{ 141 swap_copy24(alsa, most, bytes); 142} 143 144static void most_to_alsa_copy32(void *alsa, void *most, unsigned int bytes) 145{ 146 swap_copy32(alsa, most, bytes); 147} 148 149/** 150 * get_channel - get pointer to channel 151 * @iface: interface structure 152 * @channel_id: channel ID 153 * 154 * This traverses the channel list and returns the channel matching the 155 * ID and interface. 156 * 157 * Returns pointer to channel on success or NULL otherwise. 158 */ 159static struct channel *get_channel(struct most_interface *iface, 160 int channel_id) 161{ 162 struct sound_adapter *adpt = iface->priv; 163 struct channel *channel; 164 165 list_for_each_entry(channel, &adpt->dev_list, list) { 166 if ((channel->iface == iface) && (channel->id == channel_id)) 167 return channel; 168 } 169 return NULL; 170} 171 172/** 173 * copy_data - implements data copying function 174 * @channel: channel 175 * @mbo: MBO from core 176 * 177 * Copy data from/to ring buffer to/from MBO and update the buffer position 178 */ 179static bool copy_data(struct channel *channel, struct mbo *mbo) 180{ 181 struct snd_pcm_runtime *const runtime = channel->substream->runtime; 182 unsigned int const frame_bytes = channel->cfg->subbuffer_size; 183 unsigned int const buffer_size = runtime->buffer_size; 184 unsigned int frames; 185 unsigned int fr0; 186 187 if (channel->cfg->direction & MOST_CH_RX) 188 frames = mbo->processed_length / frame_bytes; 189 else 190 frames = mbo->buffer_length / frame_bytes; 191 fr0 = min(buffer_size - channel->buffer_pos, frames); 192 193 channel->copy_fn(runtime->dma_area + channel->buffer_pos * frame_bytes, 194 mbo->virt_address, 195 fr0 * frame_bytes); 196 197 if (frames > fr0) { 198 /* wrap around at end of ring buffer */ 199 channel->copy_fn(runtime->dma_area, 200 mbo->virt_address + fr0 * frame_bytes, 201 (frames - fr0) * frame_bytes); 202 } 203 204 channel->buffer_pos += frames; 205 if (channel->buffer_pos >= buffer_size) 206 channel->buffer_pos -= buffer_size; 207 channel->period_pos += frames; 208 if (channel->period_pos >= runtime->period_size) { 209 channel->period_pos -= runtime->period_size; 210 return true; 211 } 212 return false; 213} 214 215/** 216 * playback_thread - function implements the playback thread 217 * @data: private data 218 * 219 * Thread which does the playback functionality in a loop. It waits for a free 220 * MBO from mostcore for a particular channel and copy the data from ring buffer 221 * to MBO. Submit the MBO back to mostcore, after copying the data. 222 * 223 * Returns 0 on success or error code otherwise. 224 */ 225static int playback_thread(void *data) 226{ 227 struct channel *const channel = data; 228 229 while (!kthread_should_stop()) { 230 struct mbo *mbo = NULL; 231 bool period_elapsed = false; 232 233 wait_event_interruptible( 234 channel->playback_waitq, 235 kthread_should_stop() || 236 (channel->is_stream_running && 237 (mbo = most_get_mbo(channel->iface, channel->id, 238 &comp)))); 239 if (!mbo) 240 continue; 241 242 if (channel->is_stream_running) 243 period_elapsed = copy_data(channel, mbo); 244 else 245 memset(mbo->virt_address, 0, mbo->buffer_length); 246 247 most_submit_mbo(mbo); 248 if (period_elapsed) 249 snd_pcm_period_elapsed(channel->substream); 250 } 251 return 0; 252} 253 254/** 255 * pcm_open - implements open callback function for PCM middle layer 256 * @substream: pointer to ALSA PCM substream 257 * 258 * This is called when a PCM substream is opened. At least, the function should 259 * initialize the runtime->hw record. 260 * 261 * Returns 0 on success or error code otherwise. 262 */ 263static int pcm_open(struct snd_pcm_substream *substream) 264{ 265 struct channel *channel = substream->private_data; 266 struct snd_pcm_runtime *runtime = substream->runtime; 267 struct most_channel_config *cfg = channel->cfg; 268 int ret; 269 270 channel->substream = substream; 271 272 if (cfg->direction == MOST_CH_TX) { 273 channel->playback_task = kthread_run(playback_thread, channel, 274 "most_audio_playback"); 275 if (IS_ERR(channel->playback_task)) { 276 pr_err("Couldn't start thread\n"); 277 return PTR_ERR(channel->playback_task); 278 } 279 } 280 281 ret = most_start_channel(channel->iface, channel->id, &comp); 282 if (ret) { 283 pr_err("most_start_channel() failed!\n"); 284 if (cfg->direction == MOST_CH_TX) 285 kthread_stop(channel->playback_task); 286 return ret; 287 } 288 289 runtime->hw = channel->pcm_hardware; 290 return 0; 291} 292 293/** 294 * pcm_close - implements close callback function for PCM middle layer 295 * @substream: sub-stream pointer 296 * 297 * Obviously, this is called when a PCM substream is closed. Any private 298 * instance for a PCM substream allocated in the open callback will be 299 * released here. 300 * 301 * Returns 0 on success or error code otherwise. 302 */ 303static int pcm_close(struct snd_pcm_substream *substream) 304{ 305 struct channel *channel = substream->private_data; 306 307 if (channel->cfg->direction == MOST_CH_TX) 308 kthread_stop(channel->playback_task); 309 most_stop_channel(channel->iface, channel->id, &comp); 310 return 0; 311} 312 313/** 314 * pcm_prepare - implements prepare callback function for PCM middle layer 315 * @substream: substream pointer 316 * 317 * This callback is called when the PCM is "prepared". Format rate, sample rate, 318 * etc., can be set here. This callback can be called many times at each setup. 319 * 320 * Returns 0 on success or error code otherwise. 321 */ 322static int pcm_prepare(struct snd_pcm_substream *substream) 323{ 324 struct channel *channel = substream->private_data; 325 struct snd_pcm_runtime *runtime = substream->runtime; 326 struct most_channel_config *cfg = channel->cfg; 327 int width = snd_pcm_format_physical_width(runtime->format); 328 329 channel->copy_fn = NULL; 330 331 if (cfg->direction == MOST_CH_TX) { 332 if (snd_pcm_format_big_endian(runtime->format) || width == 8) 333 channel->copy_fn = alsa_to_most_memcpy; 334 else if (width == 16) 335 channel->copy_fn = alsa_to_most_copy16; 336 else if (width == 24) 337 channel->copy_fn = alsa_to_most_copy24; 338 else if (width == 32) 339 channel->copy_fn = alsa_to_most_copy32; 340 } else { 341 if (snd_pcm_format_big_endian(runtime->format) || width == 8) 342 channel->copy_fn = most_to_alsa_memcpy; 343 else if (width == 16) 344 channel->copy_fn = most_to_alsa_copy16; 345 else if (width == 24) 346 channel->copy_fn = most_to_alsa_copy24; 347 else if (width == 32) 348 channel->copy_fn = most_to_alsa_copy32; 349 } 350 351 if (!channel->copy_fn) 352 return -EINVAL; 353 channel->period_pos = 0; 354 channel->buffer_pos = 0; 355 return 0; 356} 357 358/** 359 * pcm_trigger - implements trigger callback function for PCM middle layer 360 * @substream: substream pointer 361 * @cmd: action to perform 362 * 363 * This is called when the PCM is started, stopped or paused. The action will be 364 * specified in the second argument, SNDRV_PCM_TRIGGER_XXX 365 * 366 * Returns 0 on success or error code otherwise. 367 */ 368static int pcm_trigger(struct snd_pcm_substream *substream, int cmd) 369{ 370 struct channel *channel = substream->private_data; 371 372 switch (cmd) { 373 case SNDRV_PCM_TRIGGER_START: 374 channel->is_stream_running = true; 375 wake_up_interruptible(&channel->playback_waitq); 376 return 0; 377 378 case SNDRV_PCM_TRIGGER_STOP: 379 channel->is_stream_running = false; 380 return 0; 381 382 default: 383 return -EINVAL; 384 } 385 return 0; 386} 387 388/** 389 * pcm_pointer - implements pointer callback function for PCM middle layer 390 * @substream: substream pointer 391 * 392 * This callback is called when the PCM middle layer inquires the current 393 * hardware position on the buffer. The position must be returned in frames, 394 * ranging from 0 to buffer_size-1. 395 */ 396static snd_pcm_uframes_t pcm_pointer(struct snd_pcm_substream *substream) 397{ 398 struct channel *channel = substream->private_data; 399 400 return channel->buffer_pos; 401} 402 403/** 404 * Initialization of struct snd_pcm_ops 405 */ 406static const struct snd_pcm_ops pcm_ops = { 407 .open = pcm_open, 408 .close = pcm_close, 409 .prepare = pcm_prepare, 410 .trigger = pcm_trigger, 411 .pointer = pcm_pointer, 412}; 413 414static int split_arg_list(char *buf, u16 *ch_num, char **sample_res) 415{ 416 char *num; 417 int ret; 418 419 num = strsep(&buf, "x"); 420 if (!num) 421 goto err; 422 ret = kstrtou16(num, 0, ch_num); 423 if (ret) 424 goto err; 425 *sample_res = strsep(&buf, ".\n"); 426 if (!*sample_res) 427 goto err; 428 return 0; 429 430err: 431 pr_err("Bad PCM format\n"); 432 return -EINVAL; 433} 434 435static const struct sample_resolution_info { 436 const char *sample_res; 437 int bytes; 438 u64 formats; 439} sinfo[] = { 440 { "8", 1, SNDRV_PCM_FMTBIT_S8 }, 441 { "16", 2, SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S16_BE }, 442 { "24", 3, SNDRV_PCM_FMTBIT_S24_3LE | SNDRV_PCM_FMTBIT_S24_3BE }, 443 { "32", 4, SNDRV_PCM_FMTBIT_S32_LE | SNDRV_PCM_FMTBIT_S32_BE }, 444}; 445 446static int audio_set_hw_params(struct snd_pcm_hardware *pcm_hw, 447 u16 ch_num, char *sample_res, 448 struct most_channel_config *cfg) 449{ 450 int i; 451 452 for (i = 0; i < ARRAY_SIZE(sinfo); i++) { 453 if (!strcmp(sample_res, sinfo[i].sample_res)) 454 goto found; 455 } 456 pr_err("Unsupported PCM format\n"); 457 return -EINVAL; 458 459found: 460 if (!ch_num) { 461 pr_err("Bad number of channels\n"); 462 return -EINVAL; 463 } 464 465 if (cfg->subbuffer_size != ch_num * sinfo[i].bytes) { 466 pr_err("Audio resolution doesn't fit subbuffer size\n"); 467 return -EINVAL; 468 } 469 470 pcm_hw->info = MOST_PCM_INFO; 471 pcm_hw->rates = SNDRV_PCM_RATE_48000; 472 pcm_hw->rate_min = 48000; 473 pcm_hw->rate_max = 48000; 474 pcm_hw->buffer_bytes_max = cfg->num_buffers * cfg->buffer_size; 475 pcm_hw->period_bytes_min = cfg->buffer_size; 476 pcm_hw->period_bytes_max = cfg->buffer_size; 477 pcm_hw->periods_min = 1; 478 pcm_hw->periods_max = cfg->num_buffers; 479 pcm_hw->channels_min = ch_num; 480 pcm_hw->channels_max = ch_num; 481 pcm_hw->formats = sinfo[i].formats; 482 return 0; 483} 484 485static void release_adapter(struct sound_adapter *adpt) 486{ 487 struct channel *channel, *tmp; 488 489 list_for_each_entry_safe(channel, tmp, &adpt->dev_list, list) { 490 list_del(&channel->list); 491 kfree(channel); 492 } 493 if (adpt->card) 494 snd_card_free(adpt->card); 495 list_del(&adpt->list); 496 kfree(adpt); 497} 498 499/** 500 * audio_probe_channel - probe function of the driver module 501 * @iface: pointer to interface instance 502 * @channel_id: channel index/ID 503 * @cfg: pointer to actual channel configuration 504 * @arg_list: string that provides the name of the device to be created in /dev 505 * plus the desired audio resolution 506 * 507 * Creates sound card, pcm device, sets pcm ops and registers sound card. 508 * 509 * Returns 0 on success or error code otherwise. 510 */ 511static int audio_probe_channel(struct most_interface *iface, int channel_id, 512 struct most_channel_config *cfg, 513 char *device_name, char *arg_list) 514{ 515 struct channel *channel; 516 struct sound_adapter *adpt; 517 struct snd_pcm *pcm; 518 int playback_count = 0; 519 int capture_count = 0; 520 int ret; 521 int direction; 522 u16 ch_num; 523 char *sample_res; 524 char arg_list_cpy[STRING_SIZE]; 525 526 if (cfg->data_type != MOST_CH_SYNC) { 527 pr_err("Incompatible channel type\n"); 528 return -EINVAL; 529 } 530 strscpy(arg_list_cpy, arg_list, STRING_SIZE); 531 ret = split_arg_list(arg_list_cpy, &ch_num, &sample_res); 532 if (ret < 0) 533 return ret; 534 535 list_for_each_entry(adpt, &adpt_list, list) { 536 if (adpt->iface != iface) 537 continue; 538 if (adpt->registered) 539 return -ENOSPC; 540 adpt->pcm_dev_idx++; 541 goto skip_adpt_alloc; 542 } 543 adpt = kzalloc(sizeof(*adpt), GFP_KERNEL); 544 if (!adpt) 545 return -ENOMEM; 546 547 adpt->iface = iface; 548 INIT_LIST_HEAD(&adpt->dev_list); 549 iface->priv = adpt; 550 list_add_tail(&adpt->list, &adpt_list); 551 ret = snd_card_new(iface->driver_dev, -1, "INIC", THIS_MODULE, 552 sizeof(*channel), &adpt->card); 553 if (ret < 0) 554 goto err_free_adpt; 555 snprintf(adpt->card->driver, sizeof(adpt->card->driver), 556 "%s", DRIVER_NAME); 557 snprintf(adpt->card->shortname, sizeof(adpt->card->shortname), 558 "Microchip INIC"); 559 snprintf(adpt->card->longname, sizeof(adpt->card->longname), 560 "%s at %s", adpt->card->shortname, iface->description); 561skip_adpt_alloc: 562 if (get_channel(iface, channel_id)) { 563 pr_err("channel (%s:%d) is already linked\n", 564 iface->description, channel_id); 565 return -EEXIST; 566 } 567 568 if (cfg->direction == MOST_CH_TX) { 569 playback_count = 1; 570 direction = SNDRV_PCM_STREAM_PLAYBACK; 571 } else { 572 capture_count = 1; 573 direction = SNDRV_PCM_STREAM_CAPTURE; 574 } 575 channel = kzalloc(sizeof(*channel), GFP_KERNEL); 576 if (!channel) { 577 ret = -ENOMEM; 578 goto err_free_adpt; 579 } 580 channel->card = adpt->card; 581 channel->cfg = cfg; 582 channel->iface = iface; 583 channel->id = channel_id; 584 init_waitqueue_head(&channel->playback_waitq); 585 list_add_tail(&channel->list, &adpt->dev_list); 586 587 ret = audio_set_hw_params(&channel->pcm_hardware, ch_num, sample_res, 588 cfg); 589 if (ret) 590 goto err_free_adpt; 591 592 ret = snd_pcm_new(adpt->card, device_name, adpt->pcm_dev_idx, 593 playback_count, capture_count, &pcm); 594 595 if (ret < 0) 596 goto err_free_adpt; 597 598 pcm->private_data = channel; 599 strscpy(pcm->name, device_name, sizeof(pcm->name)); 600 snd_pcm_set_ops(pcm, direction, &pcm_ops); 601 snd_pcm_set_managed_buffer_all(pcm, SNDRV_DMA_TYPE_VMALLOC, NULL, 0, 0); 602 return 0; 603 604err_free_adpt: 605 release_adapter(adpt); 606 return ret; 607} 608 609static int audio_create_sound_card(void) 610{ 611 int ret; 612 struct sound_adapter *adpt; 613 614 list_for_each_entry(adpt, &adpt_list, list) { 615 if (!adpt->registered) 616 goto adpt_alloc; 617 } 618 return -ENODEV; 619adpt_alloc: 620 ret = snd_card_register(adpt->card); 621 if (ret < 0) { 622 release_adapter(adpt); 623 return ret; 624 } 625 adpt->registered = true; 626 return 0; 627} 628 629/** 630 * audio_disconnect_channel - function to disconnect a channel 631 * @iface: pointer to interface instance 632 * @channel_id: channel index 633 * 634 * This frees allocated memory and removes the sound card from ALSA 635 * 636 * Returns 0 on success or error code otherwise. 637 */ 638static int audio_disconnect_channel(struct most_interface *iface, 639 int channel_id) 640{ 641 struct channel *channel; 642 struct sound_adapter *adpt = iface->priv; 643 644 channel = get_channel(iface, channel_id); 645 if (!channel) 646 return -EINVAL; 647 648 list_del(&channel->list); 649 650 kfree(channel); 651 if (list_empty(&adpt->dev_list)) 652 release_adapter(adpt); 653 return 0; 654} 655 656/** 657 * audio_rx_completion - completion handler for rx channels 658 * @mbo: pointer to buffer object that has completed 659 * 660 * This searches for the channel this MBO belongs to and copy the data from MBO 661 * to ring buffer 662 * 663 * Returns 0 on success or error code otherwise. 664 */ 665static int audio_rx_completion(struct mbo *mbo) 666{ 667 struct channel *channel = get_channel(mbo->ifp, mbo->hdm_channel_id); 668 bool period_elapsed = false; 669 670 if (!channel) 671 return -EINVAL; 672 if (channel->is_stream_running) 673 period_elapsed = copy_data(channel, mbo); 674 most_put_mbo(mbo); 675 if (period_elapsed) 676 snd_pcm_period_elapsed(channel->substream); 677 return 0; 678} 679 680/** 681 * audio_tx_completion - completion handler for tx channels 682 * @iface: pointer to interface instance 683 * @channel_id: channel index/ID 684 * 685 * This searches the channel that belongs to this combination of interface 686 * pointer and channel ID and wakes a process sitting in the wait queue of 687 * this channel. 688 * 689 * Returns 0 on success or error code otherwise. 690 */ 691static int audio_tx_completion(struct most_interface *iface, int channel_id) 692{ 693 struct channel *channel = get_channel(iface, channel_id); 694 695 if (!channel) 696 return -EINVAL; 697 698 wake_up_interruptible(&channel->playback_waitq); 699 return 0; 700} 701 702/** 703 * Initialization of the struct most_component 704 */ 705static struct most_component comp = { 706 .mod = THIS_MODULE, 707 .name = DRIVER_NAME, 708 .probe_channel = audio_probe_channel, 709 .disconnect_channel = audio_disconnect_channel, 710 .rx_completion = audio_rx_completion, 711 .tx_completion = audio_tx_completion, 712 .cfg_complete = audio_create_sound_card, 713}; 714 715static int __init audio_init(void) 716{ 717 int ret; 718 719 INIT_LIST_HEAD(&adpt_list); 720 721 ret = most_register_component(&comp); 722 if (ret) { 723 pr_err("Failed to register %s\n", comp.name); 724 return ret; 725 } 726 ret = most_register_configfs_subsys(&comp); 727 if (ret) { 728 pr_err("Failed to register %s configfs subsys\n", comp.name); 729 most_deregister_component(&comp); 730 } 731 return ret; 732} 733 734static void __exit audio_exit(void) 735{ 736 most_deregister_configfs_subsys(&comp); 737 most_deregister_component(&comp); 738} 739 740module_init(audio_init); 741module_exit(audio_exit); 742 743MODULE_LICENSE("GPL"); 744MODULE_AUTHOR("Christian Gromm <christian.gromm@microchip.com>"); 745MODULE_DESCRIPTION("Sound Component Module for Mostcore");