Skip to content

Commit 146c08e

Browse files
wenlong.zhutobetter
authored andcommitted
UAC: uac related files update to kernel 5.15 [1/1]
PD#SWPL-114902 Problem: 1. AudioBridge module needs to be added to kernel 5.15. Solution: 1. Adjust the uac related files that AudioBridge depends on. Verify: A113L AD403 Board Change-Id: Ibd32c020c4feea085c65fb6c781467ff87c83b67 Signed-off-by: wenlong.zhu <[email protected]>
1 parent b8b551b commit 146c08e

File tree

4 files changed

+208
-0
lines changed

4 files changed

+208
-0
lines changed

drivers/usb/gadget/function/f_hid.c

Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,10 @@ struct f_hidg {
7979
struct usb_ep *out_ep;
8080
};
8181

82+
#ifdef CONFIG_AMLOGIC_BRIDGE_HID
83+
struct f_hidg *hid_h;
84+
#endif
85+
8286
static inline struct f_hidg *func_to_hidg(struct usb_function *f)
8387
{
8488
return container_of(f, struct f_hidg, func);
@@ -520,6 +524,97 @@ static ssize_t f_hidg_write(struct file *file, const char __user *buffer,
520524
return status;
521525
}
522526

527+
#ifdef CONFIG_AMLOGIC_BRIDGE_HID
528+
ssize_t f_hidg_internal_write(char *buffer, size_t count, int nonblock)
529+
{
530+
struct f_hidg *hidg = hid_h;
531+
struct usb_request *req;
532+
unsigned long flags;
533+
ssize_t status = -ENOMEM;
534+
535+
if (!hidg)
536+
return status;
537+
538+
spin_lock_irqsave(&hidg->write_spinlock, flags);
539+
540+
if (!hidg->req) {
541+
spin_unlock_irqrestore(&hidg->write_spinlock, flags);
542+
return -ESHUTDOWN;
543+
}
544+
545+
#define WRITE_COND (!hidg->write_pending)
546+
try_again:
547+
/* write queue */
548+
while (!WRITE_COND) {
549+
spin_unlock_irqrestore(&hidg->write_spinlock, flags);
550+
if (nonblock & O_NONBLOCK)
551+
return -EAGAIN;
552+
553+
if (wait_event_interruptible_exclusive(hidg->write_queue, WRITE_COND))
554+
return -ERESTARTSYS;
555+
556+
spin_lock_irqsave(&hidg->write_spinlock, flags);
557+
}
558+
559+
hidg->write_pending = 1;
560+
req = hidg->req;
561+
count = min_t(unsigned int, count, hidg->report_length);
562+
563+
spin_unlock_irqrestore(&hidg->write_spinlock, flags);
564+
565+
if (!req) {
566+
ERROR(hidg->func.config->cdev, "hidg->req is NULL\n");
567+
status = -ESHUTDOWN;
568+
goto release_write_pending;
569+
}
570+
571+
memcpy(req->buf, buffer, count);
572+
573+
spin_lock_irqsave(&hidg->write_spinlock, flags);
574+
575+
/* when our function has been disabled by host */
576+
if (!hidg->req) {
577+
free_ep_req(hidg->in_ep, req);
578+
/*
579+
* TODO
580+
* Should we fail with error here?
581+
*/
582+
goto try_again;
583+
}
584+
585+
req->status = 0;
586+
req->zero = 0;
587+
req->length = count;
588+
req->complete = f_hidg_req_complete;
589+
req->context = hidg;
590+
591+
spin_unlock_irqrestore(&hidg->write_spinlock, flags);
592+
593+
if (!hidg->in_ep->enabled) {
594+
ERROR(hidg->func.config->cdev, "in_ep is disabled\n");
595+
status = -ESHUTDOWN;
596+
goto release_write_pending;
597+
}
598+
599+
status = usb_ep_queue(hidg->in_ep, req, GFP_ATOMIC);
600+
if (status < 0)
601+
goto release_write_pending;
602+
else
603+
status = count;
604+
605+
return status;
606+
release_write_pending:
607+
spin_lock_irqsave(&hidg->write_spinlock, flags);
608+
hidg->write_pending = 0;
609+
spin_unlock_irqrestore(&hidg->write_spinlock, flags);
610+
611+
wake_up(&hidg->write_queue);
612+
613+
return status;
614+
}
615+
EXPORT_SYMBOL(f_hidg_internal_write);
616+
#endif
617+
523618
static __poll_t f_hidg_poll(struct file *file, poll_table *wait)
524619
{
525620
struct f_hidg *hidg = file->private_data;
@@ -1010,6 +1105,10 @@ static int hidg_bind(struct usb_configuration *c, struct usb_function *f)
10101105
if (status)
10111106
goto fail_free_descs;
10121107

1108+
#ifdef CONFIG_AMLOGIC_BRIDGE_HID
1109+
hid_h = hidg;
1110+
#endif
1111+
10131112
return 0;
10141113
fail_free_descs:
10151114
usb_free_all_descriptors(f);
@@ -1251,6 +1350,10 @@ static void hidg_unbind(struct usb_configuration *c, struct usb_function *f)
12511350
{
12521351
struct f_hidg *hidg = func_to_hidg(f);
12531352

1353+
#ifdef CONFIG_AMLOGIC_BRIDGE_HID
1354+
hid_h = NULL;
1355+
#endif
1356+
12541357
cdev_device_del(&hidg->cdev, &hidg->dev);
12551358

12561359
usb_free_all_descriptors(f);

drivers/usb/gadget/function/f_uac2.c

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,9 @@
1313
#include <linux/usb/audio.h>
1414
#include <linux/usb/audio-v2.h>
1515
#include <linux/module.h>
16+
#ifdef CONFIG_AMLOGIC_BRIDGE_UAC
17+
#include <linux/amlogic/bridge_uac_ext.h>
18+
#endif
1619

1720
#include "u_audio.h"
1821
#include "u_uac2.h"
@@ -967,6 +970,17 @@ afunc_bind(struct usb_configuration *cfg, struct usb_function *fn)
967970
struct usb_string *us;
968971
int ret;
969972

973+
#ifdef CONFIG_AMLOGIC_BRIDGE_UAC
974+
if (bridge_uac_f.setup_capture && bridge_uac_f.get_capture_status) {
975+
bridge_uac_f.get_capture_hw(&uac2_opts->c_chmask,
976+
&uac2_opts->c_srate, &uac2_opts->c_ssize);
977+
}
978+
979+
if (bridge_uac_f.setup_playback && bridge_uac_f.get_playback_status)
980+
bridge_uac_f.get_playback_hw(&uac2_opts->p_chmask,
981+
&uac2_opts->p_srate, &uac2_opts->p_ssize);
982+
#endif
983+
970984
ret = afunc_validate_opts(agdev, dev);
971985
if (ret)
972986
return ret;

drivers/usb/gadget/function/u_audio.c

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,9 @@
1717
#include <sound/core.h>
1818
#include <sound/pcm.h>
1919
#include <sound/pcm_params.h>
20+
#ifdef CONFIG_AMLOGIC_BRIDGE_UAC
21+
#include <linux/amlogic/bridge_uac_ext.h>
22+
#endif
2023
#include <sound/control.h>
2124
#include <sound/tlv.h>
2225
#include <linux/usb/audio.h>
@@ -27,6 +30,16 @@
2730
#define PRD_SIZE_MAX PAGE_SIZE
2831
#define MIN_PERIODS 4
2932

33+
#ifdef CONFIG_AMLOGIC_BRIDGE_UAC
34+
struct bridge_uac_function bridge_uac_f = {0};
35+
36+
void *get_uac_function_p(void)
37+
{
38+
return &bridge_uac_f;
39+
}
40+
EXPORT_SYMBOL(get_uac_function_p);
41+
#endif
42+
3043
enum {
3144
UAC_FBACK_CTRL,
3245
UAC_MUTE_CTRL,
@@ -171,6 +184,41 @@ static void u_audio_iso_complete(struct usb_ep *ep, struct usb_request *req)
171184
pr_debug("%s: iso_complete status(%d) %d/%d\n",
172185
__func__, status, req->actual, req->length);
173186

187+
#ifdef CONFIG_AMLOGIC_BRIDGE_UAC
188+
if (prm == &uac->p_prm) {
189+
if (bridge_uac_f.setup_playback && bridge_uac_f.get_playback_status()) {
190+
/*
191+
* For each IN packet, take the quotient of the current data
192+
* rate and the endpoint's interval as the base packet size.
193+
* If there is a residue from this division, add it to the
194+
* residue accumulator.
195+
*/
196+
req->length = uac->p_pktsize;
197+
uac->p_residue += uac->p_pktsize_residue;
198+
199+
/*
200+
* Whenever there are more bytes in the accumulator than we
201+
* need to add one more sample frame, increase this packet's
202+
* size and decrease the accumulator.
203+
*/
204+
if (uac->p_residue / uac->p_interval >= uac->p_framesize) {
205+
req->length += uac->p_framesize;
206+
uac->p_residue -= uac->p_framesize *
207+
uac->p_interval;
208+
}
209+
210+
req->actual = req->length;
211+
if (req->actual)
212+
bridge_uac_f.read_data(req->buf, req->actual);
213+
}
214+
} else {
215+
if (bridge_uac_f.setup_capture && bridge_uac_f.get_capture_status()) {
216+
if (req->actual)
217+
bridge_uac_f.write_data(req->buf, req->actual);
218+
}
219+
}
220+
#endif
221+
174222
substream = prm->ss;
175223

176224
/* Do nothing if ALSA isn't active */
@@ -540,6 +588,10 @@ int u_audio_start_capture(struct g_audio *audio_dev)
540588
if (usb_ep_queue(ep_fback, req_fback, GFP_ATOMIC))
541589
dev_err(dev, "%s:%d Error!\n", __func__, __LINE__);
542590

591+
#ifdef CONFIG_AMLOGIC_BRIDGE_UAC
592+
if (bridge_uac_f.setup_capture && bridge_uac_f.get_capture_status())
593+
bridge_uac_f.start_capture();
594+
#endif
543595
return 0;
544596
}
545597
EXPORT_SYMBOL_GPL(u_audio_start_capture);
@@ -550,6 +602,10 @@ void u_audio_stop_capture(struct g_audio *audio_dev)
550602

551603
if (audio_dev->in_ep_fback)
552604
free_ep_fback(&uac->c_prm, audio_dev->in_ep_fback);
605+
#ifdef CONFIG_AMLOGIC_BRIDGE_UAC
606+
if (bridge_uac_f.setup_capture && bridge_uac_f.get_capture_status())
607+
bridge_uac_f.stop_capture();
608+
#endif
553609
free_ep(&uac->c_prm, audio_dev->out_ep);
554610
}
555611
EXPORT_SYMBOL_GPL(u_audio_stop_capture);
@@ -619,6 +675,11 @@ int u_audio_start_playback(struct g_audio *audio_dev)
619675
dev_err(dev, "%s:%d Error!\n", __func__, __LINE__);
620676
}
621677

678+
#ifdef CONFIG_AMLOGIC_BRIDGE_UAC
679+
if (bridge_uac_f.setup_playback && bridge_uac_f.get_playback_status())
680+
bridge_uac_f.start_playback();
681+
#endif
682+
622683
return 0;
623684
}
624685
EXPORT_SYMBOL_GPL(u_audio_start_playback);
@@ -627,6 +688,11 @@ void u_audio_stop_playback(struct g_audio *audio_dev)
627688
{
628689
struct snd_uac_chip *uac = audio_dev->uac;
629690

691+
#ifdef CONFIG_AMLOGIC_BRIDGE_UAC
692+
if (bridge_uac_f.setup_playback && bridge_uac_f.get_playback_status())
693+
bridge_uac_f.stop_playback();
694+
#endif
695+
630696
free_ep(&uac->p_prm, audio_dev->in_ep);
631697
}
632698
EXPORT_SYMBOL_GPL(u_audio_stop_playback);
@@ -666,6 +732,12 @@ int u_audio_set_volume(struct g_audio *audio_dev, int playback, s16 val)
666732
val = clamp(val, prm->volume_min, prm->volume_max);
667733
if (prm->volume != val) {
668734
prm->volume = val;
735+
#ifdef CONFIG_AMLOGIC_BRIDGE_UAC
736+
if (bridge_uac_f.setup_playback && playback)
737+
bridge_uac_f.ctl_playback(0, prm->volume);
738+
else if (bridge_uac_f.setup_capture && !playback)
739+
bridge_uac_f.ctl_capture(0, prm->volume);
740+
#endif
669741
change = 1;
670742
}
671743
spin_unlock_irqrestore(&prm->lock, flags);
@@ -716,6 +788,12 @@ int u_audio_set_mute(struct g_audio *audio_dev, int playback, int val)
716788
if (prm->mute != mute) {
717789
prm->mute = mute;
718790
change = 1;
791+
#ifdef CONFIG_AMLOGIC_BRIDGE_UAC
792+
if (bridge_uac_f.setup_playback && playback)
793+
bridge_uac_f.ctl_playback(0, prm->mute);
794+
else if (bridge_uac_f.setup_capture && !playback)
795+
bridge_uac_f.ctl_capture(0, prm->mute);
796+
#endif
719797
}
720798
spin_unlock_irqrestore(&prm->lock, flags);
721799

