Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit fb3c166a authored by Kyle Yan's avatar Kyle Yan Committed by Gerrit - the friendly Code Review server
Browse files

Merge "sound: usb: Map interface context information to interface number" into msm-4.9

parents 85312fcd ebbe626c
Loading
Loading
Loading
Loading
+62 −32
Original line number Diff line number Diff line
@@ -68,6 +68,7 @@ struct intf_info {
	size_t xfer_buf_size;
	phys_addr_t xfer_buf_pa;
	u8 *xfer_buf;
	u8 intf_num;
	u8 pcm_card_num;
	u8 pcm_dev_num;
	u8 direction;
@@ -390,10 +391,9 @@ static void uaudio_iommu_unmap(enum mem_type mtype, unsigned long va,
}

static int prepare_qmi_response(struct snd_usb_substream *subs,
		struct qmi_uaudio_stream_resp_msg_v01 *resp, u32 xfer_buf_len,
		int card_num, int pcm_dev_num)
		struct qmi_uaudio_stream_req_msg_v01 *req_msg,
		struct qmi_uaudio_stream_resp_msg_v01 *resp, int info_idx)
{
	int ret = -ENODEV;
	struct usb_interface *iface;
	struct usb_host_interface *alts;
	struct usb_interface_descriptor *altsd;
@@ -402,10 +402,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_ext_descriptor *fmt_v2;
	struct uac1_as_header_descriptor *as;
	int protocol;
	int ret = -ENODEV;
	int protocol, card_num, pcm_dev_num;
	void *hdr_ptr;
	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,
	xfer_buf_va = 0;
	phys_addr_t xhci_pa, xfer_buf_pa;
@@ -417,13 +418,9 @@ static int prepare_qmi_response(struct snd_usb_substream *subs,
		goto err;
	}

	if (uadev[card_num].info &&
			uadev[card_num].info[subs->interface].in_use) {
		pr_err("%s interface# %d already in use card# %d\n", __func__,
			subs->interface, card_num);
		ret = -EBUSY;
		goto err;
	}
	pcm_dev_num = (req_msg->usb_token & SND_PCM_DEV_NUM_MASK) >> 8;
	card_num = (req_msg->usb_token & SND_PCM_CARD_NUM_MASK) >> 16;
	xfer_buf_len = req_msg->xfer_buff_size;

	alts = &iface->altsetting[subs->altset_idx];
	altsd = get_iface_desc(alts);
@@ -654,18 +651,19 @@ static int prepare_qmi_response(struct snd_usb_substream *subs,
	uadev[card_num].card_num = card_num;

	/* 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[subs->interface].data_xfer_ring_size = PAGE_SIZE;
	uadev[card_num].info[subs->interface].sync_xfer_ring_va = tr_sync_va;
	uadev[card_num].info[subs->interface].sync_xfer_ring_size = PAGE_SIZE;
	uadev[card_num].info[subs->interface].xfer_buf_va = xfer_buf_va;
	uadev[card_num].info[subs->interface].xfer_buf_pa = xfer_buf_pa;
	uadev[card_num].info[subs->interface].xfer_buf_size = len;
	uadev[card_num].info[subs->interface].xfer_buf = xfer_buf;
	uadev[card_num].info[subs->interface].pcm_card_num = card_num;
	uadev[card_num].info[subs->interface].pcm_dev_num = pcm_dev_num;
	uadev[card_num].info[subs->interface].direction = subs->direction;
	uadev[card_num].info[subs->interface].in_use = true;
	uadev[card_num].info[info_idx].data_xfer_ring_va = tr_data_va;
	uadev[card_num].info[info_idx].data_xfer_ring_size = PAGE_SIZE;
	uadev[card_num].info[info_idx].sync_xfer_ring_va = tr_sync_va;
	uadev[card_num].info[info_idx].sync_xfer_ring_size = PAGE_SIZE;
	uadev[card_num].info[info_idx].xfer_buf_va = xfer_buf_va;
	uadev[card_num].info[info_idx].xfer_buf_pa = xfer_buf_pa;
	uadev[card_num].info[info_idx].xfer_buf_size = len;
	uadev[card_num].info[info_idx].xfer_buf = xfer_buf;
	uadev[card_num].info[info_idx].pcm_card_num = card_num;
	uadev[card_num].info[info_idx].pcm_dev_num = pcm_dev_num;
	uadev[card_num].info[info_idx].direction = subs->direction;
	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);

@@ -722,7 +720,7 @@ static void uaudio_dev_cleanup(struct uaudio_dev *dev)
			continue;
		uaudio_dev_intf_cleanup(dev->udev, &dev->info[if_idx]);
		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 */
@@ -866,6 +864,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)
{
	struct qmi_uaudio_stream_req_msg_v01 *req_msg;
@@ -876,7 +896,7 @@ static int handle_uaudio_stream_req(void *req_h, void *req)
	struct intf_info *info;
	int pcm_format;
	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;

@@ -920,7 +940,8 @@ static int handle_uaudio_stream_req(void *req_h, void *req)
	}

	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
			|| !subs->stream->chip) {
		ret = -ENODEV;
@@ -928,6 +949,16 @@ static int handle_uaudio_stream_req(void *req_h, void *req)
		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->channels = req_msg->number_of_ch;
	subs->cur_rate = req_msg->bit_rate;
@@ -936,19 +967,18 @@ static int handle_uaudio_stream_req(void *req_h, void *req)
	ret = snd_usb_enable_audio_stream(subs, req_msg->enable);

	if (!ret && req_msg->enable)
		ret = prepare_qmi_response(subs, &resp, req_msg->xfer_buff_size,
			pcm_card_num, pcm_dev_num);
		ret = prepare_qmi_response(subs, req_msg, &resp, info_idx);

	mutex_unlock(&chip->dev_lock);

response:
	if (!req_msg->enable && ret != -EINVAL) {
		if (intf_num >= 0) {
		if (info_idx >= 0) {
			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);
			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);
		}
		if (atomic_read(&uadev[pcm_card_num].in_use))