Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

usb: gadget: u_audio: Support multiple sampling rates

Implement support for multiple sampling rates in u_audio part of the
audio gadget. The currently configured rates are exposed through
read-only amixer controls 'Capture Rate' and 'Playback Rate'.

Signed-off-by: Julian Scheel <julian@jusst.de>
Signed-off-by: Pavel Hofman <pavel.hofman@ivitera.com>
Link: https://lore.kernel.org/r/20220121155308.48794-3-pavel.hofman@ivitera.com
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

authored by

Julian Scheel and committed by
Greg Kroah-Hartman
c565ad07 ce6a7bfb

+152 -2
+2
drivers/usb/gadget/function/f_uac1.c
··· 1298 1298 audio->in_ep_maxpsize = le16_to_cpu(as_in_ep_desc.wMaxPacketSize); 1299 1299 audio->params.c_chmask = audio_opts->c_chmask; 1300 1300 audio->params.c_srate = audio_opts->c_srate; 1301 + audio->params.c_srates[0] = audio_opts->c_srate; 1301 1302 audio->params.c_ssize = audio_opts->c_ssize; 1302 1303 if (FUIN_EN(audio_opts)) { 1303 1304 audio->params.p_fu.id = USB_IN_FU_ID; ··· 1311 1310 } 1312 1311 audio->params.p_chmask = audio_opts->p_chmask; 1313 1312 audio->params.p_srate = audio_opts->p_srate; 1313 + audio->params.p_srates[0] = audio_opts->p_srate; 1314 1314 audio->params.p_ssize = audio_opts->p_ssize; 1315 1315 if (FUOUT_EN(audio_opts)) { 1316 1316 audio->params.c_fu.id = USB_OUT_FU_ID;
+2
drivers/usb/gadget/function/f_uac2.c
··· 1210 1210 1211 1211 agdev->params.p_chmask = uac2_opts->p_chmask; 1212 1212 agdev->params.p_srate = uac2_opts->p_srate; 1213 + agdev->params.p_srates[0] = uac2_opts->p_srate; 1213 1214 agdev->params.p_ssize = uac2_opts->p_ssize; 1214 1215 if (FUIN_EN(uac2_opts)) { 1215 1216 agdev->params.p_fu.id = USB_IN_FU_ID; ··· 1222 1221 } 1223 1222 agdev->params.c_chmask = uac2_opts->c_chmask; 1224 1223 agdev->params.c_srate = uac2_opts->c_srate; 1224 + agdev->params.c_srates[0] = uac2_opts->c_srate; 1225 1225 agdev->params.c_ssize = uac2_opts->c_ssize; 1226 1226 if (FUOUT_EN(uac2_opts)) { 1227 1227 agdev->params.c_fu.id = USB_OUT_FU_ID;
+131
drivers/usb/gadget/function/u_audio.c
··· 32 32 UAC_P_PITCH_CTRL, 33 33 UAC_MUTE_CTRL, 34 34 UAC_VOLUME_CTRL, 35 + UAC_RATE_CTRL, 35 36 }; 36 37 37 38 /* Runtime data params for one stream */ ··· 62 61 s16 volume_min, volume_max, volume_res; 63 62 s16 volume; 64 63 int mute; 64 + 65 + struct snd_kcontrol *snd_kctl_rate; /* read-only current rate */ 65 66 66 67 spinlock_t lock; /* lock for control transfers */ 67 68 ··· 496 493 dev_err(uac->card->dev, "%s:%d Error!\n", __func__, __LINE__); 497 494 } 498 495 496 + int u_audio_set_capture_srate(struct g_audio *audio_dev, int srate) 497 + { 498 + struct uac_params *params = &audio_dev->params; 499 + int i; 500 + 501 + dev_dbg(&audio_dev->gadget->dev, "%s: srate %d\n", __func__, srate); 502 + for (i = 0; i < UAC_MAX_RATES; i++) { 503 + if (params->c_srates[i] == srate) { 504 + params->c_srate = srate; 505 + return 0; 506 + } 507 + if (params->c_srates[i] == 0) 508 + break; 509 + } 510 + 511 + return -EINVAL; 512 + } 513 + EXPORT_SYMBOL_GPL(u_audio_set_capture_srate); 514 + 515 + int u_audio_set_playback_srate(struct g_audio *audio_dev, int srate) 516 + { 517 + struct uac_params *params = &audio_dev->params; 518 + int i; 519 + 520 + dev_dbg(&audio_dev->gadget->dev, "%s: srate %d\n", __func__, srate); 521 + for (i = 0; i < UAC_MAX_RATES; i++) { 522 + if (params->p_srates[i] == srate) { 523 + params->p_srate = srate; 524 + return 0; 525 + } 526 + if (params->p_srates[i] == 0) 527 + break; 528 + } 529 + 530 + return -EINVAL; 531 + } 532 + EXPORT_SYMBOL_GPL(u_audio_set_playback_srate); 533 + 499 534 int u_audio_start_capture(struct g_audio *audio_dev) 500 535 { 501 536 struct snd_uac_chip *uac = audio_dev->uac; ··· 545 504 struct uac_params *params = &audio_dev->params; 546 505 int req_len, i; 547 506 507 + dev_dbg(dev, "start capture with rate %d\n", params->c_srate); 548 508 ep = audio_dev->out_ep; 549 509 prm = &uac->c_prm; 550 510 config_ep_by_speed(gadget, &audio_dev->func, ep); ··· 638 596 int req_len, i; 639 597 unsigned int p_pktsize; 640 598 599 + dev_dbg(dev, "start playback with rate %d\n", params->p_srate); 641 600 ep = audio_dev->in_ep; 642 601 prm = &uac->p_prm; 643 602 config_ep_by_speed(gadget, &audio_dev->func, ep); ··· 986 943 return change; 987 944 } 988 945 946 + static int get_max_srate(const int *srates) 947 + { 948 + int i, max_srate = 0; 949 + 950 + for (i = 0; i < UAC_MAX_RATES; i++) { 951 + if (srates[i] == 0) 952 + break; 953 + if (srates[i] > max_srate) 954 + max_srate = srates[i]; 955 + } 956 + return max_srate; 957 + } 958 + 959 + static int get_min_srate(const int *srates) 960 + { 961 + int i, min_srate = INT_MAX; 962 + 963 + for (i = 0; i < UAC_MAX_RATES; i++) { 964 + if (srates[i] == 0) 965 + break; 966 + if (srates[i] < min_srate) 967 + min_srate = srates[i]; 968 + } 969 + return min_srate; 970 + } 971 + 972 + static int u_audio_rate_info(struct snd_kcontrol *kcontrol, 973 + struct snd_ctl_elem_info *uinfo) 974 + { 975 + const int *srates; 976 + struct uac_rtd_params *prm = snd_kcontrol_chip(kcontrol); 977 + struct snd_uac_chip *uac = prm->uac; 978 + struct g_audio *audio_dev = uac->audio_dev; 979 + struct uac_params *params = &audio_dev->params; 980 + 981 + uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; 982 + uinfo->count = 1; 983 + 984 + if (prm == &uac->c_prm) 985 + srates = params->c_srates; 986 + else 987 + srates = params->p_srates; 988 + uinfo->value.integer.min = get_min_srate(srates); 989 + uinfo->value.integer.max = get_max_srate(srates); 990 + return 0; 991 + } 992 + 993 + static int u_audio_rate_get(struct snd_kcontrol *kcontrol, 994 + struct snd_ctl_elem_value *ucontrol) 995 + { 996 + struct uac_rtd_params *prm = snd_kcontrol_chip(kcontrol); 997 + struct snd_uac_chip *uac = prm->uac; 998 + struct g_audio *audio_dev = uac->audio_dev; 999 + struct uac_params *params = &audio_dev->params; 1000 + 1001 + if (prm == &uac->c_prm) 1002 + ucontrol->value.integer.value[0] = params->c_srate; 1003 + else 1004 + ucontrol->value.integer.value[0] = params->p_srate; 1005 + 1006 + return 0; 1007 + } 989 1008 990 1009 static struct snd_kcontrol_new u_audio_controls[] = { 991 1010 [UAC_FBACK_CTRL] { ··· 1077 972 .info = u_audio_volume_info, 1078 973 .get = u_audio_volume_get, 1079 974 .put = u_audio_volume_put, 975 + }, 976 + [UAC_RATE_CTRL] { 977 + .iface = SNDRV_CTL_ELEM_IFACE_PCM, 978 + .name = "", /* will be filled later */ 979 + .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE, 980 + .info = u_audio_rate_info, 981 + .get = u_audio_rate_get, 1080 982 }, 1081 983 }; 1082 984 ··· 1298 1186 prm->volume_min = fu->volume_min; 1299 1187 prm->volume_res = fu->volume_res; 1300 1188 } 1189 + 1190 + /* Add rate control */ 1191 + snprintf(ctrl_name, sizeof(ctrl_name), 1192 + "%s Rate", direction); 1193 + u_audio_controls[UAC_RATE_CTRL].name = ctrl_name; 1194 + 1195 + kctl = snd_ctl_new1(&u_audio_controls[UAC_RATE_CTRL], prm); 1196 + if (!kctl) { 1197 + err = -ENOMEM; 1198 + goto snd_fail; 1199 + } 1200 + 1201 + kctl->id.device = pcm->device; 1202 + kctl->id.subdevice = 0; 1203 + 1204 + err = snd_ctl_add(card, kctl); 1205 + if (err < 0) 1206 + goto snd_fail; 1207 + prm->snd_kctl_rate = kctl; 1301 1208 } 1302 1209 1303 1210 strscpy(card->driver, card_name, sizeof(card->driver));
+8 -2
drivers/usb/gadget/function/u_audio.h
··· 10 10 #define __U_AUDIO_H 11 11 12 12 #include <linux/usb/composite.h> 13 + #include "uac_common.h" 13 14 14 15 /* 15 16 * Same maximum frequency deviation on the slower side as in ··· 41 40 struct uac_params { 42 41 /* playback */ 43 42 int p_chmask; /* channel mask */ 44 - int p_srate; /* rate in Hz */ 43 + int p_srates[UAC_MAX_RATES]; /* available rates in Hz (0 terminated list) */ 44 + int p_srate; /* selected rate in Hz */ 45 45 int p_ssize; /* sample size */ 46 46 struct uac_fu_params p_fu; /* Feature Unit parameters */ 47 47 48 48 /* capture */ 49 49 int c_chmask; /* channel mask */ 50 - int c_srate; /* rate in Hz */ 50 + int c_srates[UAC_MAX_RATES]; /* available rates in Hz (0 terminated list) */ 51 + int c_srate; /* selected rate in Hz */ 51 52 int c_ssize; /* sample size */ 52 53 struct uac_fu_params c_fu; /* Feature Unit parameters */ 53 54 ··· 119 116 void u_audio_stop_capture(struct g_audio *g_audio); 120 117 int u_audio_start_playback(struct g_audio *g_audio); 121 118 void u_audio_stop_playback(struct g_audio *g_audio); 119 + 120 + int u_audio_set_capture_srate(struct g_audio *audio_dev, int srate); 121 + int u_audio_set_playback_srate(struct g_audio *audio_dev, int srate); 122 122 123 123 int u_audio_get_volume(struct g_audio *g_audio, int playback, s16 *val); 124 124 int u_audio_set_volume(struct g_audio *g_audio, int playback, s16 val);
+9
drivers/usb/gadget/function/uac_common.h
··· 1 + /* SPDX-License-Identifier: GPL-2.0+ */ 2 + /* 3 + */ 4 + 5 + #ifndef UAC_COMMON_H 6 + #define UAC_COMMON_H 7 + 8 + #define UAC_MAX_RATES 10 /* maximum number of rates configurable by f_uac1/2 */ 9 + #endif