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