root/drivers/staging/most/sound/sound.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. swap_copy16
  2. swap_copy24
  3. swap_copy32
  4. alsa_to_most_memcpy
  5. alsa_to_most_copy16
  6. alsa_to_most_copy24
  7. alsa_to_most_copy32
  8. most_to_alsa_memcpy
  9. most_to_alsa_copy16
  10. most_to_alsa_copy24
  11. most_to_alsa_copy32
  12. get_channel
  13. copy_data
  14. playback_thread
  15. pcm_open
  16. pcm_close
  17. pcm_hw_params
  18. pcm_hw_free
  19. pcm_prepare
  20. pcm_trigger
  21. pcm_pointer
  22. split_arg_list
  23. audio_set_hw_params
  24. release_adapter
  25. audio_probe_channel
  26. audio_create_sound_card
  27. audio_disconnect_channel
  28. audio_rx_completion
  29. audio_tx_completion
  30. audio_init
  31. audio_exit

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

/* [<][>][^][v][top][bottom][index][help] */