27
27
#include <linux/delay.h>
28
28
#include <linux/atomic.h>
29
29
#include <linux/module.h>
30
+ #include <linux/completion.h>
30
31
31
32
#include "bcm2835.h"
32
33
37
38
38
39
/* ---- Private Constants and Types ------------------------------------------ */
39
40
41
+ #define BCM2835_AUDIO_STOP 0
42
+ #define BCM2835_AUDIO_START 1
43
+ #define BCM2835_AUDIO_WRITE 2
44
+
40
45
/* Logging macros (for remapping to other logging mechanisms, i.e., printf) */
41
46
#ifdef AUDIO_DEBUG_ENABLE
42
47
#define LOG_ERR ( fmt , arg ... ) pr_err( "%s:%d " fmt, __func__, __LINE__, ##arg)
53
58
typedef struct opaque_AUDIO_INSTANCE_T {
54
59
uint32_t num_connections ;
55
60
VCHI_SERVICE_HANDLE_T vchi_handle [VCHI_MAX_NUM_CONNECTIONS ];
56
- struct semaphore msg_avail_event ;
61
+ struct completion msg_avail_comp ;
57
62
struct mutex vchi_mutex ;
58
63
bcm2835_alsa_stream_t * alsa_stream ;
59
64
int32_t result ;
@@ -70,27 +75,35 @@ bool force_bulk = false;
70
75
71
76
static int bcm2835_audio_stop_worker (bcm2835_alsa_stream_t * alsa_stream );
72
77
static int bcm2835_audio_start_worker (bcm2835_alsa_stream_t * alsa_stream );
78
+ static int bcm2835_audio_write_worker (bcm2835_alsa_stream_t * alsa_stream ,
79
+ uint32_t count , void * src );
73
80
74
81
typedef struct {
75
82
struct work_struct my_work ;
76
83
bcm2835_alsa_stream_t * alsa_stream ;
77
- int x ;
84
+ int cmd ;
85
+ void * src ;
86
+ uint32_t count ;
78
87
} my_work_t ;
79
88
80
89
static void my_wq_function (struct work_struct * work )
81
90
{
82
91
my_work_t * w = (my_work_t * ) work ;
83
92
int ret = -9 ;
84
- LOG_DBG (" .. IN %p:%d\n" , w -> alsa_stream , w -> x );
85
- switch (w -> x ) {
86
- case 1 :
93
+ LOG_DBG (" .. IN %p:%d\n" , w -> alsa_stream , w -> cmd );
94
+ switch (w -> cmd ) {
95
+ case BCM2835_AUDIO_START :
87
96
ret = bcm2835_audio_start_worker (w -> alsa_stream );
88
97
break ;
89
- case 2 :
98
+ case BCM2835_AUDIO_STOP :
90
99
ret = bcm2835_audio_stop_worker (w -> alsa_stream );
91
100
break ;
101
+ case BCM2835_AUDIO_WRITE :
102
+ ret = bcm2835_audio_write_worker (w -> alsa_stream , w -> count ,
103
+ w -> src );
104
+ break ;
92
105
default :
93
- LOG_ERR (" Unexpected work: %p:%d\n" , w -> alsa_stream , w -> x );
106
+ LOG_ERR (" Unexpected work: %p:%d\n" , w -> alsa_stream , w -> cmd );
94
107
break ;
95
108
}
96
109
kfree ((void * )work );
@@ -107,7 +120,7 @@ int bcm2835_audio_start(bcm2835_alsa_stream_t * alsa_stream)
107
120
if (work ) {
108
121
INIT_WORK ((struct work_struct * )work , my_wq_function );
109
122
work -> alsa_stream = alsa_stream ;
110
- work -> x = 1 ;
123
+ work -> cmd = BCM2835_AUDIO_START ;
111
124
if (queue_work
112
125
(alsa_stream -> my_wq , (struct work_struct * )work ))
113
126
ret = 0 ;
@@ -128,7 +141,31 @@ int bcm2835_audio_stop(bcm2835_alsa_stream_t * alsa_stream)
128
141
if (work ) {
129
142
INIT_WORK ((struct work_struct * )work , my_wq_function );
130
143
work -> alsa_stream = alsa_stream ;
131
- work -> x = 2 ;
144
+ work -> cmd = BCM2835_AUDIO_STOP ;
145
+ if (queue_work
146
+ (alsa_stream -> my_wq , (struct work_struct * )work ))
147
+ ret = 0 ;
148
+ } else
149
+ LOG_ERR (" .. Error: NULL work kmalloc\n" );
150
+ }
151
+ LOG_DBG (" .. OUT %d\n" , ret );
152
+ return ret ;
153
+ }
154
+
155
+ int bcm2835_audio_write (bcm2835_alsa_stream_t * alsa_stream ,
156
+ uint32_t count , void * src )
157
+ {
158
+ int ret = -1 ;
159
+ LOG_DBG (" .. IN\n" );
160
+ if (alsa_stream -> my_wq ) {
161
+ my_work_t * work = kmalloc (sizeof (my_work_t ), GFP_ATOMIC );
162
+ /*--- Queue some work (item 1) ---*/
163
+ if (work ) {
164
+ INIT_WORK ((struct work_struct * )work , my_wq_function );
165
+ work -> alsa_stream = alsa_stream ;
166
+ work -> cmd = BCM2835_AUDIO_WRITE ;
167
+ work -> src = src ;
168
+ work -> count = count ;
132
169
if (queue_work
133
170
(alsa_stream -> my_wq , (struct work_struct * )work ))
134
171
ret = 0 ;
@@ -178,7 +215,7 @@ static void audio_vchi_callback(void *param,
178
215
(" .. instance=%p, m.type=VC_AUDIO_MSG_TYPE_RESULT, success=%d\n" ,
179
216
instance , m .u .result .success );
180
217
instance -> result = m .u .result .success ;
181
- up (& instance -> msg_avail_event );
218
+ complete (& instance -> msg_avail_comp );
182
219
} else if (m .type == VC_AUDIO_MSG_TYPE_COMPLETE ) {
183
220
irq_handler_t callback = (irq_handler_t ) m .u .complete .callback ;
184
221
LOG_DBG
@@ -435,8 +472,8 @@ static int bcm2835_audio_set_ctls_chan(bcm2835_alsa_stream_t * alsa_stream,
435
472
m .u .control .dest = chip -> dest ;
436
473
m .u .control .volume = chip -> volume ;
437
474
438
- /* Create the message available event */
439
- sema_init (& instance -> msg_avail_event , 0 );
475
+ /* Create the message available completion */
476
+ init_completion (& instance -> msg_avail_comp );
440
477
441
478
/* Send the message to the videocore */
442
479
success = vchi_msg_queue (instance -> vchi_handle [0 ],
@@ -452,11 +489,10 @@ static int bcm2835_audio_set_ctls_chan(bcm2835_alsa_stream_t * alsa_stream,
452
489
}
453
490
454
491
/* We are expecting a reply from the videocore */
455
- if (down_interruptible (& instance -> msg_avail_event )) {
492
+ ret = wait_for_completion_interruptible (& instance -> msg_avail_comp );
493
+ if (ret ) {
456
494
LOG_ERR ("%s: failed on waiting for event (status=%d)\n" ,
457
495
__func__ , success );
458
-
459
- ret = -1 ;
460
496
goto unlock ;
461
497
}
462
498
@@ -539,8 +575,8 @@ int bcm2835_audio_set_params(bcm2835_alsa_stream_t * alsa_stream,
539
575
m .u .config .samplerate = samplerate ;
540
576
m .u .config .bps = bps ;
541
577
542
- /* Create the message available event */
543
- sema_init (& instance -> msg_avail_event , 0 );
578
+ /* Create the message available completion */
579
+ init_completion (& instance -> msg_avail_comp );
544
580
545
581
/* Send the message to the videocore */
546
582
success = vchi_msg_queue (instance -> vchi_handle [0 ],
@@ -556,11 +592,10 @@ int bcm2835_audio_set_params(bcm2835_alsa_stream_t * alsa_stream,
556
592
}
557
593
558
594
/* We are expecting a reply from the videocore */
559
- if (down_interruptible (& instance -> msg_avail_event )) {
595
+ ret = wait_for_completion_interruptible (& instance -> msg_avail_comp );
596
+ if (ret ) {
560
597
LOG_ERR ("%s: failed on waiting for event (status=%d)\n" ,
561
598
__func__ , success );
562
-
563
- ret = -1 ;
564
599
goto unlock ;
565
600
}
566
601
@@ -688,8 +723,8 @@ int bcm2835_audio_close(bcm2835_alsa_stream_t * alsa_stream)
688
723
689
724
m .type = VC_AUDIO_MSG_TYPE_CLOSE ;
690
725
691
- /* Create the message available event */
692
- sema_init (& instance -> msg_avail_event , 0 );
726
+ /* Create the message available completion */
727
+ init_completion (& instance -> msg_avail_comp );
693
728
694
729
/* Send the message to the videocore */
695
730
success = vchi_msg_queue (instance -> vchi_handle [0 ],
@@ -702,11 +737,11 @@ int bcm2835_audio_close(bcm2835_alsa_stream_t * alsa_stream)
702
737
ret = -1 ;
703
738
goto unlock ;
704
739
}
705
- if (down_interruptible (& instance -> msg_avail_event )) {
740
+
741
+ ret = wait_for_completion_interruptible (& instance -> msg_avail_comp );
742
+ if (ret ) {
706
743
LOG_ERR ("%s: failed on waiting for event (status=%d)" ,
707
744
__func__ , success );
708
-
709
- ret = -1 ;
710
745
goto unlock ;
711
746
}
712
747
if (instance -> result != 0 ) {
@@ -732,8 +767,8 @@ int bcm2835_audio_close(bcm2835_alsa_stream_t * alsa_stream)
732
767
return ret ;
733
768
}
734
769
735
- int bcm2835_audio_write (bcm2835_alsa_stream_t * alsa_stream , uint32_t count ,
736
- void * src )
770
+ int bcm2835_audio_write_worker (bcm2835_alsa_stream_t * alsa_stream ,
771
+ uint32_t count , void * src )
737
772
{
738
773
VC_AUDIO_MSG_T m ;
739
774
AUDIO_INSTANCE_T * instance = alsa_stream -> instance ;
0 commit comments