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