@@ -1135,6 +1213,16 @@ int g_audio_setup(struct g_audio *g_audio, const char *pcm_name,
11351213
prm->volume_max = fu->volume_max;
11361214
prm->volume_min = fu->volume_min;
11371215
prm->volume_res = fu->volume_res;
1216+
1217+
#ifdef CONFIG_AMLOGIC_BRIDGE_UAC
1218+
if (i == SNDRV_PCM_STREAM_CAPTURE && bridge_uac_f.setup_capture) {
1219+
prm->volume = bridge_uac_f.get_default_volume_capture();
1220+
bridge_uac_f.ctl_capture(0, prm->volume);
1221+
} else if (i == SNDRV_PCM_STREAM_PLAYBACK && bridge_uac_f.setup_playback) {
1222+
prm->volume = bridge_uac_f.get_default_volume_playback();
1223+
bridge_uac_f.ctl_playback(0, prm->volume);
1224+
}
1225+
#endif
11381226
}
11391227
}
11401228

include/linux/usb/g_hid.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,4 +30,7 @@ struct hidg_func_descriptor {
3030
unsigned char report_desc[];
3131
};
3232

33+
#ifdef CONFIG_AMLOGIC_BRIDGE_HID
34+
ssize_t f_hidg_internal_write(char *buffer, size_t count, int nonblock);
35+
#endif
3336
#endif /* __LINUX_USB_G_HID_H */

0 commit comments

Comments
 (0)