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