forked from ~ljy/RK356X_SDK_RELEASE

hc
2024-05-10 37f49e37ab4cb5d0bc4c60eb5c6d4dd57db767bb
kernel/drivers/staging/most/sound/sound.c
....@@ -10,18 +10,19 @@
1010 #include <linux/module.h>
1111 #include <linux/printk.h>
1212 #include <linux/kernel.h>
13
+#include <linux/slab.h>
1314 #include <linux/init.h>
1415 #include <sound/core.h>
1516 #include <sound/pcm.h>
1617 #include <sound/pcm_params.h>
1718 #include <linux/sched.h>
1819 #include <linux/kthread.h>
19
-#include <most/core.h>
20
+#include <linux/most.h>
2021
2122 #define DRIVER_NAME "sound"
23
+#define STRING_SIZE 80
2224
23
-static struct list_head dev_list;
24
-static struct core_component comp;
25
+static struct most_component comp;
2526
2627 /**
2728 * struct channel - private structure to keep channel specific data
....@@ -49,12 +50,21 @@
4950 unsigned int period_pos;
5051 unsigned int buffer_pos;
5152 bool is_stream_running;
52
-
5353 struct task_struct *playback_task;
5454 wait_queue_head_t playback_waitq;
55
-
5655 void (*copy_fn)(void *alsa, void *most, unsigned int bytes);
5756 };
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;
5868
5969 #define MOST_PCM_INFO (SNDRV_PCM_INFO_MMAP | \
6070 SNDRV_PCM_INFO_MMAP_VALID | \
....@@ -159,13 +169,13 @@
159169 static struct channel *get_channel(struct most_interface *iface,
160170 int channel_id)
161171 {
172
+ struct sound_adapter *adpt = iface->priv;
162173 struct channel *channel, *tmp;
163174
164
- list_for_each_entry_safe(channel, tmp, &dev_list, list) {
175
+ list_for_each_entry_safe(channel, tmp, &adpt->dev_list, list) {
165176 if ((channel->iface == iface) && (channel->id == channel_id))
166177 return channel;
167178 }
168
-
169179 return NULL;
170180 }
171181
....@@ -209,7 +219,6 @@
209219 channel->period_pos -= runtime->period_size;
210220 return true;
211221 }
212
-
213222 return false;
214223 }
215224
....@@ -249,7 +258,6 @@
249258 if (period_elapsed)
250259 snd_pcm_period_elapsed(channel->substream);
251260 }
252
-
253261 return 0;
254262 }
255263
....@@ -267,6 +275,7 @@
267275 struct channel *channel = substream->private_data;
268276 struct snd_pcm_runtime *runtime = substream->runtime;
269277 struct most_channel_config *cfg = channel->cfg;
278
+ int ret;
270279
271280 channel->substream = substream;
272281
....@@ -279,11 +288,12 @@
279288 }
280289 }
281290
282
- if (most_start_channel(channel->iface, channel->id, &comp)) {
291
+ ret = most_start_channel(channel->iface, channel->id, &comp);
292
+ if (ret) {
283293 pr_err("most_start_channel() failed!\n");
284294 if (cfg->direction == MOST_CH_TX)
285295 kthread_stop(channel->playback_task);
286
- return -EBUSY;
296
+ return ret;
287297 }
288298
289299 runtime->hw = channel->pcm_hardware;
....@@ -307,48 +317,7 @@
307317 if (channel->cfg->direction == MOST_CH_TX)
308318 kthread_stop(channel->playback_task);
309319 most_stop_channel(channel->iface, channel->id, &comp);
310
-
311320 return 0;
312
-}
313
-
314
-/**
315
- * pcm_hw_params - implements hw_params callback function for PCM middle layer
316
- * @substream: sub-stream pointer
317
- * @hw_params: contains the hardware parameters set by the application
318
- *
319
- * This is called when the hardware parameters is set by the application, that
320
- * is, once when the buffer size, the period size, the format, etc. are defined
321
- * for the PCM substream. Many hardware setups should be done is this callback,
322
- * including the allocation of buffers.
323
- *
324
- * Returns 0 on success or error code otherwise.
325
- */
326
-static int pcm_hw_params(struct snd_pcm_substream *substream,
327
- struct snd_pcm_hw_params *hw_params)
328
-{
329
- struct channel *channel = substream->private_data;
330
-
331
- if ((params_channels(hw_params) > channel->pcm_hardware.channels_max) ||
332
- (params_channels(hw_params) < channel->pcm_hardware.channels_min)) {
333
- pr_err("Requested number of channels not supported.\n");
334
- return -EINVAL;
335
- }
336
- return snd_pcm_lib_alloc_vmalloc_buffer(substream,
337
- params_buffer_bytes(hw_params));
338
-}
339
-
340
-/**
341
- * pcm_hw_free - implements hw_free callback function for PCM middle layer
342
- * @substream: substream pointer
343
- *
344
- * This is called to release the resources allocated via hw_params.
345
- * This function will be always called before the close callback is called.
346
- *
347
- * Returns 0 on success or error code otherwise.
348
- */
349
-static int pcm_hw_free(struct snd_pcm_substream *substream)
350
-{
351
- return snd_pcm_lib_free_vmalloc_buffer(substream);
352321 }
353322
354323 /**
....@@ -389,14 +358,10 @@
389358 channel->copy_fn = most_to_alsa_copy32;
390359 }
391360
392
- if (!channel->copy_fn) {
393
- pr_err("unsupported format\n");
361
+ if (!channel->copy_fn)
394362 return -EINVAL;
395
- }
396
-
397363 channel->period_pos = 0;
398364 channel->buffer_pos = 0;
399
-
400365 return 0;
401366 }
402367
....@@ -425,7 +390,6 @@
425390 return 0;
426391
427392 default:
428
- pr_info("%s(), invalid\n", __func__);
429393 return -EINVAL;
430394 }
431395 return 0;
....@@ -452,26 +416,16 @@
452416 static const struct snd_pcm_ops pcm_ops = {
453417 .open = pcm_open,
454418 .close = pcm_close,
455
- .ioctl = snd_pcm_lib_ioctl,
456
- .hw_params = pcm_hw_params,
457
- .hw_free = pcm_hw_free,
458419 .prepare = pcm_prepare,
459420 .trigger = pcm_trigger,
460421 .pointer = pcm_pointer,
461
- .page = snd_pcm_lib_get_vmalloc_page,
462422 };
463423
464
-static int split_arg_list(char *buf, char **card_name, u16 *ch_num,
465
- char **sample_res)
424
+static int split_arg_list(char *buf, u16 *ch_num, char **sample_res)
466425 {
467426 char *num;
468427 int ret;
469428
470
- *card_name = strsep(&buf, ".");
471
- if (!*card_name) {
472
- pr_err("Missing sound card name\n");
473
- return -EIO;
474
- }
475429 num = strsep(&buf, "x");
476430 if (!num)
477431 goto err;
....@@ -485,7 +439,7 @@
485439
486440 err:
487441 pr_err("Bad PCM format\n");
488
- return -EIO;
442
+ return -EINVAL;
489443 }
490444
491445 static const struct sample_resolution_info {
....@@ -510,7 +464,7 @@
510464 goto found;
511465 }
512466 pr_err("Unsupported PCM format\n");
513
- return -EIO;
467
+ return -EINVAL;
514468
515469 found:
516470 if (!ch_num) {
....@@ -538,6 +492,20 @@
538492 return 0;
539493 }
540494
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
+
541509 /**
542510 * audio_probe_channel - probe function of the driver module
543511 * @iface: pointer to interface instance
....@@ -552,31 +520,59 @@
552520 */
553521 static int audio_probe_channel(struct most_interface *iface, int channel_id,
554522 struct most_channel_config *cfg,
555
- char *arg_list)
523
+ char *device_name, char *arg_list)
556524 {
557525 struct channel *channel;
558
- struct snd_card *card;
526
+ struct sound_adapter *adpt;
559527 struct snd_pcm *pcm;
560528 int playback_count = 0;
561529 int capture_count = 0;
562530 int ret;
563531 int direction;
564
- char *card_name;
565532 u16 ch_num;
566533 char *sample_res;
567
-
568
- if (!iface)
569
- return -EINVAL;
534
+ char arg_list_cpy[STRING_SIZE];
570535
571536 if (cfg->data_type != MOST_CH_SYNC) {
572537 pr_err("Incompatible channel type\n");
573538 return -EINVAL;
574539 }
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;
575544
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:
576572 if (get_channel(iface, channel_id)) {
577573 pr_err("channel (%s:%d) is already linked\n",
578574 iface->description, channel_id);
579
- return -EINVAL;
575
+ return -EEXIST;
580576 }
581577
582578 if (cfg->direction == MOST_CH_TX) {
....@@ -586,54 +582,58 @@
586582 capture_count = 1;
587583 direction = SNDRV_PCM_STREAM_CAPTURE;
588584 }
589
-
590
- ret = split_arg_list(arg_list, &card_name, &ch_num, &sample_res);
591
- if (ret < 0)
592
- return ret;
593
-
594
- ret = snd_card_new(&iface->dev, -1, card_name, THIS_MODULE,
595
- sizeof(*channel), &card);
596
- if (ret < 0)
597
- return ret;
598
-
599
- channel = card->private_data;
600
- channel->card = card;
585
+ channel = kzalloc(sizeof(*channel), GFP_KERNEL);
586
+ if (!channel) {
587
+ ret = -ENOMEM;
588
+ goto err_free_adpt;
589
+ }
590
+ channel->card = adpt->card;
601591 channel->cfg = cfg;
602592 channel->iface = iface;
603593 channel->id = channel_id;
604594 init_waitqueue_head(&channel->playback_waitq);
595
+ list_add_tail(&channel->list, &adpt->dev_list);
605596
606597 ret = audio_set_hw_params(&channel->pcm_hardware, ch_num, sample_res,
607598 cfg);
608599 if (ret)
609
- goto err_free_card;
600
+ goto err_free_adpt;
610601
611
- snprintf(card->driver, sizeof(card->driver), "%s", DRIVER_NAME);
612
- snprintf(card->shortname, sizeof(card->shortname), "Microchip MOST:%d",
613
- card->number);
614
- snprintf(card->longname, sizeof(card->longname), "%s at %s, ch %d",
615
- card->shortname, iface->description, channel_id);
602
+ ret = snd_pcm_new(adpt->card, device_name, adpt->pcm_dev_idx,
603
+ playback_count, capture_count, &pcm);
616604
617
- ret = snd_pcm_new(card, card_name, 0, playback_count,
618
- capture_count, &pcm);
619605 if (ret < 0)
620
- goto err_free_card;
606
+ goto err_free_adpt;
621607
622608 pcm->private_data = channel;
623
-
609
+ strscpy(pcm->name, device_name, sizeof(pcm->name));
624610 snd_pcm_set_ops(pcm, direction, &pcm_ops);
625
-
626
- ret = snd_card_register(card);
627
- if (ret < 0)
628
- goto err_free_card;
629
-
630
- list_add_tail(&channel->list, &dev_list);
631
-
611
+ snd_pcm_set_managed_buffer_all(pcm, SNDRV_DMA_TYPE_VMALLOC, NULL, 0, 0);
632612 return 0;
633613
634
-err_free_card:
635
- snd_card_free(card);
614
+err_free_adpt:
615
+ release_adapter(adpt);
636616 return ret;
617
+}
618
+
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;
637637 }
638638
639639 /**
....@@ -649,17 +649,17 @@
649649 int channel_id)
650650 {
651651 struct channel *channel;
652
+ struct sound_adapter *adpt = iface->priv;
652653
653654 channel = get_channel(iface, channel_id);
654
- if (!channel) {
655
- pr_err("sound_disconnect_channel(), invalid channel %d\n",
656
- channel_id);
655
+ if (!channel)
657656 return -EINVAL;
658
- }
659657
660658 list_del(&channel->list);
661
- snd_card_free(channel->card);
662659
660
+ kfree(channel);
661
+ if (list_empty(&adpt->dev_list))
662
+ release_adapter(adpt);
663663 return 0;
664664 }
665665
....@@ -677,20 +677,13 @@
677677 struct channel *channel = get_channel(mbo->ifp, mbo->hdm_channel_id);
678678 bool period_elapsed = false;
679679
680
- if (!channel) {
681
- pr_err("sound_rx_completion(), invalid channel %d\n",
682
- mbo->hdm_channel_id);
680
+ if (!channel)
683681 return -EINVAL;
684
- }
685
-
686682 if (channel->is_stream_running)
687683 period_elapsed = copy_data(channel, mbo);
688
-
689684 most_put_mbo(mbo);
690
-
691685 if (period_elapsed)
692686 snd_pcm_period_elapsed(channel->substream);
693
-
694687 return 0;
695688 }
696689
....@@ -709,48 +702,48 @@
709702 {
710703 struct channel *channel = get_channel(iface, channel_id);
711704
712
- if (!channel) {
713
- pr_err("sound_tx_completion(), invalid channel %d\n",
714
- channel_id);
705
+ if (!channel)
715706 return -EINVAL;
716
- }
717707
718708 wake_up_interruptible(&channel->playback_waitq);
719
-
720709 return 0;
721710 }
722711
723712 /**
724
- * Initialization of the struct core_component
713
+ * Initialization of the struct most_component
725714 */
726
-static struct core_component comp = {
715
+static struct most_component comp = {
716
+ .mod = THIS_MODULE,
727717 .name = DRIVER_NAME,
728718 .probe_channel = audio_probe_channel,
729719 .disconnect_channel = audio_disconnect_channel,
730720 .rx_completion = audio_rx_completion,
731721 .tx_completion = audio_tx_completion,
722
+ .cfg_complete = audio_create_sound_card,
732723 };
733724
734725 static int __init audio_init(void)
735726 {
736
- pr_info("init()\n");
727
+ int ret;
737728
738
- INIT_LIST_HEAD(&dev_list);
729
+ INIT_LIST_HEAD(&adpt_list);
739730
740
- return most_register_component(&comp);
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;
741742 }
742743
743744 static void __exit audio_exit(void)
744745 {
745
- struct channel *channel, *tmp;
746
-
747
- pr_info("exit()\n");
748
-
749
- list_for_each_entry_safe(channel, tmp, &dev_list, list) {
750
- list_del(&channel->list);
751
- snd_card_free(channel->card);
752
- }
753
-
746
+ most_deregister_configfs_subsys(&comp);
754747 most_deregister_component(&comp);
755748 }
756749