Merge "sound: usb: Map interface context information to interface number"
This commit is contained in:
commit
b3a739e9c7
1 changed files with 62 additions and 32 deletions
|
@ -69,6 +69,7 @@ struct intf_info {
|
||||||
size_t xfer_buf_size;
|
size_t xfer_buf_size;
|
||||||
phys_addr_t xfer_buf_pa;
|
phys_addr_t xfer_buf_pa;
|
||||||
u8 *xfer_buf;
|
u8 *xfer_buf;
|
||||||
|
u8 intf_num;
|
||||||
u8 pcm_card_num;
|
u8 pcm_card_num;
|
||||||
u8 pcm_dev_num;
|
u8 pcm_dev_num;
|
||||||
u8 direction;
|
u8 direction;
|
||||||
|
@ -391,10 +392,9 @@ static void uaudio_iommu_unmap(enum mem_type mtype, unsigned long va,
|
||||||
}
|
}
|
||||||
|
|
||||||
static int prepare_qmi_response(struct snd_usb_substream *subs,
|
static int prepare_qmi_response(struct snd_usb_substream *subs,
|
||||||
struct qmi_uaudio_stream_resp_msg_v01 *resp, u32 xfer_buf_len,
|
struct qmi_uaudio_stream_req_msg_v01 *req_msg,
|
||||||
int card_num, int pcm_dev_num)
|
struct qmi_uaudio_stream_resp_msg_v01 *resp, int info_idx)
|
||||||
{
|
{
|
||||||
int ret = -ENODEV;
|
|
||||||
struct usb_interface *iface;
|
struct usb_interface *iface;
|
||||||
struct usb_host_interface *alts;
|
struct usb_host_interface *alts;
|
||||||
struct usb_interface_descriptor *altsd;
|
struct usb_interface_descriptor *altsd;
|
||||||
|
@ -403,10 +403,11 @@ static int prepare_qmi_response(struct snd_usb_substream *subs,
|
||||||
struct uac_format_type_i_discrete_descriptor *fmt_v1;
|
struct uac_format_type_i_discrete_descriptor *fmt_v1;
|
||||||
struct uac_format_type_i_ext_descriptor *fmt_v2;
|
struct uac_format_type_i_ext_descriptor *fmt_v2;
|
||||||
struct uac1_as_header_descriptor *as;
|
struct uac1_as_header_descriptor *as;
|
||||||
int protocol;
|
int ret = -ENODEV;
|
||||||
|
int protocol, card_num, pcm_dev_num;
|
||||||
void *hdr_ptr;
|
void *hdr_ptr;
|
||||||
u8 *xfer_buf;
|
u8 *xfer_buf;
|
||||||
u32 len, mult, remainder;
|
u32 len, mult, remainder, xfer_buf_len;
|
||||||
unsigned long va, tr_data_va = 0, tr_sync_va = 0, dcba_va = 0,
|
unsigned long va, tr_data_va = 0, tr_sync_va = 0, dcba_va = 0,
|
||||||
xfer_buf_va = 0;
|
xfer_buf_va = 0;
|
||||||
phys_addr_t xhci_pa, xfer_buf_pa;
|
phys_addr_t xhci_pa, xfer_buf_pa;
|
||||||
|
@ -418,13 +419,9 @@ static int prepare_qmi_response(struct snd_usb_substream *subs,
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (uadev[card_num].info &&
|
pcm_dev_num = (req_msg->usb_token & SND_PCM_DEV_NUM_MASK) >> 8;
|
||||||
uadev[card_num].info[subs->interface].in_use) {
|
card_num = (req_msg->usb_token & SND_PCM_CARD_NUM_MASK) >> 16;
|
||||||
pr_err("%s interface# %d already in use card# %d\n", __func__,
|
xfer_buf_len = req_msg->xfer_buff_size;
|
||||||
subs->interface, card_num);
|
|
||||||
ret = -EBUSY;
|
|
||||||
goto err;
|
|
||||||
}
|
|
||||||
|
|
||||||
alts = &iface->altsetting[subs->altset_idx];
|
alts = &iface->altsetting[subs->altset_idx];
|
||||||
altsd = get_iface_desc(alts);
|
altsd = get_iface_desc(alts);
|
||||||
|
@ -655,18 +652,19 @@ skip_sync:
|
||||||
uadev[card_num].card_num = card_num;
|
uadev[card_num].card_num = card_num;
|
||||||
|
|
||||||
/* cache intf specific info to use it for unmap and free xfer buf */
|
/* cache intf specific info to use it for unmap and free xfer buf */
|
||||||
uadev[card_num].info[subs->interface].data_xfer_ring_va = tr_data_va;
|
uadev[card_num].info[info_idx].data_xfer_ring_va = tr_data_va;
|
||||||
uadev[card_num].info[subs->interface].data_xfer_ring_size = PAGE_SIZE;
|
uadev[card_num].info[info_idx].data_xfer_ring_size = PAGE_SIZE;
|
||||||
uadev[card_num].info[subs->interface].sync_xfer_ring_va = tr_sync_va;
|
uadev[card_num].info[info_idx].sync_xfer_ring_va = tr_sync_va;
|
||||||
uadev[card_num].info[subs->interface].sync_xfer_ring_size = PAGE_SIZE;
|
uadev[card_num].info[info_idx].sync_xfer_ring_size = PAGE_SIZE;
|
||||||
uadev[card_num].info[subs->interface].xfer_buf_va = xfer_buf_va;
|
uadev[card_num].info[info_idx].xfer_buf_va = xfer_buf_va;
|
||||||
uadev[card_num].info[subs->interface].xfer_buf_pa = xfer_buf_pa;
|
uadev[card_num].info[info_idx].xfer_buf_pa = xfer_buf_pa;
|
||||||
uadev[card_num].info[subs->interface].xfer_buf_size = len;
|
uadev[card_num].info[info_idx].xfer_buf_size = len;
|
||||||
uadev[card_num].info[subs->interface].xfer_buf = xfer_buf;
|
uadev[card_num].info[info_idx].xfer_buf = xfer_buf;
|
||||||
uadev[card_num].info[subs->interface].pcm_card_num = card_num;
|
uadev[card_num].info[info_idx].pcm_card_num = card_num;
|
||||||
uadev[card_num].info[subs->interface].pcm_dev_num = pcm_dev_num;
|
uadev[card_num].info[info_idx].pcm_dev_num = pcm_dev_num;
|
||||||
uadev[card_num].info[subs->interface].direction = subs->direction;
|
uadev[card_num].info[info_idx].direction = subs->direction;
|
||||||
uadev[card_num].info[subs->interface].in_use = true;
|
uadev[card_num].info[info_idx].intf_num = subs->interface;
|
||||||
|
uadev[card_num].info[info_idx].in_use = true;
|
||||||
|
|
||||||
set_bit(card_num, &uaudio_qdev->card_slot);
|
set_bit(card_num, &uaudio_qdev->card_slot);
|
||||||
|
|
||||||
|
@ -723,7 +721,7 @@ static void uaudio_dev_cleanup(struct uaudio_dev *dev)
|
||||||
continue;
|
continue;
|
||||||
uaudio_dev_intf_cleanup(dev->udev, &dev->info[if_idx]);
|
uaudio_dev_intf_cleanup(dev->udev, &dev->info[if_idx]);
|
||||||
pr_debug("%s: release resources: intf# %d card# %d\n", __func__,
|
pr_debug("%s: release resources: intf# %d card# %d\n", __func__,
|
||||||
if_idx, dev->card_num);
|
dev->info[if_idx].intf_num, dev->card_num);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* iommu_unmap dcba iova for a usb device */
|
/* iommu_unmap dcba iova for a usb device */
|
||||||
|
@ -867,6 +865,28 @@ static int map_pcm_format(unsigned int fmt_received)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int info_idx_from_ifnum(int card_num, int intf_num, bool enable)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* default index 0 is used when info is allocated upon
|
||||||
|
* first enable audio stream req for a pcm device
|
||||||
|
*/
|
||||||
|
if (enable && !uadev[card_num].info)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
for (i = 0; i < uadev[card_num].num_intf; i++) {
|
||||||
|
if (enable && !uadev[card_num].info[i].in_use)
|
||||||
|
return i;
|
||||||
|
else if (!enable &&
|
||||||
|
uadev[card_num].info[i].intf_num == intf_num)
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
static int handle_uaudio_stream_req(void *req_h, void *req)
|
static int handle_uaudio_stream_req(void *req_h, void *req)
|
||||||
{
|
{
|
||||||
struct qmi_uaudio_stream_req_msg_v01 *req_msg;
|
struct qmi_uaudio_stream_req_msg_v01 *req_msg;
|
||||||
|
@ -877,7 +897,7 @@ static int handle_uaudio_stream_req(void *req_h, void *req)
|
||||||
struct intf_info *info;
|
struct intf_info *info;
|
||||||
int pcm_format;
|
int pcm_format;
|
||||||
u8 pcm_card_num, pcm_dev_num, direction;
|
u8 pcm_card_num, pcm_dev_num, direction;
|
||||||
int intf_num = -1, ret = 0;
|
int info_idx = -EINVAL, ret = 0;
|
||||||
|
|
||||||
req_msg = (struct qmi_uaudio_stream_req_msg_v01 *)req;
|
req_msg = (struct qmi_uaudio_stream_req_msg_v01 *)req;
|
||||||
|
|
||||||
|
@ -921,7 +941,8 @@ static int handle_uaudio_stream_req(void *req_h, void *req)
|
||||||
}
|
}
|
||||||
|
|
||||||
mutex_lock(&chip->dev_lock);
|
mutex_lock(&chip->dev_lock);
|
||||||
intf_num = subs->interface;
|
info_idx = info_idx_from_ifnum(pcm_card_num, subs->interface,
|
||||||
|
req_msg->enable);
|
||||||
if (atomic_read(&chip->shutdown) || !subs->stream || !subs->stream->pcm
|
if (atomic_read(&chip->shutdown) || !subs->stream || !subs->stream->pcm
|
||||||
|| !subs->stream->chip) {
|
|| !subs->stream->chip) {
|
||||||
ret = -ENODEV;
|
ret = -ENODEV;
|
||||||
|
@ -929,6 +950,16 @@ static int handle_uaudio_stream_req(void *req_h, void *req)
|
||||||
goto response;
|
goto response;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (req_msg->enable) {
|
||||||
|
if (info_idx < 0) {
|
||||||
|
pr_err("%s interface# %d already in use card# %d\n",
|
||||||
|
__func__, subs->interface, pcm_card_num);
|
||||||
|
ret = -EBUSY;
|
||||||
|
mutex_unlock(&chip->dev_lock);
|
||||||
|
goto response;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
subs->pcm_format = pcm_format;
|
subs->pcm_format = pcm_format;
|
||||||
subs->channels = req_msg->number_of_ch;
|
subs->channels = req_msg->number_of_ch;
|
||||||
subs->cur_rate = req_msg->bit_rate;
|
subs->cur_rate = req_msg->bit_rate;
|
||||||
|
@ -937,19 +968,18 @@ static int handle_uaudio_stream_req(void *req_h, void *req)
|
||||||
ret = snd_usb_enable_audio_stream(subs, req_msg->enable);
|
ret = snd_usb_enable_audio_stream(subs, req_msg->enable);
|
||||||
|
|
||||||
if (!ret && req_msg->enable)
|
if (!ret && req_msg->enable)
|
||||||
ret = prepare_qmi_response(subs, &resp, req_msg->xfer_buff_size,
|
ret = prepare_qmi_response(subs, req_msg, &resp, info_idx);
|
||||||
pcm_card_num, pcm_dev_num);
|
|
||||||
|
|
||||||
mutex_unlock(&chip->dev_lock);
|
mutex_unlock(&chip->dev_lock);
|
||||||
|
|
||||||
response:
|
response:
|
||||||
if (!req_msg->enable && ret != -EINVAL) {
|
if (!req_msg->enable && ret != -EINVAL) {
|
||||||
if (intf_num >= 0) {
|
if (info_idx >= 0) {
|
||||||
mutex_lock(&chip->dev_lock);
|
mutex_lock(&chip->dev_lock);
|
||||||
info = &uadev[pcm_card_num].info[intf_num];
|
info = &uadev[pcm_card_num].info[info_idx];
|
||||||
uaudio_dev_intf_cleanup(uadev[pcm_card_num].udev, info);
|
uaudio_dev_intf_cleanup(uadev[pcm_card_num].udev, info);
|
||||||
pr_debug("%s:release resources: intf# %d card# %d\n",
|
pr_debug("%s:release resources: intf# %d card# %d\n",
|
||||||
__func__, intf_num, pcm_card_num);
|
__func__, subs->interface, pcm_card_num);
|
||||||
mutex_unlock(&chip->dev_lock);
|
mutex_unlock(&chip->dev_lock);
|
||||||
}
|
}
|
||||||
if (atomic_read(&uadev[pcm_card_num].in_use))
|
if (atomic_read(&uadev[pcm_card_num].in_use))
|
||||||
|
|
Loading…
Add table
Reference in a new issue