blob: ebc081f8b112b9e838a9fefd3e14f8e31039d51b [file] [log] [blame]
Vamsi Krishna Samavedam0836aae2016-11-03 17:21:02 -07001/* Copyright (c) 2016-2017, The Linux Foundation. All rights reserved.
Hemant Kumar0ef9fbb2016-01-28 11:41:42 -08002 *
3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License version 2 and
5 * only version 2 as published by the Free Software Foundation.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 *
12 */
13
14#include <linux/module.h>
15#include <linux/slab.h>
16#include <linux/errno.h>
17#include <linux/delay.h>
18#include <linux/debugfs.h>
19#include <linux/usb/audio.h>
Hemant Kumare1578ed2016-12-14 13:19:40 -080020#include <linux/usb/audio-v2.h>
Hemant Kumar0ef9fbb2016-01-28 11:41:42 -080021#include <linux/uaccess.h>
22#include <sound/pcm.h>
23#include <sound/core.h>
24#include <sound/asound.h>
25#include <linux/usb.h>
26#include <linux/qmi_encdec.h>
27#include <soc/qcom/msm_qmi_interface.h>
Hemant Kumard2a54502016-03-22 16:35:16 -070028#include <linux/iommu.h>
29#include <linux/platform_device.h>
Ajay Agarwal2a39f672017-04-11 11:58:28 +053030#include <linux/usb/audio-v3.h>
Hemant Kumar0ef9fbb2016-01-28 11:41:42 -080031
32#include "usbaudio.h"
33#include "card.h"
34#include "helper.h"
35#include "pcm.h"
36#include "usb_audio_qmi_v01.h"
37
38#define SND_PCM_CARD_NUM_MASK 0xffff0000
39#define SND_PCM_DEV_NUM_MASK 0xff00
40#define SND_PCM_STREAM_DIRECTION 0xff
41
Hemant Kumard2a54502016-03-22 16:35:16 -070042#define PREPEND_SID_TO_IOVA(iova, sid) (u64)(((u64)(iova)) | \
43 (((u64)sid) << 32))
44
45/* event ring iova base address */
46#define IOVA_BASE 0x1000
47
Hemant Kumar81156ed2017-09-22 12:34:52 -070048#define IOVA_XFER_RING_BASE (IOVA_BASE + PAGE_SIZE * (SNDRV_CARDS + 1))
Hemant Kumard2a54502016-03-22 16:35:16 -070049#define IOVA_XFER_BUF_BASE (IOVA_XFER_RING_BASE + PAGE_SIZE * SNDRV_CARDS * 32)
50#define IOVA_XFER_RING_MAX (IOVA_XFER_BUF_BASE - PAGE_SIZE)
51#define IOVA_XFER_BUF_MAX (0xfffff000 - PAGE_SIZE)
52
Hemant Kumarbeb99fd2016-10-10 16:49:34 -070053#define MAX_XFER_BUFF_LEN (24 * PAGE_SIZE)
Hemant Kumard2a54502016-03-22 16:35:16 -070054
55struct iova_info {
56 struct list_head list;
57 unsigned long start_iova;
58 size_t size;
59 bool in_use;
60};
61
62struct intf_info {
63 unsigned long data_xfer_ring_va;
64 size_t data_xfer_ring_size;
65 unsigned long sync_xfer_ring_va;
66 size_t sync_xfer_ring_size;
67 unsigned long xfer_buf_va;
68 size_t xfer_buf_size;
69 phys_addr_t xfer_buf_pa;
70 u8 *xfer_buf;
Hemant Kumarebbe6262017-01-10 19:26:40 -080071 u8 intf_num;
Hemant Kumar89fa7b92016-10-27 19:56:31 -070072 u8 pcm_card_num;
73 u8 pcm_dev_num;
74 u8 direction;
Hemant Kumard2a54502016-03-22 16:35:16 -070075 bool in_use;
76};
77
Hemant Kumar0ef9fbb2016-01-28 11:41:42 -080078struct uaudio_dev {
Hemant Kumard2a54502016-03-22 16:35:16 -070079 struct usb_device *udev;
Hemant Kumare1578ed2016-12-14 13:19:40 -080080 /* audio control interface */
81 struct usb_host_interface *ctrl_intf;
Hemant Kumard2a54502016-03-22 16:35:16 -070082 unsigned int card_num;
Hemant Kumar0ef9fbb2016-01-28 11:41:42 -080083 atomic_t in_use;
84 struct kref kref;
85 wait_queue_head_t disconnect_wq;
Hemant Kumard2a54502016-03-22 16:35:16 -070086
87 /* interface specific */
88 int num_intf;
89 struct intf_info *info;
Hemant Kumar0ef9fbb2016-01-28 11:41:42 -080090};
91
92static struct uaudio_dev uadev[SNDRV_CARDS];
93
Hemant Kumard2a54502016-03-22 16:35:16 -070094struct uaudio_qmi_dev {
95 struct device *dev;
96 u32 sid;
97 u32 intr_num;
98 struct iommu_domain *domain;
99
100 /* list to keep track of available iova */
Hemant Kumard2a54502016-03-22 16:35:16 -0700101 struct list_head xfer_ring_list;
102 size_t xfer_ring_iova_size;
103 unsigned long curr_xfer_ring_iova;
104 struct list_head xfer_buf_list;
105 size_t xfer_buf_iova_size;
106 unsigned long curr_xfer_buf_iova;
107 /* bit fields representing pcm card enabled */
108 unsigned long card_slot;
109 /* cache event ring phys addr */
110 u64 er_phys_addr;
111};
112
113static struct uaudio_qmi_dev *uaudio_qdev;
114
Hemant Kumar0ef9fbb2016-01-28 11:41:42 -0800115struct uaudio_qmi_svc {
116 struct qmi_handle *uaudio_svc_hdl;
117 void *curr_conn;
118 struct work_struct recv_msg_work;
Hemant Kumar89fa7b92016-10-27 19:56:31 -0700119 struct work_struct qmi_disconnect_work;
Hemant Kumar0ef9fbb2016-01-28 11:41:42 -0800120 struct workqueue_struct *uaudio_wq;
121 ktime_t t_request_recvd;
122 ktime_t t_resp_sent;
123};
124
125static struct uaudio_qmi_svc *uaudio_svc;
126
127static struct msg_desc uaudio_stream_req_desc = {
128 .max_msg_len = QMI_UAUDIO_STREAM_REQ_MSG_V01_MAX_MSG_LEN,
129 .msg_id = QMI_UAUDIO_STREAM_REQ_V01,
130 .ei_array = qmi_uaudio_stream_req_msg_v01_ei,
131};
132
133static struct msg_desc uaudio_stream_resp_desc = {
134 .max_msg_len = QMI_UAUDIO_STREAM_RESP_MSG_V01_MAX_MSG_LEN,
135 .msg_id = QMI_UAUDIO_STREAM_RESP_V01,
136 .ei_array = qmi_uaudio_stream_resp_msg_v01_ei,
137};
138
Vamsi Krishna Samavedam1e634532016-09-13 14:09:37 -0700139static struct msg_desc uaudio_stream_ind_desc = {
140 .max_msg_len = QMI_UAUDIO_STREAM_IND_MSG_V01_MAX_MSG_LEN,
141 .msg_id = QMI_UADUIO_STREAM_IND_V01,
142 .ei_array = qmi_uaudio_stream_ind_msg_v01_ei,
143};
144
Hemant Kumard2a54502016-03-22 16:35:16 -0700145enum mem_type {
146 MEM_EVENT_RING,
Hemant Kumard2a54502016-03-22 16:35:16 -0700147 MEM_XFER_RING,
148 MEM_XFER_BUF,
149};
150
Hemant Kumara4f61012016-10-13 15:41:55 -0700151enum usb_qmi_audio_format {
152 USB_QMI_PCM_FORMAT_S8 = 0,
153 USB_QMI_PCM_FORMAT_U8,
154 USB_QMI_PCM_FORMAT_S16_LE,
155 USB_QMI_PCM_FORMAT_S16_BE,
156 USB_QMI_PCM_FORMAT_U16_LE,
157 USB_QMI_PCM_FORMAT_U16_BE,
158 USB_QMI_PCM_FORMAT_S24_LE,
159 USB_QMI_PCM_FORMAT_S24_BE,
160 USB_QMI_PCM_FORMAT_U24_LE,
161 USB_QMI_PCM_FORMAT_U24_BE,
162 USB_QMI_PCM_FORMAT_S24_3LE,
163 USB_QMI_PCM_FORMAT_S24_3BE,
164 USB_QMI_PCM_FORMAT_U24_3LE,
165 USB_QMI_PCM_FORMAT_U24_3BE,
166 USB_QMI_PCM_FORMAT_S32_LE,
167 USB_QMI_PCM_FORMAT_S32_BE,
168 USB_QMI_PCM_FORMAT_U32_LE,
169 USB_QMI_PCM_FORMAT_U32_BE,
170};
171
Hemant Kumar81156ed2017-09-22 12:34:52 -0700172static enum usb_audio_device_speed_enum_v01
173get_speed_info(enum usb_device_speed udev_speed)
174{
175 switch (udev_speed) {
176 case USB_SPEED_LOW:
177 return USB_AUDIO_DEVICE_SPEED_LOW_V01;
178 case USB_SPEED_FULL:
179 return USB_AUDIO_DEVICE_SPEED_FULL_V01;
180 case USB_SPEED_HIGH:
181 return USB_AUDIO_DEVICE_SPEED_HIGH_V01;
182 case USB_SPEED_SUPER:
183 return USB_AUDIO_DEVICE_SPEED_SUPER_V01;
184 default:
185 pr_err("%s: udev speed %d\n", __func__, udev_speed);
186 return USB_AUDIO_DEVICE_SPEED_INVALID_V01;
187 }
188}
189
Hemant Kumard2a54502016-03-22 16:35:16 -0700190static unsigned long uaudio_get_iova(unsigned long *curr_iova,
191 size_t *curr_iova_size, struct list_head *head, size_t size)
Hemant Kumar0ef9fbb2016-01-28 11:41:42 -0800192{
Hemant Kumard2a54502016-03-22 16:35:16 -0700193 struct iova_info *info, *new_info = NULL;
194 struct list_head *curr_head;
195 unsigned long va = 0;
196 size_t tmp_size = size;
197 bool found = false;
198
199 if (size % PAGE_SIZE) {
200 pr_err("%s: size %zu is not page size multiple\n", __func__,
201 size);
202 goto done;
203 }
204
205 if (size > *curr_iova_size) {
206 pr_err("%s: size %zu > curr size %zu\n", __func__, size,
207 *curr_iova_size);
208 goto done;
209 }
210 if (*curr_iova_size == 0) {
211 pr_err("%s: iova mapping is full\n", __func__);
212 goto done;
213 }
214
215 list_for_each_entry(info, head, list) {
216 /* exact size iova_info */
217 if (!info->in_use && info->size == size) {
218 info->in_use = true;
219 va = info->start_iova;
220 *curr_iova_size -= size;
221 found = true;
222 pr_debug("%s: exact size :%zu found\n", __func__, size);
223 goto done;
224 } else if (!info->in_use && tmp_size >= info->size) {
225 if (!new_info)
226 new_info = info;
227 pr_debug("%s: partial size: %zu found\n", __func__,
228 info->size);
229 tmp_size -= info->size;
230 if (tmp_size)
231 continue;
232
233 va = new_info->start_iova;
234 for (curr_head = &new_info->list; curr_head !=
235 &info->list; curr_head = curr_head->next) {
236 new_info = list_entry(curr_head, struct
237 iova_info, list);
238 new_info->in_use = true;
239 }
240 info->in_use = true;
241 *curr_iova_size -= size;
242 found = true;
243 goto done;
244 } else {
245 /* iova region in use */
246 new_info = NULL;
247 tmp_size = size;
248 }
249 }
250
251 info = kzalloc(sizeof(struct iova_info), GFP_KERNEL);
252 if (!info) {
253 va = 0;
254 goto done;
255 }
256
257 va = info->start_iova = *curr_iova;
258 info->size = size;
259 info->in_use = true;
260 *curr_iova += size;
261 *curr_iova_size -= size;
262 found = true;
263 list_add_tail(&info->list, head);
264
265done:
266 if (!found)
267 pr_err("%s: unable to find %zu size iova\n", __func__, size);
268 else
269 pr_debug("%s: va:%lu curr_iova:%lu curr_iova_size:%zu\n",
270 __func__, va, *curr_iova, *curr_iova_size);
271
272 return va;
273}
274
275static unsigned long uaudio_iommu_map(enum mem_type mtype, phys_addr_t pa,
276 size_t size)
277{
278 unsigned long va = 0;
279 bool map = true;
280 int ret;
281
282 switch (mtype) {
283 case MEM_EVENT_RING:
284 va = IOVA_BASE;
285 /* er already mapped */
286 if (uaudio_qdev->er_phys_addr == pa)
287 map = false;
288 break;
Hemant Kumard2a54502016-03-22 16:35:16 -0700289 case MEM_XFER_RING:
290 va = uaudio_get_iova(&uaudio_qdev->curr_xfer_ring_iova,
291 &uaudio_qdev->xfer_ring_iova_size, &uaudio_qdev->xfer_ring_list,
292 size);
293 break;
294 case MEM_XFER_BUF:
295 va = uaudio_get_iova(&uaudio_qdev->curr_xfer_buf_iova,
296 &uaudio_qdev->xfer_buf_iova_size, &uaudio_qdev->xfer_buf_list,
297 size);
298 break;
299 default:
300 pr_err("%s: unknown mem type %d\n", __func__, mtype);
301 }
302
303 if (!va)
304 map = false;
305
306 if (!map)
307 goto done;
308
309 pr_debug("%s: map pa %pa to iova %lu for memtype %d\n", __func__, &pa,
310 va, mtype);
311 ret = iommu_map(uaudio_qdev->domain, va, pa, size,
312 IOMMU_READ | IOMMU_WRITE | IOMMU_MMIO);
313 if (ret)
314 pr_err("%s:failed to map pa:%pa iova:%lu memtype:%d ret:%d\n",
315 __func__, &pa, va, mtype, ret);
316done:
317 return va;
318}
319
320static void uaudio_put_iova(unsigned long va, size_t size, struct list_head
321 *head, size_t *curr_iova_size)
322{
323 struct iova_info *info;
324 size_t tmp_size = size;
325 bool found = false;
326
327 list_for_each_entry(info, head, list) {
328 if (info->start_iova == va) {
329 if (!info->in_use) {
330 pr_err("%s: va %lu is not in use\n", __func__,
331 va);
332 return;
333 }
334 found = true;
335 info->in_use = false;
336 if (info->size == size)
337 goto done;
338 }
339
340 if (found && tmp_size >= info->size) {
341 info->in_use = false;
342 tmp_size -= info->size;
343 if (!tmp_size)
344 goto done;
345 }
346 }
347
348 if (!found) {
349 pr_err("%s: unable to find the va %lu\n", __func__, va);
350 return;
351 }
352done:
353 *curr_iova_size += size;
354 pr_debug("%s: curr_iova_size %zu\n", __func__, *curr_iova_size);
355}
356
357static void uaudio_iommu_unmap(enum mem_type mtype, unsigned long va,
358 size_t size)
359{
360 size_t umap_size;
361 bool unmap = true;
362
363 if (!va || !size)
364 return;
365
366 switch (mtype) {
367 case MEM_EVENT_RING:
368 if (uaudio_qdev->er_phys_addr)
369 uaudio_qdev->er_phys_addr = 0;
370 else
371 unmap = false;
372 break;
Hemant Kumar81156ed2017-09-22 12:34:52 -0700373
Hemant Kumard2a54502016-03-22 16:35:16 -0700374 case MEM_XFER_RING:
375 uaudio_put_iova(va, size, &uaudio_qdev->xfer_ring_list,
376 &uaudio_qdev->xfer_ring_iova_size);
377 break;
378 case MEM_XFER_BUF:
379 uaudio_put_iova(va, size, &uaudio_qdev->xfer_buf_list,
380 &uaudio_qdev->xfer_buf_iova_size);
381 break;
382 default:
383 pr_err("%s: unknown mem type %d\n", __func__, mtype);
384 unmap = false;
385 }
386
387 if (!unmap)
388 return;
389
390 pr_debug("%s: unmap iova %lu for memtype %d\n", __func__, va, mtype);
391
392 umap_size = iommu_unmap(uaudio_qdev->domain, va, size);
393 if (umap_size != size)
394 pr_err("%s: unmapped size %zu for iova %lu\n", __func__,
395 umap_size, va);
396}
397
398static int prepare_qmi_response(struct snd_usb_substream *subs,
Hemant Kumarebbe6262017-01-10 19:26:40 -0800399 struct qmi_uaudio_stream_req_msg_v01 *req_msg,
400 struct qmi_uaudio_stream_resp_msg_v01 *resp, int info_idx)
Hemant Kumard2a54502016-03-22 16:35:16 -0700401{
Hemant Kumar0ef9fbb2016-01-28 11:41:42 -0800402 struct usb_interface *iface;
403 struct usb_host_interface *alts;
404 struct usb_interface_descriptor *altsd;
405 struct usb_host_endpoint *ep;
406 struct uac_format_type_i_continuous_descriptor *fmt;
407 struct uac_format_type_i_discrete_descriptor *fmt_v1;
408 struct uac_format_type_i_ext_descriptor *fmt_v2;
409 struct uac1_as_header_descriptor *as;
Hemant Kumarebbe6262017-01-10 19:26:40 -0800410 int ret = -ENODEV;
411 int protocol, card_num, pcm_dev_num;
Hemant Kumare1578ed2016-12-14 13:19:40 -0800412 void *hdr_ptr;
Hemant Kumard2a54502016-03-22 16:35:16 -0700413 u8 *xfer_buf;
Hemant Kumar1346a802017-09-22 15:03:45 -0700414 u32 len, mult, remainder, xfer_buf_len, sg_len, i, total_len = 0;
415 unsigned long va, va_sg, tr_data_va = 0, tr_sync_va = 0;
416 phys_addr_t xhci_pa, xfer_buf_pa, tr_data_pa = 0, tr_sync_pa = 0;
417 dma_addr_t dma;
418 struct sg_table sgt;
419 struct scatterlist *sg;
Hemant Kumar0ef9fbb2016-01-28 11:41:42 -0800420
421 iface = usb_ifnum_to_if(subs->dev, subs->interface);
422 if (!iface) {
423 pr_err("%s: interface # %d does not exist\n", __func__,
424 subs->interface);
425 goto err;
426 }
427
Hemant Kumarebbe6262017-01-10 19:26:40 -0800428 pcm_dev_num = (req_msg->usb_token & SND_PCM_DEV_NUM_MASK) >> 8;
429 card_num = (req_msg->usb_token & SND_PCM_CARD_NUM_MASK) >> 16;
430 xfer_buf_len = req_msg->xfer_buff_size;
Hemant Kumar89fa7b92016-10-27 19:56:31 -0700431
Hemant Kumar0ef9fbb2016-01-28 11:41:42 -0800432 alts = &iface->altsetting[subs->altset_idx];
433 altsd = get_iface_desc(alts);
434 protocol = altsd->bInterfaceProtocol;
435
436 /* get format type */
Ajay Agarwal2a39f672017-04-11 11:58:28 +0530437 if (protocol != UAC_VERSION_3) {
438 fmt = snd_usb_find_csint_desc(alts->extra, alts->extralen, NULL,
439 UAC_FORMAT_TYPE);
440 if (!fmt) {
441 pr_err("%s: %u:%d : no UAC_FORMAT_TYPE desc\n",
442 __func__, subs->interface, subs->altset_idx);
443 goto err;
444 }
Hemant Kumar0ef9fbb2016-01-28 11:41:42 -0800445 }
446
Hemant Kumare1578ed2016-12-14 13:19:40 -0800447 if (!uadev[card_num].ctrl_intf) {
448 pr_err("%s: audio ctrl intf info not cached\n", __func__);
449 goto err;
450 }
451
Ajay Agarwal2a39f672017-04-11 11:58:28 +0530452 if (protocol != UAC_VERSION_3) {
453 hdr_ptr = snd_usb_find_csint_desc(
454 uadev[card_num].ctrl_intf->extra,
455 uadev[card_num].ctrl_intf->extralen,
456 NULL, UAC_HEADER);
457 if (!hdr_ptr) {
458 pr_err("%s: no UAC_HEADER desc\n", __func__);
459 goto err;
460 }
Hemant Kumare1578ed2016-12-14 13:19:40 -0800461 }
462
Hemant Kumar0ef9fbb2016-01-28 11:41:42 -0800463 if (protocol == UAC_VERSION_1) {
464 as = snd_usb_find_csint_desc(alts->extra, alts->extralen, NULL,
465 UAC_AS_GENERAL);
466 if (!as) {
467 pr_err("%s: %u:%d : no UAC_AS_GENERAL desc\n", __func__,
468 subs->interface, subs->altset_idx);
469 goto err;
470 }
Hemant Kumaraa2fa3c2016-07-18 16:26:48 -0700471 resp->data_path_delay = as->bDelay;
472 resp->data_path_delay_valid = 1;
Hemant Kumar0ef9fbb2016-01-28 11:41:42 -0800473 fmt_v1 = (struct uac_format_type_i_discrete_descriptor *)fmt;
Hemant Kumaraa2fa3c2016-07-18 16:26:48 -0700474 resp->usb_audio_subslot_size = fmt_v1->bSubframeSize;
475 resp->usb_audio_subslot_size_valid = 1;
Hemant Kumare1578ed2016-12-14 13:19:40 -0800476
477 resp->usb_audio_spec_revision =
478 ((struct uac1_ac_header_descriptor *)hdr_ptr)->bcdADC;
479 resp->usb_audio_spec_revision_valid = 1;
Hemant Kumar0ef9fbb2016-01-28 11:41:42 -0800480 } else if (protocol == UAC_VERSION_2) {
481 fmt_v2 = (struct uac_format_type_i_ext_descriptor *)fmt;
Hemant Kumaraa2fa3c2016-07-18 16:26:48 -0700482 resp->usb_audio_subslot_size = fmt_v2->bSubslotSize;
483 resp->usb_audio_subslot_size_valid = 1;
Hemant Kumare1578ed2016-12-14 13:19:40 -0800484
485 resp->usb_audio_spec_revision =
486 ((struct uac2_ac_header_descriptor *)hdr_ptr)->bcdADC;
487 resp->usb_audio_spec_revision_valid = 1;
Ajay Agarwal2a39f672017-04-11 11:58:28 +0530488 } else if (protocol == UAC_VERSION_3) {
489 switch (le16_to_cpu(get_endpoint(alts, 0)->wMaxPacketSize)) {
490 case BADD_MAXPSIZE_SYNC_MONO_16:
491 case BADD_MAXPSIZE_SYNC_STEREO_16:
492 case BADD_MAXPSIZE_ASYNC_MONO_16:
493 case BADD_MAXPSIZE_ASYNC_STEREO_16: {
494 resp->usb_audio_subslot_size = SUBSLOTSIZE_16_BIT;
495 break;
496 }
497
498 case BADD_MAXPSIZE_SYNC_MONO_24:
499 case BADD_MAXPSIZE_SYNC_STEREO_24:
500 case BADD_MAXPSIZE_ASYNC_MONO_24:
501 case BADD_MAXPSIZE_ASYNC_STEREO_24: {
502 resp->usb_audio_subslot_size = SUBSLOTSIZE_24_BIT;
503 break;
504 }
505
506 default:
507 pr_err("%d: %u: Invalid wMaxPacketSize\n",
508 subs->interface, subs->altset_idx);
509 ret = -EINVAL;
510 goto err;
511 }
512 resp->usb_audio_subslot_size_valid = 1;
Hemant Kumar0ef9fbb2016-01-28 11:41:42 -0800513 } else {
514 pr_err("%s: unknown protocol version %x\n", __func__, protocol);
515 goto err;
516 }
517
Hemant Kumar0ef9fbb2016-01-28 11:41:42 -0800518 resp->slot_id = subs->dev->slot_id;
Hemant Kumaraa2fa3c2016-07-18 16:26:48 -0700519 resp->slot_id_valid = 1;
Hemant Kumar0ef9fbb2016-01-28 11:41:42 -0800520
521 memcpy(&resp->std_as_opr_intf_desc, &alts->desc, sizeof(alts->desc));
Hemant Kumaraa2fa3c2016-07-18 16:26:48 -0700522 resp->std_as_opr_intf_desc_valid = 1;
Hemant Kumar0ef9fbb2016-01-28 11:41:42 -0800523
524 ep = usb_pipe_endpoint(subs->dev, subs->data_endpoint->pipe);
525 if (!ep) {
526 pr_err("%s: data ep # %d context is null\n", __func__,
527 subs->data_endpoint->ep_num);
528 goto err;
529 }
530 memcpy(&resp->std_as_data_ep_desc, &ep->desc, sizeof(ep->desc));
Hemant Kumaraa2fa3c2016-07-18 16:26:48 -0700531 resp->std_as_data_ep_desc_valid = 1;
Hemant Kumar0ef9fbb2016-01-28 11:41:42 -0800532
Hemant Kumar1346a802017-09-22 15:03:45 -0700533 tr_data_pa = usb_get_xfer_ring_phys_addr(subs->dev, ep, &dma);
534 if (!tr_data_pa) {
Hemant Kumard2a54502016-03-22 16:35:16 -0700535 pr_err("%s:failed to get data ep ring dma address\n", __func__);
536 goto err;
537 }
538
Hemant Kumar1346a802017-09-22 15:03:45 -0700539 resp->xhci_mem_info.tr_data.pa = dma;
Hemant Kumard2a54502016-03-22 16:35:16 -0700540
Hemant Kumar0ef9fbb2016-01-28 11:41:42 -0800541 if (subs->sync_endpoint) {
542 ep = usb_pipe_endpoint(subs->dev, subs->sync_endpoint->pipe);
543 if (!ep) {
Hemant Kumar44cefc52016-12-06 18:34:40 -0800544 pr_debug("%s: implicit fb on data ep\n", __func__);
545 goto skip_sync_ep;
Hemant Kumar0ef9fbb2016-01-28 11:41:42 -0800546 }
547 memcpy(&resp->std_as_sync_ep_desc, &ep->desc, sizeof(ep->desc));
Hemant Kumaraa2fa3c2016-07-18 16:26:48 -0700548 resp->std_as_sync_ep_desc_valid = 1;
549
Hemant Kumar1346a802017-09-22 15:03:45 -0700550 tr_sync_pa = usb_get_xfer_ring_phys_addr(subs->dev, ep, &dma);
551 if (!tr_sync_pa) {
Hemant Kumard2a54502016-03-22 16:35:16 -0700552 pr_err("%s:failed to get sync ep ring dma address\n",
553 __func__);
554 goto err;
555 }
Hemant Kumar1346a802017-09-22 15:03:45 -0700556 resp->xhci_mem_info.tr_sync.pa = dma;
Hemant Kumar0ef9fbb2016-01-28 11:41:42 -0800557 }
558
Hemant Kumar44cefc52016-12-06 18:34:40 -0800559skip_sync_ep:
Hemant Kumard2a54502016-03-22 16:35:16 -0700560 resp->interrupter_num = uaudio_qdev->intr_num;
Hemant Kumaraa2fa3c2016-07-18 16:26:48 -0700561 resp->interrupter_num_valid = 1;
Hemant Kumard2a54502016-03-22 16:35:16 -0700562
Hemant Kumar746cc972017-08-17 17:34:05 -0700563 ret = usb_get_controller_id(subs->dev);
564 if (ret < 0)
565 goto err;
566
567 resp->controller_num = ret;
568 resp->controller_num_valid = 1;
569
Hemant Kumard2a54502016-03-22 16:35:16 -0700570 /* map xhci data structures PA memory to iova */
571
572 /* event ring */
573 ret = usb_sec_event_ring_setup(subs->dev, resp->interrupter_num);
574 if (ret) {
575 pr_err("%s: failed to setup sec event ring ret %d\n", __func__,
576 ret);
577 goto err;
578 }
Hemant Kumar1346a802017-09-22 15:03:45 -0700579 xhci_pa = usb_get_sec_event_ring_phys_addr(subs->dev,
580 resp->interrupter_num, &dma);
Hemant Kumard2a54502016-03-22 16:35:16 -0700581 if (!xhci_pa) {
582 pr_err("%s: failed to get sec event ring dma address\n",
583 __func__);
584 goto err;
585 }
586
587 va = uaudio_iommu_map(MEM_EVENT_RING, xhci_pa, PAGE_SIZE);
588 if (!va)
589 goto err;
590
591 resp->xhci_mem_info.evt_ring.va = PREPEND_SID_TO_IOVA(va,
592 uaudio_qdev->sid);
Hemant Kumar1346a802017-09-22 15:03:45 -0700593 resp->xhci_mem_info.evt_ring.pa = dma;
Hemant Kumard2a54502016-03-22 16:35:16 -0700594 resp->xhci_mem_info.evt_ring.size = PAGE_SIZE;
595 uaudio_qdev->er_phys_addr = xhci_pa;
596
Hemant Kumar81156ed2017-09-22 12:34:52 -0700597 resp->speed_info = get_speed_info(subs->dev->speed);
598 if (resp->speed_info == USB_AUDIO_DEVICE_SPEED_INVALID_V01)
Hemant Kumard2a54502016-03-22 16:35:16 -0700599 goto unmap_er;
Hemant Kumard2a54502016-03-22 16:35:16 -0700600
Hemant Kumar81156ed2017-09-22 12:34:52 -0700601 resp->speed_info_valid = 1;
Hemant Kumard2a54502016-03-22 16:35:16 -0700602
603 /* data transfer ring */
Hemant Kumar1346a802017-09-22 15:03:45 -0700604 va = uaudio_iommu_map(MEM_XFER_RING, tr_data_pa, PAGE_SIZE);
Hemant Kumard2a54502016-03-22 16:35:16 -0700605 if (!va)
Hemant Kumar81156ed2017-09-22 12:34:52 -0700606 goto unmap_er;
Hemant Kumard2a54502016-03-22 16:35:16 -0700607
608 tr_data_va = va;
609 resp->xhci_mem_info.tr_data.va = PREPEND_SID_TO_IOVA(va,
610 uaudio_qdev->sid);
611 resp->xhci_mem_info.tr_data.size = PAGE_SIZE;
612
613 /* sync transfer ring */
614 if (!resp->xhci_mem_info.tr_sync.pa)
615 goto skip_sync;
616
617 xhci_pa = resp->xhci_mem_info.tr_sync.pa;
Hemant Kumar1346a802017-09-22 15:03:45 -0700618 va = uaudio_iommu_map(MEM_XFER_RING, tr_sync_pa, PAGE_SIZE);
Hemant Kumard2a54502016-03-22 16:35:16 -0700619 if (!va)
620 goto unmap_data;
621
622 tr_sync_va = va;
623 resp->xhci_mem_info.tr_sync.va = PREPEND_SID_TO_IOVA(va,
624 uaudio_qdev->sid);
625 resp->xhci_mem_info.tr_sync.size = PAGE_SIZE;
626
627skip_sync:
628 /* xfer buffer, multiple of 4K only */
629 if (!xfer_buf_len)
630 xfer_buf_len = PAGE_SIZE;
631
632 mult = xfer_buf_len / PAGE_SIZE;
633 remainder = xfer_buf_len % PAGE_SIZE;
634 len = mult * PAGE_SIZE;
635 len += remainder ? PAGE_SIZE : 0;
636
637 if (len > MAX_XFER_BUFF_LEN) {
638 pr_err("%s: req buf len %d > max buf len %lu, setting %lu\n",
639 __func__, len, MAX_XFER_BUFF_LEN, MAX_XFER_BUFF_LEN);
640 len = MAX_XFER_BUFF_LEN;
641 }
642
643 xfer_buf = usb_alloc_coherent(subs->dev, len, GFP_KERNEL, &xfer_buf_pa);
644 if (!xfer_buf)
645 goto unmap_sync;
646
Hemant Kumar1346a802017-09-22 15:03:45 -0700647 dma_get_sgtable(subs->dev->bus->sysdev, &sgt, xfer_buf, xfer_buf_pa,
648 len);
649
650 va = 0;
651 for_each_sg(sgt.sgl, sg, sgt.nents, i) {
652 sg_len = PAGE_ALIGN(sg->offset + sg->length);
653 va_sg = uaudio_iommu_map(MEM_XFER_BUF,
654 page_to_phys(sg_page(sg)), sg_len);
655 if (!va_sg)
656 goto unmap_xfer_buf;
657
658 if (!va)
659 va = va_sg;
660
661 total_len += sg_len;
662 }
663
Hemant Kumard2a54502016-03-22 16:35:16 -0700664 resp->xhci_mem_info.xfer_buff.pa = xfer_buf_pa;
665 resp->xhci_mem_info.xfer_buff.size = len;
666
Hemant Kumard2a54502016-03-22 16:35:16 -0700667 resp->xhci_mem_info.xfer_buff.va = PREPEND_SID_TO_IOVA(va,
668 uaudio_qdev->sid);
669
Hemant Kumaraa2fa3c2016-07-18 16:26:48 -0700670 resp->xhci_mem_info_valid = 1;
671
Hemant Kumar1346a802017-09-22 15:03:45 -0700672 sg_free_table(&sgt);
673
Hemant Kumar0ef9fbb2016-01-28 11:41:42 -0800674 if (!atomic_read(&uadev[card_num].in_use)) {
675 kref_init(&uadev[card_num].kref);
676 init_waitqueue_head(&uadev[card_num].disconnect_wq);
Hemant Kumard2a54502016-03-22 16:35:16 -0700677 uadev[card_num].num_intf =
678 subs->dev->config->desc.bNumInterfaces;
679 uadev[card_num].info =
680 kzalloc(sizeof(struct intf_info) *
681 uadev[card_num].num_intf, GFP_KERNEL);
682 if (!uadev[card_num].info) {
683 ret = -ENOMEM;
684 goto unmap_xfer_buf;
685 }
686 uadev[card_num].udev = subs->dev;
Hemant Kumar0ef9fbb2016-01-28 11:41:42 -0800687 atomic_set(&uadev[card_num].in_use, 1);
688 } else {
689 kref_get(&uadev[card_num].kref);
690 }
691
Hemant Kumard2a54502016-03-22 16:35:16 -0700692 uadev[card_num].card_num = card_num;
693
694 /* cache intf specific info to use it for unmap and free xfer buf */
Hemant Kumarebbe6262017-01-10 19:26:40 -0800695 uadev[card_num].info[info_idx].data_xfer_ring_va = tr_data_va;
696 uadev[card_num].info[info_idx].data_xfer_ring_size = PAGE_SIZE;
697 uadev[card_num].info[info_idx].sync_xfer_ring_va = tr_sync_va;
698 uadev[card_num].info[info_idx].sync_xfer_ring_size = PAGE_SIZE;
Hemant Kumar1346a802017-09-22 15:03:45 -0700699 uadev[card_num].info[info_idx].xfer_buf_va = va;
Hemant Kumarebbe6262017-01-10 19:26:40 -0800700 uadev[card_num].info[info_idx].xfer_buf_pa = xfer_buf_pa;
701 uadev[card_num].info[info_idx].xfer_buf_size = len;
702 uadev[card_num].info[info_idx].xfer_buf = xfer_buf;
703 uadev[card_num].info[info_idx].pcm_card_num = card_num;
704 uadev[card_num].info[info_idx].pcm_dev_num = pcm_dev_num;
705 uadev[card_num].info[info_idx].direction = subs->direction;
706 uadev[card_num].info[info_idx].intf_num = subs->interface;
707 uadev[card_num].info[info_idx].in_use = true;
Hemant Kumard2a54502016-03-22 16:35:16 -0700708
709 set_bit(card_num, &uaudio_qdev->card_slot);
710
Hemant Kumar0ef9fbb2016-01-28 11:41:42 -0800711 return 0;
Hemant Kumard2a54502016-03-22 16:35:16 -0700712
713unmap_xfer_buf:
Hemant Kumar1346a802017-09-22 15:03:45 -0700714 if (va)
715 uaudio_iommu_unmap(MEM_XFER_BUF, va, total_len);
Hemant Kumard2a54502016-03-22 16:35:16 -0700716unmap_sync:
717 usb_free_coherent(subs->dev, len, xfer_buf, xfer_buf_pa);
718 uaudio_iommu_unmap(MEM_XFER_RING, tr_sync_va, PAGE_SIZE);
719unmap_data:
720 uaudio_iommu_unmap(MEM_XFER_RING, tr_data_va, PAGE_SIZE);
Hemant Kumard2a54502016-03-22 16:35:16 -0700721unmap_er:
722 uaudio_iommu_unmap(MEM_EVENT_RING, IOVA_BASE, PAGE_SIZE);
Hemant Kumar0ef9fbb2016-01-28 11:41:42 -0800723err:
Hemant Kumard2a54502016-03-22 16:35:16 -0700724 return ret;
Hemant Kumar0ef9fbb2016-01-28 11:41:42 -0800725}
726
Hemant Kumar89fa7b92016-10-27 19:56:31 -0700727static void uaudio_dev_intf_cleanup(struct usb_device *udev,
728 struct intf_info *info)
Hemant Kumar0ef9fbb2016-01-28 11:41:42 -0800729{
Hemant Kumar89fa7b92016-10-27 19:56:31 -0700730 uaudio_iommu_unmap(MEM_XFER_RING, info->data_xfer_ring_va,
731 info->data_xfer_ring_size);
732 info->data_xfer_ring_va = 0;
733 info->data_xfer_ring_size = 0;
734
735 uaudio_iommu_unmap(MEM_XFER_RING, info->sync_xfer_ring_va,
736 info->sync_xfer_ring_size);
737 info->sync_xfer_ring_va = 0;
738 info->sync_xfer_ring_size = 0;
739
740 uaudio_iommu_unmap(MEM_XFER_BUF, info->xfer_buf_va,
741 info->xfer_buf_size);
742 info->xfer_buf_va = 0;
743
744 usb_free_coherent(udev, info->xfer_buf_size,
745 info->xfer_buf, info->xfer_buf_pa);
746 info->xfer_buf_size = 0;
747 info->xfer_buf = NULL;
748 info->xfer_buf_pa = 0;
749
750 info->in_use = false;
751}
752
753static void uaudio_dev_cleanup(struct uaudio_dev *dev)
754{
755 int if_idx;
756
757 /* free xfer buffer and unmap xfer ring and buf per interface */
758 for (if_idx = 0; if_idx < dev->num_intf; if_idx++) {
759 if (!dev->info[if_idx].in_use)
760 continue;
761 uaudio_dev_intf_cleanup(dev->udev, &dev->info[if_idx]);
762 pr_debug("%s: release resources: intf# %d card# %d\n", __func__,
Hemant Kumarebbe6262017-01-10 19:26:40 -0800763 dev->info[if_idx].intf_num, dev->card_num);
Hemant Kumar89fa7b92016-10-27 19:56:31 -0700764 }
765
Hemant Kumar89fa7b92016-10-27 19:56:31 -0700766 dev->num_intf = 0;
767
768 /* free interface info */
769 kfree(dev->info);
770 dev->info = NULL;
771
772 clear_bit(dev->card_num, &uaudio_qdev->card_slot);
773
774 /* all audio devices are disconnected */
775 if (!uaudio_qdev->card_slot) {
776 uaudio_iommu_unmap(MEM_EVENT_RING, IOVA_BASE, PAGE_SIZE);
777 usb_sec_event_ring_cleanup(dev->udev, uaudio_qdev->intr_num);
778 pr_debug("%s: all audio devices disconnected\n", __func__);
779 }
780
781 dev->udev = NULL;
782}
783
784static void uaudio_disconnect_cb(struct snd_usb_audio *chip)
785{
786 int ret;
Hemant Kumar0ef9fbb2016-01-28 11:41:42 -0800787 struct uaudio_dev *dev;
788 int card_num = chip->card_num;
Vamsi Krishna Samavedam1e634532016-09-13 14:09:37 -0700789 struct uaudio_qmi_svc *svc = uaudio_svc;
790 struct qmi_uaudio_stream_ind_msg_v01 disconnect_ind = {0};
Hemant Kumar0ef9fbb2016-01-28 11:41:42 -0800791
Hemant Kumard2a54502016-03-22 16:35:16 -0700792 pr_debug("%s: for card# %d\n", __func__, card_num);
793
Hemant Kumar0ef9fbb2016-01-28 11:41:42 -0800794 if (card_num >= SNDRV_CARDS) {
795 pr_err("%s: invalid card number\n", __func__);
Vamsi Krishna Samavedam1e634532016-09-13 14:09:37 -0700796 return;
Hemant Kumar0ef9fbb2016-01-28 11:41:42 -0800797 }
798
Vamsi Krishna Samavedam1e634532016-09-13 14:09:37 -0700799 mutex_lock(&chip->dev_lock);
Hemant Kumar0ef9fbb2016-01-28 11:41:42 -0800800 dev = &uadev[card_num];
Hemant Kumard2a54502016-03-22 16:35:16 -0700801
802 /* clean up */
803 if (!dev->udev) {
804 pr_debug("%s: no clean up required\n", __func__);
805 goto done;
806 }
807
Vamsi Krishna Samavedam1e634532016-09-13 14:09:37 -0700808 if (atomic_read(&dev->in_use)) {
809 mutex_unlock(&chip->dev_lock);
810
811 pr_debug("%s: sending qmi indication disconnect\n", __func__);
812 disconnect_ind.dev_event = USB_AUDIO_DEV_DISCONNECT_V01;
813 disconnect_ind.slot_id = dev->udev->slot_id;
814 ret = qmi_send_ind(svc->uaudio_svc_hdl, svc->curr_conn,
815 &uaudio_stream_ind_desc, &disconnect_ind,
816 sizeof(disconnect_ind));
817 if (ret < 0) {
818 pr_err("%s: qmi send failed wiht err: %d\n",
819 __func__, ret);
820 return;
821 }
822
823 ret = wait_event_interruptible(dev->disconnect_wq,
824 !atomic_read(&dev->in_use));
825 if (ret < 0) {
826 pr_debug("%s: failed with ret %d\n", __func__, ret);
827 return;
828 }
829 mutex_lock(&chip->dev_lock);
830 }
831
Hemant Kumar89fa7b92016-10-27 19:56:31 -0700832 uaudio_dev_cleanup(dev);
Hemant Kumar0ef9fbb2016-01-28 11:41:42 -0800833done:
834 mutex_unlock(&chip->dev_lock);
835}
836
837static void uaudio_dev_release(struct kref *kref)
838{
839 struct uaudio_dev *dev = container_of(kref, struct uaudio_dev, kref);
840
Vamsi Krishna Samavedam0836aae2016-11-03 17:21:02 -0700841 pr_debug("%s for dev %pK\n", __func__, dev);
Hemant Kumard2a54502016-03-22 16:35:16 -0700842
Hemant Kumar0ef9fbb2016-01-28 11:41:42 -0800843 atomic_set(&dev->in_use, 0);
Hemant Kumard2a54502016-03-22 16:35:16 -0700844
845 clear_bit(dev->card_num, &uaudio_qdev->card_slot);
846
847 /* all audio devices are disconnected */
848 if (!uaudio_qdev->card_slot) {
849 usb_sec_event_ring_cleanup(dev->udev, uaudio_qdev->intr_num);
850 uaudio_iommu_unmap(MEM_EVENT_RING, IOVA_BASE, PAGE_SIZE);
851 pr_debug("%s: all audio devices disconnected\n", __func__);
852 }
853
Hemant Kumar0ef9fbb2016-01-28 11:41:42 -0800854 wake_up(&dev->disconnect_wq);
855}
856
Hemant Kumara4f61012016-10-13 15:41:55 -0700857/* maps audio format received over QMI to asound.h based pcm format */
Hemant Kumar89fa7b92016-10-27 19:56:31 -0700858static int map_pcm_format(unsigned int fmt_received)
Hemant Kumara4f61012016-10-13 15:41:55 -0700859{
860 switch (fmt_received) {
861 case USB_QMI_PCM_FORMAT_S8:
862 return SNDRV_PCM_FORMAT_S8;
863 case USB_QMI_PCM_FORMAT_U8:
864 return SNDRV_PCM_FORMAT_U8;
865 case USB_QMI_PCM_FORMAT_S16_LE:
866 return SNDRV_PCM_FORMAT_S16_LE;
867 case USB_QMI_PCM_FORMAT_S16_BE:
868 return SNDRV_PCM_FORMAT_S16_BE;
869 case USB_QMI_PCM_FORMAT_U16_LE:
870 return SNDRV_PCM_FORMAT_U16_LE;
871 case USB_QMI_PCM_FORMAT_U16_BE:
872 return SNDRV_PCM_FORMAT_U16_BE;
873 case USB_QMI_PCM_FORMAT_S24_LE:
874 return SNDRV_PCM_FORMAT_S24_LE;
875 case USB_QMI_PCM_FORMAT_S24_BE:
876 return SNDRV_PCM_FORMAT_S24_BE;
877 case USB_QMI_PCM_FORMAT_U24_LE:
878 return SNDRV_PCM_FORMAT_U24_LE;
879 case USB_QMI_PCM_FORMAT_U24_BE:
880 return SNDRV_PCM_FORMAT_U24_BE;
881 case USB_QMI_PCM_FORMAT_S24_3LE:
882 return SNDRV_PCM_FORMAT_S24_3LE;
883 case USB_QMI_PCM_FORMAT_S24_3BE:
884 return SNDRV_PCM_FORMAT_S24_3BE;
885 case USB_QMI_PCM_FORMAT_U24_3LE:
886 return SNDRV_PCM_FORMAT_U24_3LE;
887 case USB_QMI_PCM_FORMAT_U24_3BE:
888 return SNDRV_PCM_FORMAT_U24_3BE;
889 case USB_QMI_PCM_FORMAT_S32_LE:
890 return SNDRV_PCM_FORMAT_S32_LE;
891 case USB_QMI_PCM_FORMAT_S32_BE:
892 return SNDRV_PCM_FORMAT_S32_BE;
893 case USB_QMI_PCM_FORMAT_U32_LE:
894 return SNDRV_PCM_FORMAT_U32_LE;
895 case USB_QMI_PCM_FORMAT_U32_BE:
896 return SNDRV_PCM_FORMAT_U32_BE;
897 default:
898 return -EINVAL;
899 }
900}
901
Hemant Kumarebbe6262017-01-10 19:26:40 -0800902static int info_idx_from_ifnum(int card_num, int intf_num, bool enable)
903{
904 int i;
905
906 /*
907 * default index 0 is used when info is allocated upon
908 * first enable audio stream req for a pcm device
909 */
910 if (enable && !uadev[card_num].info)
911 return 0;
912
913 for (i = 0; i < uadev[card_num].num_intf; i++) {
914 if (enable && !uadev[card_num].info[i].in_use)
915 return i;
916 else if (!enable &&
917 uadev[card_num].info[i].intf_num == intf_num)
918 return i;
919 }
920
921 return -EINVAL;
922}
923
Hemant Kumar0ef9fbb2016-01-28 11:41:42 -0800924static int handle_uaudio_stream_req(void *req_h, void *req)
925{
926 struct qmi_uaudio_stream_req_msg_v01 *req_msg;
Hemant Kumaraa2fa3c2016-07-18 16:26:48 -0700927 struct qmi_uaudio_stream_resp_msg_v01 resp = {{0}, 0};
Hemant Kumar0ef9fbb2016-01-28 11:41:42 -0800928 struct snd_usb_substream *subs;
929 struct snd_usb_audio *chip = NULL;
930 struct uaudio_qmi_svc *svc = uaudio_svc;
Hemant Kumard2a54502016-03-22 16:35:16 -0700931 struct intf_info *info;
Hemant Kumara4f61012016-10-13 15:41:55 -0700932 int pcm_format;
Hemant Kumar0ef9fbb2016-01-28 11:41:42 -0800933 u8 pcm_card_num, pcm_dev_num, direction;
Hemant Kumarebbe6262017-01-10 19:26:40 -0800934 int info_idx = -EINVAL, ret = 0;
Hemant Kumar0ef9fbb2016-01-28 11:41:42 -0800935
936 req_msg = (struct qmi_uaudio_stream_req_msg_v01 *)req;
937
Hemant Kumaraa2fa3c2016-07-18 16:26:48 -0700938 if (!req_msg->audio_format_valid || !req_msg->bit_rate_valid ||
939 !req_msg->number_of_ch_valid || !req_msg->xfer_buff_size_valid) {
940 pr_err("%s: invalid request msg\n", __func__);
941 ret = -EINVAL;
942 goto response;
943 }
944
Hemant Kumar0ef9fbb2016-01-28 11:41:42 -0800945 direction = req_msg->usb_token & SND_PCM_STREAM_DIRECTION;
946 pcm_dev_num = (req_msg->usb_token & SND_PCM_DEV_NUM_MASK) >> 8;
947 pcm_card_num = (req_msg->usb_token & SND_PCM_CARD_NUM_MASK) >> 16;
948
949 pr_debug("%s:card#:%d dev#:%d dir:%d en:%d fmt:%d rate:%d #ch:%d\n",
950 __func__, pcm_card_num, pcm_dev_num, direction, req_msg->enable,
951 req_msg->audio_format, req_msg->bit_rate,
952 req_msg->number_of_ch);
953
954 if (pcm_card_num >= SNDRV_CARDS) {
955 pr_err("%s: invalid card # %u", __func__, pcm_card_num);
956 ret = -EINVAL;
957 goto response;
958 }
959
Hemant Kumara4f61012016-10-13 15:41:55 -0700960 pcm_format = map_pcm_format(req_msg->audio_format);
961 if (pcm_format == -EINVAL) {
962 pr_err("%s: unsupported pcm format received %d\n",
963 __func__, req_msg->audio_format);
964 ret = -EINVAL;
965 goto response;
966 }
967
Hemant Kumar0ef9fbb2016-01-28 11:41:42 -0800968 subs = find_snd_usb_substream(pcm_card_num, pcm_dev_num, direction,
969 &chip, uaudio_disconnect_cb);
970 if (!subs || !chip || atomic_read(&chip->shutdown)) {
971 pr_err("%s: can't find substream for card# %u, dev# %u dir%u\n",
972 __func__, pcm_card_num, pcm_dev_num, direction);
973 ret = -ENODEV;
974 goto response;
975 }
976
977 mutex_lock(&chip->dev_lock);
Hemant Kumarebbe6262017-01-10 19:26:40 -0800978 info_idx = info_idx_from_ifnum(pcm_card_num, subs->interface,
979 req_msg->enable);
Hemant Kumar0ef9fbb2016-01-28 11:41:42 -0800980 if (atomic_read(&chip->shutdown) || !subs->stream || !subs->stream->pcm
981 || !subs->stream->chip) {
982 ret = -ENODEV;
983 mutex_unlock(&chip->dev_lock);
984 goto response;
985 }
986
Hemant Kumarebbe6262017-01-10 19:26:40 -0800987 if (req_msg->enable) {
988 if (info_idx < 0) {
989 pr_err("%s interface# %d already in use card# %d\n",
990 __func__, subs->interface, pcm_card_num);
991 ret = -EBUSY;
992 mutex_unlock(&chip->dev_lock);
993 goto response;
994 }
995 }
996
Hemant Kumara4f61012016-10-13 15:41:55 -0700997 subs->pcm_format = pcm_format;
Hemant Kumar0ef9fbb2016-01-28 11:41:42 -0800998 subs->channels = req_msg->number_of_ch;
999 subs->cur_rate = req_msg->bit_rate;
Hemant Kumare1578ed2016-12-14 13:19:40 -08001000 uadev[pcm_card_num].ctrl_intf = chip->ctrl_intf;
Hemant Kumar0ef9fbb2016-01-28 11:41:42 -08001001
1002 ret = snd_usb_enable_audio_stream(subs, req_msg->enable);
1003
1004 if (!ret && req_msg->enable)
Hemant Kumarebbe6262017-01-10 19:26:40 -08001005 ret = prepare_qmi_response(subs, req_msg, &resp, info_idx);
Hemant Kumar0ef9fbb2016-01-28 11:41:42 -08001006
1007 mutex_unlock(&chip->dev_lock);
1008
1009response:
1010 if (!req_msg->enable && ret != -EINVAL) {
Hemant Kumarebbe6262017-01-10 19:26:40 -08001011 if (info_idx >= 0) {
Hemant Kumard2a54502016-03-22 16:35:16 -07001012 mutex_lock(&chip->dev_lock);
Hemant Kumarebbe6262017-01-10 19:26:40 -08001013 info = &uadev[pcm_card_num].info[info_idx];
Hemant Kumar89fa7b92016-10-27 19:56:31 -07001014 uaudio_dev_intf_cleanup(uadev[pcm_card_num].udev, info);
Hemant Kumard2a54502016-03-22 16:35:16 -07001015 pr_debug("%s:release resources: intf# %d card# %d\n",
Hemant Kumarebbe6262017-01-10 19:26:40 -08001016 __func__, subs->interface, pcm_card_num);
Hemant Kumard2a54502016-03-22 16:35:16 -07001017 mutex_unlock(&chip->dev_lock);
1018 }
Hemant Kumar0ef9fbb2016-01-28 11:41:42 -08001019 if (atomic_read(&uadev[pcm_card_num].in_use))
1020 kref_put(&uadev[pcm_card_num].kref,
1021 uaudio_dev_release);
1022 }
1023
Hemant Kumaraa2fa3c2016-07-18 16:26:48 -07001024 resp.usb_token = req_msg->usb_token;
1025 resp.usb_token_valid = 1;
1026 resp.internal_status = ret;
1027 resp.internal_status_valid = 1;
1028 resp.status = ret ? USB_AUDIO_STREAM_REQ_FAILURE_V01 : ret;
1029 resp.status_valid = 1;
Hemant Kumar0ef9fbb2016-01-28 11:41:42 -08001030 ret = qmi_send_resp_from_cb(svc->uaudio_svc_hdl, svc->curr_conn, req_h,
1031 &uaudio_stream_resp_desc, &resp, sizeof(resp));
1032
1033 svc->t_resp_sent = ktime_get();
1034
1035 pr_debug("%s: t_resp sent - t_req recvd (in ms) %lld\n", __func__,
1036 ktime_to_ms(ktime_sub(svc->t_resp_sent, svc->t_request_recvd)));
1037
1038 return ret;
1039}
1040
1041static int uaudio_qmi_svc_connect_cb(struct qmi_handle *handle,
1042 void *conn_h)
1043{
1044 struct uaudio_qmi_svc *svc = uaudio_svc;
1045
1046 if (svc->uaudio_svc_hdl != handle || !conn_h) {
1047 pr_err("%s: handle mismatch\n", __func__);
1048 return -EINVAL;
1049 }
1050 if (svc->curr_conn) {
1051 pr_err("%s: Service is busy\n", __func__);
1052 return -ECONNREFUSED;
1053 }
1054 svc->curr_conn = conn_h;
1055 return 0;
1056}
1057
Hemant Kumar89fa7b92016-10-27 19:56:31 -07001058static void uaudio_qmi_disconnect_work(struct work_struct *w)
1059{
1060 struct intf_info *info;
1061 int idx, if_idx;
1062 struct snd_usb_substream *subs;
1063 struct snd_usb_audio *chip = NULL;
1064
1065 /* find all active intf for set alt 0 and cleanup usb audio dev */
1066 for (idx = 0; idx < SNDRV_CARDS; idx++) {
1067 if (!atomic_read(&uadev[idx].in_use))
1068 continue;
1069
1070 for (if_idx = 0; if_idx < uadev[idx].num_intf; if_idx++) {
1071 if (!uadev[idx].info || !uadev[idx].info[if_idx].in_use)
1072 continue;
1073 info = &uadev[idx].info[if_idx];
1074 subs = find_snd_usb_substream(info->pcm_card_num,
1075 info->pcm_dev_num,
1076 info->direction,
1077 &chip,
1078 uaudio_disconnect_cb);
1079 if (!subs || !chip || atomic_read(&chip->shutdown)) {
1080 pr_debug("%s:no subs for c#%u, dev#%u dir%u\n",
1081 __func__, info->pcm_card_num,
1082 info->pcm_dev_num,
1083 info->direction);
1084 continue;
1085 }
1086 snd_usb_enable_audio_stream(subs, 0);
1087 }
1088 atomic_set(&uadev[idx].in_use, 0);
1089 mutex_lock(&chip->dev_lock);
1090 uaudio_dev_cleanup(&uadev[idx]);
1091 mutex_unlock(&chip->dev_lock);
1092 }
1093}
1094
Hemant Kumar0ef9fbb2016-01-28 11:41:42 -08001095static int uaudio_qmi_svc_disconnect_cb(struct qmi_handle *handle,
1096 void *conn_h)
1097{
1098 struct uaudio_qmi_svc *svc = uaudio_svc;
1099
1100 if (svc->uaudio_svc_hdl != handle || svc->curr_conn != conn_h) {
1101 pr_err("%s: handle mismatch\n", __func__);
1102 return -EINVAL;
1103 }
1104
1105 svc->curr_conn = NULL;
Hemant Kumar89fa7b92016-10-27 19:56:31 -07001106 queue_work(svc->uaudio_wq, &svc->qmi_disconnect_work);
1107
Hemant Kumar0ef9fbb2016-01-28 11:41:42 -08001108 return 0;
1109}
1110
1111static int uaudio_qmi_svc_req_cb(struct qmi_handle *handle, void *conn_h,
1112 void *req_h, unsigned int msg_id, void *req)
1113{
1114 int ret;
1115 struct uaudio_qmi_svc *svc = uaudio_svc;
1116
1117 if (svc->uaudio_svc_hdl != handle || svc->curr_conn != conn_h) {
1118 pr_err("%s: handle mismatch\n", __func__);
1119 return -EINVAL;
1120 }
1121
1122 switch (msg_id) {
1123 case QMI_UAUDIO_STREAM_REQ_V01:
1124 ret = handle_uaudio_stream_req(req_h, req);
1125 break;
1126
1127 default:
1128 ret = -ENOTSUPP;
1129 break;
1130 }
1131 return ret;
1132}
1133
1134static int uaudio_qmi_svc_req_desc_cb(unsigned int msg_id,
1135 struct msg_desc **req_desc)
1136{
1137 int ret;
1138
1139 pr_debug("%s: msg_id %d\n", __func__, msg_id);
1140
1141 switch (msg_id) {
1142 case QMI_UAUDIO_STREAM_REQ_V01:
1143 *req_desc = &uaudio_stream_req_desc;
1144 ret = sizeof(struct qmi_uaudio_stream_req_msg_v01);
1145 break;
1146
1147 default:
1148 ret = -ENOTSUPP;
1149 break;
1150 }
1151 return ret;
1152}
1153
1154static void uaudio_qmi_svc_recv_msg(struct work_struct *w)
1155{
1156 int ret;
1157 struct uaudio_qmi_svc *svc = container_of(w, struct uaudio_qmi_svc,
1158 recv_msg_work);
1159
1160 do {
1161 pr_debug("%s: Notified about a Receive Event", __func__);
1162 } while ((ret = qmi_recv_msg(svc->uaudio_svc_hdl)) == 0);
1163
1164 if (ret != -ENOMSG)
1165 pr_err("%s: Error receiving message\n", __func__);
1166}
1167
1168static void uaudio_qmi_svc_ntfy(struct qmi_handle *handle,
1169 enum qmi_event_type event, void *priv)
1170{
1171 struct uaudio_qmi_svc *svc = uaudio_svc;
1172
1173 pr_debug("%s: event %d", __func__, event);
1174
1175 svc->t_request_recvd = ktime_get();
1176
1177 switch (event) {
1178 case QMI_RECV_MSG:
1179 queue_work(svc->uaudio_wq, &svc->recv_msg_work);
1180 break;
1181 default:
1182 break;
1183 }
1184}
1185
1186static struct qmi_svc_ops_options uaudio_svc_ops_options = {
1187 .version = 1,
1188 .service_id = UAUDIO_STREAM_SERVICE_ID_V01,
1189 .service_vers = UAUDIO_STREAM_SERVICE_VERS_V01,
1190 .connect_cb = uaudio_qmi_svc_connect_cb,
1191 .disconnect_cb = uaudio_qmi_svc_disconnect_cb,
1192 .req_desc_cb = uaudio_qmi_svc_req_desc_cb,
1193 .req_cb = uaudio_qmi_svc_req_cb,
1194};
1195
Hemant Kumard2a54502016-03-22 16:35:16 -07001196static int uaudio_qmi_plat_probe(struct platform_device *pdev)
1197{
1198 int ret;
1199 struct device_node *node = pdev->dev.of_node;
1200
1201 uaudio_qdev = devm_kzalloc(&pdev->dev, sizeof(struct uaudio_qmi_dev),
1202 GFP_KERNEL);
1203 if (!uaudio_qdev)
1204 return -ENOMEM;
1205
1206 uaudio_qdev->dev = &pdev->dev;
1207
1208 ret = of_property_read_u32(node, "qcom,usb-audio-stream-id",
1209 &uaudio_qdev->sid);
1210 if (ret) {
1211 dev_err(&pdev->dev, "failed to read sid.\n");
1212 return -ENODEV;
1213 }
1214
1215 ret = of_property_read_u32(node, "qcom,usb-audio-intr-num",
1216 &uaudio_qdev->intr_num);
1217 if (ret) {
1218 dev_err(&pdev->dev, "failed to read intr num.\n");
1219 return -ENODEV;
1220 }
1221
1222 uaudio_qdev->domain = iommu_domain_alloc(pdev->dev.bus);
Hemant Kumara2a80912016-08-22 19:31:35 -07001223 if (!uaudio_qdev->domain) {
1224 dev_err(&pdev->dev, "failed to allocate iommu domain\n");
Hemant Kumard2a54502016-03-22 16:35:16 -07001225 return -ENODEV;
1226 }
1227
1228 /* attach to external processor iommu */
1229 ret = iommu_attach_device(uaudio_qdev->domain, &pdev->dev);
1230 if (ret) {
1231 dev_err(&pdev->dev, "failed to attach device ret = %d\n", ret);
1232 goto free_domain;
1233 }
1234
Hemant Kumar81156ed2017-09-22 12:34:52 -07001235 /* initialize xfer ring and xfer buf iova list */
Hemant Kumard2a54502016-03-22 16:35:16 -07001236 INIT_LIST_HEAD(&uaudio_qdev->xfer_ring_list);
1237 uaudio_qdev->curr_xfer_ring_iova = IOVA_XFER_RING_BASE;
1238 uaudio_qdev->xfer_ring_iova_size =
1239 IOVA_XFER_RING_MAX - IOVA_XFER_RING_BASE;
1240
1241 INIT_LIST_HEAD(&uaudio_qdev->xfer_buf_list);
1242 uaudio_qdev->curr_xfer_buf_iova = IOVA_XFER_BUF_BASE;
1243 uaudio_qdev->xfer_buf_iova_size =
1244 IOVA_XFER_BUF_MAX - IOVA_XFER_BUF_BASE;
1245
1246 return 0;
1247
1248free_domain:
1249 iommu_domain_free(uaudio_qdev->domain);
1250 return ret;
1251}
1252
1253static int uaudio_qmi_plat_remove(struct platform_device *pdev)
1254{
1255 iommu_detach_device(uaudio_qdev->domain, &pdev->dev);
1256 iommu_domain_free(uaudio_qdev->domain);
1257 uaudio_qdev->domain = NULL;
1258
1259 return 0;
1260}
1261
1262static const struct of_device_id of_uaudio_matach[] = {
1263 {
1264 .compatible = "qcom,usb-audio-qmi-dev",
1265 },
1266 { },
1267};
1268MODULE_DEVICE_TABLE(of, of_uaudio_matach);
1269
1270static struct platform_driver uaudio_qmi_driver = {
1271 .probe = uaudio_qmi_plat_probe,
1272 .remove = uaudio_qmi_plat_remove,
1273 .driver = {
1274 .name = "uaudio-qmi",
1275 .of_match_table = of_uaudio_matach,
1276 },
1277};
1278
1279static int uaudio_qmi_svc_init(void)
Hemant Kumar0ef9fbb2016-01-28 11:41:42 -08001280{
1281 int ret;
1282 struct uaudio_qmi_svc *svc;
1283
1284 svc = kzalloc(sizeof(struct uaudio_qmi_svc), GFP_KERNEL);
1285 if (!svc)
1286 return -ENOMEM;
1287
1288 svc->uaudio_wq = create_singlethread_workqueue("uaudio_svc");
1289 if (!svc->uaudio_wq) {
1290 ret = -ENOMEM;
1291 goto free_svc;
1292 }
1293
1294 svc->uaudio_svc_hdl = qmi_handle_create(uaudio_qmi_svc_ntfy, NULL);
1295 if (!svc->uaudio_svc_hdl) {
1296 pr_err("%s: Error creating svc_hdl\n", __func__);
1297 ret = -EFAULT;
1298 goto destroy_uaudio_wq;
1299 }
1300
1301 ret = qmi_svc_register(svc->uaudio_svc_hdl, &uaudio_svc_ops_options);
1302 if (ret < 0) {
1303 pr_err("%s:Error registering uaudio svc %d\n", __func__, ret);
1304 goto destroy_svc_handle;
1305 }
1306
1307 INIT_WORK(&svc->recv_msg_work, uaudio_qmi_svc_recv_msg);
Hemant Kumar89fa7b92016-10-27 19:56:31 -07001308 INIT_WORK(&svc->qmi_disconnect_work, uaudio_qmi_disconnect_work);
Hemant Kumar0ef9fbb2016-01-28 11:41:42 -08001309
1310 uaudio_svc = svc;
1311
1312 return 0;
1313
1314destroy_svc_handle:
1315 qmi_handle_destroy(svc->uaudio_svc_hdl);
1316destroy_uaudio_wq:
1317 destroy_workqueue(svc->uaudio_wq);
1318free_svc:
1319 kfree(svc);
1320 return ret;
1321}
1322
Hemant Kumard2a54502016-03-22 16:35:16 -07001323static void uaudio_qmi_svc_exit(void)
Hemant Kumar0ef9fbb2016-01-28 11:41:42 -08001324{
1325 struct uaudio_qmi_svc *svc = uaudio_svc;
1326
1327 qmi_svc_unregister(svc->uaudio_svc_hdl);
1328 flush_workqueue(svc->uaudio_wq);
1329 qmi_handle_destroy(svc->uaudio_svc_hdl);
1330 destroy_workqueue(svc->uaudio_wq);
1331 kfree(svc);
1332 uaudio_svc = NULL;
1333}
1334
Hemant Kumard2a54502016-03-22 16:35:16 -07001335static int __init uaudio_qmi_plat_init(void)
1336{
1337 int ret;
1338
1339 ret = platform_driver_register(&uaudio_qmi_driver);
1340 if (ret)
1341 return ret;
1342
1343 return uaudio_qmi_svc_init();
1344}
1345
1346static void __exit uaudio_qmi_plat_exit(void)
1347{
1348 uaudio_qmi_svc_exit();
1349 platform_driver_unregister(&uaudio_qmi_driver);
1350}
1351
1352module_init(uaudio_qmi_plat_init);
1353module_exit(uaudio_qmi_plat_exit);
Hemant Kumar0ef9fbb2016-01-28 11:41:42 -08001354
1355MODULE_DESCRIPTION("USB AUDIO QMI Service Driver");
1356MODULE_LICENSE("GPL v2");