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