blob: 801508c46c462ee116cbf9da7973e916db0fae42 [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
48#define IOVA_DCBA_BASE 0x2000
49#define IOVA_XFER_RING_BASE (IOVA_DCBA_BASE + PAGE_SIZE * (SNDRV_CARDS + 1))
50#define IOVA_XFER_BUF_BASE (IOVA_XFER_RING_BASE + PAGE_SIZE * SNDRV_CARDS * 32)
51#define IOVA_XFER_RING_MAX (IOVA_XFER_BUF_BASE - PAGE_SIZE)
52#define IOVA_XFER_BUF_MAX (0xfffff000 - PAGE_SIZE)
53
Hemant Kumarbeb99fd2016-10-10 16:49:34 -070054#define MAX_XFER_BUFF_LEN (24 * PAGE_SIZE)
Hemant Kumard2a54502016-03-22 16:35:16 -070055
56struct iova_info {
57 struct list_head list;
58 unsigned long start_iova;
59 size_t size;
60 bool in_use;
61};
62
63struct intf_info {
64 unsigned long data_xfer_ring_va;
65 size_t data_xfer_ring_size;
66 unsigned long sync_xfer_ring_va;
67 size_t sync_xfer_ring_size;
68 unsigned long xfer_buf_va;
69 size_t xfer_buf_size;
70 phys_addr_t xfer_buf_pa;
71 u8 *xfer_buf;
Hemant Kumarebbe6262017-01-10 19:26:40 -080072 u8 intf_num;
Hemant Kumar89fa7b92016-10-27 19:56:31 -070073 u8 pcm_card_num;
74 u8 pcm_dev_num;
75 u8 direction;
Hemant Kumard2a54502016-03-22 16:35:16 -070076 bool in_use;
77};
78
Hemant Kumar0ef9fbb2016-01-28 11:41:42 -080079struct uaudio_dev {
Hemant Kumard2a54502016-03-22 16:35:16 -070080 struct usb_device *udev;
Hemant Kumare1578ed2016-12-14 13:19:40 -080081 /* audio control interface */
82 struct usb_host_interface *ctrl_intf;
Hemant Kumard2a54502016-03-22 16:35:16 -070083 unsigned int card_num;
Hemant Kumar0ef9fbb2016-01-28 11:41:42 -080084 atomic_t in_use;
85 struct kref kref;
Hemant Kumard2a54502016-03-22 16:35:16 -070086 unsigned long dcba_iova;
87 size_t dcba_size;
Hemant Kumar0ef9fbb2016-01-28 11:41:42 -080088 wait_queue_head_t disconnect_wq;
Hemant Kumard2a54502016-03-22 16:35:16 -070089
90 /* interface specific */
91 int num_intf;
92 struct intf_info *info;
Hemant Kumar0ef9fbb2016-01-28 11:41:42 -080093};
94
95static struct uaudio_dev uadev[SNDRV_CARDS];
96
Hemant Kumard2a54502016-03-22 16:35:16 -070097struct uaudio_qmi_dev {
98 struct device *dev;
99 u32 sid;
100 u32 intr_num;
101 struct iommu_domain *domain;
102
103 /* list to keep track of available iova */
104 struct list_head dcba_list;
105 size_t dcba_iova_size;
106 unsigned long curr_dcba_iova;
107 struct list_head xfer_ring_list;
108 size_t xfer_ring_iova_size;
109 unsigned long curr_xfer_ring_iova;
110 struct list_head xfer_buf_list;
111 size_t xfer_buf_iova_size;
112 unsigned long curr_xfer_buf_iova;
113 /* bit fields representing pcm card enabled */
114 unsigned long card_slot;
115 /* cache event ring phys addr */
116 u64 er_phys_addr;
117};
118
119static struct uaudio_qmi_dev *uaudio_qdev;
120
Hemant Kumar0ef9fbb2016-01-28 11:41:42 -0800121struct uaudio_qmi_svc {
122 struct qmi_handle *uaudio_svc_hdl;
123 void *curr_conn;
124 struct work_struct recv_msg_work;
Hemant Kumar89fa7b92016-10-27 19:56:31 -0700125 struct work_struct qmi_disconnect_work;
Hemant Kumar0ef9fbb2016-01-28 11:41:42 -0800126 struct workqueue_struct *uaudio_wq;
127 ktime_t t_request_recvd;
128 ktime_t t_resp_sent;
129};
130
131static struct uaudio_qmi_svc *uaudio_svc;
132
133static struct msg_desc uaudio_stream_req_desc = {
134 .max_msg_len = QMI_UAUDIO_STREAM_REQ_MSG_V01_MAX_MSG_LEN,
135 .msg_id = QMI_UAUDIO_STREAM_REQ_V01,
136 .ei_array = qmi_uaudio_stream_req_msg_v01_ei,
137};
138
139static struct msg_desc uaudio_stream_resp_desc = {
140 .max_msg_len = QMI_UAUDIO_STREAM_RESP_MSG_V01_MAX_MSG_LEN,
141 .msg_id = QMI_UAUDIO_STREAM_RESP_V01,
142 .ei_array = qmi_uaudio_stream_resp_msg_v01_ei,
143};
144
Vamsi Krishna Samavedam1e634532016-09-13 14:09:37 -0700145static struct msg_desc uaudio_stream_ind_desc = {
146 .max_msg_len = QMI_UAUDIO_STREAM_IND_MSG_V01_MAX_MSG_LEN,
147 .msg_id = QMI_UADUIO_STREAM_IND_V01,
148 .ei_array = qmi_uaudio_stream_ind_msg_v01_ei,
149};
150
Hemant Kumard2a54502016-03-22 16:35:16 -0700151enum mem_type {
152 MEM_EVENT_RING,
153 MEM_DCBA,
154 MEM_XFER_RING,
155 MEM_XFER_BUF,
156};
157
Hemant Kumara4f61012016-10-13 15:41:55 -0700158enum usb_qmi_audio_format {
159 USB_QMI_PCM_FORMAT_S8 = 0,
160 USB_QMI_PCM_FORMAT_U8,
161 USB_QMI_PCM_FORMAT_S16_LE,
162 USB_QMI_PCM_FORMAT_S16_BE,
163 USB_QMI_PCM_FORMAT_U16_LE,
164 USB_QMI_PCM_FORMAT_U16_BE,
165 USB_QMI_PCM_FORMAT_S24_LE,
166 USB_QMI_PCM_FORMAT_S24_BE,
167 USB_QMI_PCM_FORMAT_U24_LE,
168 USB_QMI_PCM_FORMAT_U24_BE,
169 USB_QMI_PCM_FORMAT_S24_3LE,
170 USB_QMI_PCM_FORMAT_S24_3BE,
171 USB_QMI_PCM_FORMAT_U24_3LE,
172 USB_QMI_PCM_FORMAT_U24_3BE,
173 USB_QMI_PCM_FORMAT_S32_LE,
174 USB_QMI_PCM_FORMAT_S32_BE,
175 USB_QMI_PCM_FORMAT_U32_LE,
176 USB_QMI_PCM_FORMAT_U32_BE,
177};
178
Hemant Kumard2a54502016-03-22 16:35:16 -0700179static unsigned long uaudio_get_iova(unsigned long *curr_iova,
180 size_t *curr_iova_size, struct list_head *head, size_t size)
Hemant Kumar0ef9fbb2016-01-28 11:41:42 -0800181{
Hemant Kumard2a54502016-03-22 16:35:16 -0700182 struct iova_info *info, *new_info = NULL;
183 struct list_head *curr_head;
184 unsigned long va = 0;
185 size_t tmp_size = size;
186 bool found = false;
187
188 if (size % PAGE_SIZE) {
189 pr_err("%s: size %zu is not page size multiple\n", __func__,
190 size);
191 goto done;
192 }
193
194 if (size > *curr_iova_size) {
195 pr_err("%s: size %zu > curr size %zu\n", __func__, size,
196 *curr_iova_size);
197 goto done;
198 }
199 if (*curr_iova_size == 0) {
200 pr_err("%s: iova mapping is full\n", __func__);
201 goto done;
202 }
203
204 list_for_each_entry(info, head, list) {
205 /* exact size iova_info */
206 if (!info->in_use && info->size == size) {
207 info->in_use = true;
208 va = info->start_iova;
209 *curr_iova_size -= size;
210 found = true;
211 pr_debug("%s: exact size :%zu found\n", __func__, size);
212 goto done;
213 } else if (!info->in_use && tmp_size >= info->size) {
214 if (!new_info)
215 new_info = info;
216 pr_debug("%s: partial size: %zu found\n", __func__,
217 info->size);
218 tmp_size -= info->size;
219 if (tmp_size)
220 continue;
221
222 va = new_info->start_iova;
223 for (curr_head = &new_info->list; curr_head !=
224 &info->list; curr_head = curr_head->next) {
225 new_info = list_entry(curr_head, struct
226 iova_info, list);
227 new_info->in_use = true;
228 }
229 info->in_use = true;
230 *curr_iova_size -= size;
231 found = true;
232 goto done;
233 } else {
234 /* iova region in use */
235 new_info = NULL;
236 tmp_size = size;
237 }
238 }
239
240 info = kzalloc(sizeof(struct iova_info), GFP_KERNEL);
241 if (!info) {
242 va = 0;
243 goto done;
244 }
245
246 va = info->start_iova = *curr_iova;
247 info->size = size;
248 info->in_use = true;
249 *curr_iova += size;
250 *curr_iova_size -= size;
251 found = true;
252 list_add_tail(&info->list, head);
253
254done:
255 if (!found)
256 pr_err("%s: unable to find %zu size iova\n", __func__, size);
257 else
258 pr_debug("%s: va:%lu curr_iova:%lu curr_iova_size:%zu\n",
259 __func__, va, *curr_iova, *curr_iova_size);
260
261 return va;
262}
263
264static unsigned long uaudio_iommu_map(enum mem_type mtype, phys_addr_t pa,
265 size_t size)
266{
267 unsigned long va = 0;
268 bool map = true;
269 int ret;
270
271 switch (mtype) {
272 case MEM_EVENT_RING:
273 va = IOVA_BASE;
274 /* er already mapped */
275 if (uaudio_qdev->er_phys_addr == pa)
276 map = false;
277 break;
278 case MEM_DCBA:
279 va = uaudio_get_iova(&uaudio_qdev->curr_dcba_iova,
280 &uaudio_qdev->dcba_iova_size, &uaudio_qdev->dcba_list, size);
281 break;
282 case MEM_XFER_RING:
283 va = uaudio_get_iova(&uaudio_qdev->curr_xfer_ring_iova,
284 &uaudio_qdev->xfer_ring_iova_size, &uaudio_qdev->xfer_ring_list,
285 size);
286 break;
287 case MEM_XFER_BUF:
288 va = uaudio_get_iova(&uaudio_qdev->curr_xfer_buf_iova,
289 &uaudio_qdev->xfer_buf_iova_size, &uaudio_qdev->xfer_buf_list,
290 size);
291 break;
292 default:
293 pr_err("%s: unknown mem type %d\n", __func__, mtype);
294 }
295
296 if (!va)
297 map = false;
298
299 if (!map)
300 goto done;
301
302 pr_debug("%s: map pa %pa to iova %lu for memtype %d\n", __func__, &pa,
303 va, mtype);
304 ret = iommu_map(uaudio_qdev->domain, va, pa, size,
305 IOMMU_READ | IOMMU_WRITE | IOMMU_MMIO);
306 if (ret)
307 pr_err("%s:failed to map pa:%pa iova:%lu memtype:%d ret:%d\n",
308 __func__, &pa, va, mtype, ret);
309done:
310 return va;
311}
312
313static void uaudio_put_iova(unsigned long va, size_t size, struct list_head
314 *head, size_t *curr_iova_size)
315{
316 struct iova_info *info;
317 size_t tmp_size = size;
318 bool found = false;
319
320 list_for_each_entry(info, head, list) {
321 if (info->start_iova == va) {
322 if (!info->in_use) {
323 pr_err("%s: va %lu is not in use\n", __func__,
324 va);
325 return;
326 }
327 found = true;
328 info->in_use = false;
329 if (info->size == size)
330 goto done;
331 }
332
333 if (found && tmp_size >= info->size) {
334 info->in_use = false;
335 tmp_size -= info->size;
336 if (!tmp_size)
337 goto done;
338 }
339 }
340
341 if (!found) {
342 pr_err("%s: unable to find the va %lu\n", __func__, va);
343 return;
344 }
345done:
346 *curr_iova_size += size;
347 pr_debug("%s: curr_iova_size %zu\n", __func__, *curr_iova_size);
348}
349
350static void uaudio_iommu_unmap(enum mem_type mtype, unsigned long va,
351 size_t size)
352{
353 size_t umap_size;
354 bool unmap = true;
355
356 if (!va || !size)
357 return;
358
359 switch (mtype) {
360 case MEM_EVENT_RING:
361 if (uaudio_qdev->er_phys_addr)
362 uaudio_qdev->er_phys_addr = 0;
363 else
364 unmap = false;
365 break;
366 case MEM_DCBA:
367 uaudio_put_iova(va, size, &uaudio_qdev->dcba_list,
368 &uaudio_qdev->dcba_iova_size);
369 break;
370 case MEM_XFER_RING:
371 uaudio_put_iova(va, size, &uaudio_qdev->xfer_ring_list,
372 &uaudio_qdev->xfer_ring_iova_size);
373 break;
374 case MEM_XFER_BUF:
375 uaudio_put_iova(va, size, &uaudio_qdev->xfer_buf_list,
376 &uaudio_qdev->xfer_buf_iova_size);
377 break;
378 default:
379 pr_err("%s: unknown mem type %d\n", __func__, mtype);
380 unmap = false;
381 }
382
383 if (!unmap)
384 return;
385
386 pr_debug("%s: unmap iova %lu for memtype %d\n", __func__, va, mtype);
387
388 umap_size = iommu_unmap(uaudio_qdev->domain, va, size);
389 if (umap_size != size)
390 pr_err("%s: unmapped size %zu for iova %lu\n", __func__,
391 umap_size, va);
392}
393
394static int prepare_qmi_response(struct snd_usb_substream *subs,
Hemant Kumarebbe6262017-01-10 19:26:40 -0800395 struct qmi_uaudio_stream_req_msg_v01 *req_msg,
396 struct qmi_uaudio_stream_resp_msg_v01 *resp, int info_idx)
Hemant Kumard2a54502016-03-22 16:35:16 -0700397{
Hemant Kumar0ef9fbb2016-01-28 11:41:42 -0800398 struct usb_interface *iface;
399 struct usb_host_interface *alts;
400 struct usb_interface_descriptor *altsd;
401 struct usb_host_endpoint *ep;
402 struct uac_format_type_i_continuous_descriptor *fmt;
403 struct uac_format_type_i_discrete_descriptor *fmt_v1;
404 struct uac_format_type_i_ext_descriptor *fmt_v2;
405 struct uac1_as_header_descriptor *as;
Hemant Kumarebbe6262017-01-10 19:26:40 -0800406 int ret = -ENODEV;
407 int protocol, card_num, pcm_dev_num;
Hemant Kumare1578ed2016-12-14 13:19:40 -0800408 void *hdr_ptr;
Hemant Kumard2a54502016-03-22 16:35:16 -0700409 u8 *xfer_buf;
Hemant Kumarebbe6262017-01-10 19:26:40 -0800410 u32 len, mult, remainder, xfer_buf_len;
Hemant Kumard2a54502016-03-22 16:35:16 -0700411 unsigned long va, tr_data_va = 0, tr_sync_va = 0, dcba_va = 0,
412 xfer_buf_va = 0;
413 phys_addr_t xhci_pa, xfer_buf_pa;
Hemant Kumar0ef9fbb2016-01-28 11:41:42 -0800414
415 iface = usb_ifnum_to_if(subs->dev, subs->interface);
416 if (!iface) {
417 pr_err("%s: interface # %d does not exist\n", __func__,
418 subs->interface);
419 goto err;
420 }
421
Hemant Kumarebbe6262017-01-10 19:26:40 -0800422 pcm_dev_num = (req_msg->usb_token & SND_PCM_DEV_NUM_MASK) >> 8;
423 card_num = (req_msg->usb_token & SND_PCM_CARD_NUM_MASK) >> 16;
424 xfer_buf_len = req_msg->xfer_buff_size;
Hemant Kumar89fa7b92016-10-27 19:56:31 -0700425
Hemant Kumar0ef9fbb2016-01-28 11:41:42 -0800426 alts = &iface->altsetting[subs->altset_idx];
427 altsd = get_iface_desc(alts);
428 protocol = altsd->bInterfaceProtocol;
429
430 /* get format type */
Ajay Agarwal2a39f672017-04-11 11:58:28 +0530431 if (protocol != UAC_VERSION_3) {
432 fmt = snd_usb_find_csint_desc(alts->extra, alts->extralen, NULL,
433 UAC_FORMAT_TYPE);
434 if (!fmt) {
435 pr_err("%s: %u:%d : no UAC_FORMAT_TYPE desc\n",
436 __func__, subs->interface, subs->altset_idx);
437 goto err;
438 }
Hemant Kumar0ef9fbb2016-01-28 11:41:42 -0800439 }
440
Hemant Kumare1578ed2016-12-14 13:19:40 -0800441 if (!uadev[card_num].ctrl_intf) {
442 pr_err("%s: audio ctrl intf info not cached\n", __func__);
443 goto err;
444 }
445
Ajay Agarwal2a39f672017-04-11 11:58:28 +0530446 if (protocol != UAC_VERSION_3) {
447 hdr_ptr = snd_usb_find_csint_desc(
448 uadev[card_num].ctrl_intf->extra,
449 uadev[card_num].ctrl_intf->extralen,
450 NULL, UAC_HEADER);
451 if (!hdr_ptr) {
452 pr_err("%s: no UAC_HEADER desc\n", __func__);
453 goto err;
454 }
Hemant Kumare1578ed2016-12-14 13:19:40 -0800455 }
456
Hemant Kumar0ef9fbb2016-01-28 11:41:42 -0800457 if (protocol == UAC_VERSION_1) {
458 as = snd_usb_find_csint_desc(alts->extra, alts->extralen, NULL,
459 UAC_AS_GENERAL);
460 if (!as) {
461 pr_err("%s: %u:%d : no UAC_AS_GENERAL desc\n", __func__,
462 subs->interface, subs->altset_idx);
463 goto err;
464 }
Hemant Kumaraa2fa3c2016-07-18 16:26:48 -0700465 resp->data_path_delay = as->bDelay;
466 resp->data_path_delay_valid = 1;
Hemant Kumar0ef9fbb2016-01-28 11:41:42 -0800467 fmt_v1 = (struct uac_format_type_i_discrete_descriptor *)fmt;
Hemant Kumaraa2fa3c2016-07-18 16:26:48 -0700468 resp->usb_audio_subslot_size = fmt_v1->bSubframeSize;
469 resp->usb_audio_subslot_size_valid = 1;
Hemant Kumare1578ed2016-12-14 13:19:40 -0800470
471 resp->usb_audio_spec_revision =
472 ((struct uac1_ac_header_descriptor *)hdr_ptr)->bcdADC;
473 resp->usb_audio_spec_revision_valid = 1;
Hemant Kumar0ef9fbb2016-01-28 11:41:42 -0800474 } else if (protocol == UAC_VERSION_2) {
475 fmt_v2 = (struct uac_format_type_i_ext_descriptor *)fmt;
Hemant Kumaraa2fa3c2016-07-18 16:26:48 -0700476 resp->usb_audio_subslot_size = fmt_v2->bSubslotSize;
477 resp->usb_audio_subslot_size_valid = 1;
Hemant Kumare1578ed2016-12-14 13:19:40 -0800478
479 resp->usb_audio_spec_revision =
480 ((struct uac2_ac_header_descriptor *)hdr_ptr)->bcdADC;
481 resp->usb_audio_spec_revision_valid = 1;
Ajay Agarwal2a39f672017-04-11 11:58:28 +0530482 } else if (protocol == UAC_VERSION_3) {
483 switch (le16_to_cpu(get_endpoint(alts, 0)->wMaxPacketSize)) {
484 case BADD_MAXPSIZE_SYNC_MONO_16:
485 case BADD_MAXPSIZE_SYNC_STEREO_16:
486 case BADD_MAXPSIZE_ASYNC_MONO_16:
487 case BADD_MAXPSIZE_ASYNC_STEREO_16: {
488 resp->usb_audio_subslot_size = SUBSLOTSIZE_16_BIT;
489 break;
490 }
491
492 case BADD_MAXPSIZE_SYNC_MONO_24:
493 case BADD_MAXPSIZE_SYNC_STEREO_24:
494 case BADD_MAXPSIZE_ASYNC_MONO_24:
495 case BADD_MAXPSIZE_ASYNC_STEREO_24: {
496 resp->usb_audio_subslot_size = SUBSLOTSIZE_24_BIT;
497 break;
498 }
499
500 default:
501 pr_err("%d: %u: Invalid wMaxPacketSize\n",
502 subs->interface, subs->altset_idx);
503 ret = -EINVAL;
504 goto err;
505 }
506 resp->usb_audio_subslot_size_valid = 1;
Hemant Kumar0ef9fbb2016-01-28 11:41:42 -0800507 } else {
508 pr_err("%s: unknown protocol version %x\n", __func__, protocol);
509 goto err;
510 }
511
Hemant Kumar0ef9fbb2016-01-28 11:41:42 -0800512 resp->slot_id = subs->dev->slot_id;
Hemant Kumaraa2fa3c2016-07-18 16:26:48 -0700513 resp->slot_id_valid = 1;
Hemant Kumar0ef9fbb2016-01-28 11:41:42 -0800514
515 memcpy(&resp->std_as_opr_intf_desc, &alts->desc, sizeof(alts->desc));
Hemant Kumaraa2fa3c2016-07-18 16:26:48 -0700516 resp->std_as_opr_intf_desc_valid = 1;
Hemant Kumar0ef9fbb2016-01-28 11:41:42 -0800517
518 ep = usb_pipe_endpoint(subs->dev, subs->data_endpoint->pipe);
519 if (!ep) {
520 pr_err("%s: data ep # %d context is null\n", __func__,
521 subs->data_endpoint->ep_num);
522 goto err;
523 }
524 memcpy(&resp->std_as_data_ep_desc, &ep->desc, sizeof(ep->desc));
Hemant Kumaraa2fa3c2016-07-18 16:26:48 -0700525 resp->std_as_data_ep_desc_valid = 1;
Hemant Kumar0ef9fbb2016-01-28 11:41:42 -0800526
Hemant Kumard2a54502016-03-22 16:35:16 -0700527 xhci_pa = usb_get_xfer_ring_dma_addr(subs->dev, ep);
528 if (!xhci_pa) {
529 pr_err("%s:failed to get data ep ring dma address\n", __func__);
530 goto err;
531 }
532
533 resp->xhci_mem_info.tr_data.pa = xhci_pa;
534
Hemant Kumar0ef9fbb2016-01-28 11:41:42 -0800535 if (subs->sync_endpoint) {
536 ep = usb_pipe_endpoint(subs->dev, subs->sync_endpoint->pipe);
537 if (!ep) {
Hemant Kumar44cefc52016-12-06 18:34:40 -0800538 pr_debug("%s: implicit fb on data ep\n", __func__);
539 goto skip_sync_ep;
Hemant Kumar0ef9fbb2016-01-28 11:41:42 -0800540 }
541 memcpy(&resp->std_as_sync_ep_desc, &ep->desc, sizeof(ep->desc));
Hemant Kumaraa2fa3c2016-07-18 16:26:48 -0700542 resp->std_as_sync_ep_desc_valid = 1;
543
Hemant Kumard2a54502016-03-22 16:35:16 -0700544 xhci_pa = usb_get_xfer_ring_dma_addr(subs->dev, ep);
545 if (!xhci_pa) {
546 pr_err("%s:failed to get sync ep ring dma address\n",
547 __func__);
548 goto err;
549 }
550 resp->xhci_mem_info.tr_sync.pa = xhci_pa;
Hemant Kumar0ef9fbb2016-01-28 11:41:42 -0800551 }
552
Hemant Kumar44cefc52016-12-06 18:34:40 -0800553skip_sync_ep:
Hemant Kumard2a54502016-03-22 16:35:16 -0700554 resp->interrupter_num = uaudio_qdev->intr_num;
Hemant Kumaraa2fa3c2016-07-18 16:26:48 -0700555 resp->interrupter_num_valid = 1;
Hemant Kumard2a54502016-03-22 16:35:16 -0700556
557 /* map xhci data structures PA memory to iova */
558
559 /* event ring */
560 ret = usb_sec_event_ring_setup(subs->dev, resp->interrupter_num);
561 if (ret) {
562 pr_err("%s: failed to setup sec event ring ret %d\n", __func__,
563 ret);
564 goto err;
565 }
566 xhci_pa = usb_get_sec_event_ring_dma_addr(subs->dev,
567 resp->interrupter_num);
568 if (!xhci_pa) {
569 pr_err("%s: failed to get sec event ring dma address\n",
570 __func__);
571 goto err;
572 }
573
574 va = uaudio_iommu_map(MEM_EVENT_RING, xhci_pa, PAGE_SIZE);
575 if (!va)
576 goto err;
577
578 resp->xhci_mem_info.evt_ring.va = PREPEND_SID_TO_IOVA(va,
579 uaudio_qdev->sid);
580 resp->xhci_mem_info.evt_ring.pa = xhci_pa;
581 resp->xhci_mem_info.evt_ring.size = PAGE_SIZE;
582 uaudio_qdev->er_phys_addr = xhci_pa;
583
584 /* dcba */
585 xhci_pa = usb_get_dcba_dma_addr(subs->dev);
586 if (!xhci_pa) {
587 pr_err("%s:failed to get dcba dma address\n", __func__);
588 goto unmap_er;
589 }
590
591 if (!uadev[card_num].dcba_iova) { /* mappped per usb device */
592 va = uaudio_iommu_map(MEM_DCBA, xhci_pa, PAGE_SIZE);
593 if (!va)
594 goto unmap_er;
595
596 uadev[card_num].dcba_iova = va;
597 uadev[card_num].dcba_size = PAGE_SIZE;
598 }
599
600 dcba_va = uadev[card_num].dcba_iova;
601 resp->xhci_mem_info.dcba.va = PREPEND_SID_TO_IOVA(dcba_va,
602 uaudio_qdev->sid);
603 resp->xhci_mem_info.dcba.pa = xhci_pa;
604 resp->xhci_mem_info.dcba.size = PAGE_SIZE;
605
606 /* data transfer ring */
607 xhci_pa = resp->xhci_mem_info.tr_data.pa;
608 va = uaudio_iommu_map(MEM_XFER_RING, xhci_pa, PAGE_SIZE);
609 if (!va)
610 goto unmap_dcba;
611
612 tr_data_va = va;
613 resp->xhci_mem_info.tr_data.va = PREPEND_SID_TO_IOVA(va,
614 uaudio_qdev->sid);
615 resp->xhci_mem_info.tr_data.size = PAGE_SIZE;
616
617 /* sync transfer ring */
618 if (!resp->xhci_mem_info.tr_sync.pa)
619 goto skip_sync;
620
621 xhci_pa = resp->xhci_mem_info.tr_sync.pa;
622 va = uaudio_iommu_map(MEM_XFER_RING, xhci_pa, PAGE_SIZE);
623 if (!va)
624 goto unmap_data;
625
626 tr_sync_va = va;
627 resp->xhci_mem_info.tr_sync.va = PREPEND_SID_TO_IOVA(va,
628 uaudio_qdev->sid);
629 resp->xhci_mem_info.tr_sync.size = PAGE_SIZE;
630
631skip_sync:
632 /* xfer buffer, multiple of 4K only */
633 if (!xfer_buf_len)
634 xfer_buf_len = PAGE_SIZE;
635
636 mult = xfer_buf_len / PAGE_SIZE;
637 remainder = xfer_buf_len % PAGE_SIZE;
638 len = mult * PAGE_SIZE;
639 len += remainder ? PAGE_SIZE : 0;
640
641 if (len > MAX_XFER_BUFF_LEN) {
642 pr_err("%s: req buf len %d > max buf len %lu, setting %lu\n",
643 __func__, len, MAX_XFER_BUFF_LEN, MAX_XFER_BUFF_LEN);
644 len = MAX_XFER_BUFF_LEN;
645 }
646
647 xfer_buf = usb_alloc_coherent(subs->dev, len, GFP_KERNEL, &xfer_buf_pa);
648 if (!xfer_buf)
649 goto unmap_sync;
650
651 resp->xhci_mem_info.xfer_buff.pa = xfer_buf_pa;
652 resp->xhci_mem_info.xfer_buff.size = len;
653
654 va = uaudio_iommu_map(MEM_XFER_BUF, xfer_buf_pa, len);
655 if (!va)
656 goto unmap_sync;
657
658 xfer_buf_va = va;
659 resp->xhci_mem_info.xfer_buff.va = PREPEND_SID_TO_IOVA(va,
660 uaudio_qdev->sid);
661
Hemant Kumaraa2fa3c2016-07-18 16:26:48 -0700662 resp->xhci_mem_info_valid = 1;
663
Hemant Kumar0ef9fbb2016-01-28 11:41:42 -0800664 if (!atomic_read(&uadev[card_num].in_use)) {
665 kref_init(&uadev[card_num].kref);
666 init_waitqueue_head(&uadev[card_num].disconnect_wq);
Hemant Kumard2a54502016-03-22 16:35:16 -0700667 uadev[card_num].num_intf =
668 subs->dev->config->desc.bNumInterfaces;
669 uadev[card_num].info =
670 kzalloc(sizeof(struct intf_info) *
671 uadev[card_num].num_intf, GFP_KERNEL);
672 if (!uadev[card_num].info) {
673 ret = -ENOMEM;
674 goto unmap_xfer_buf;
675 }
676 uadev[card_num].udev = subs->dev;
Hemant Kumar0ef9fbb2016-01-28 11:41:42 -0800677 atomic_set(&uadev[card_num].in_use, 1);
678 } else {
679 kref_get(&uadev[card_num].kref);
680 }
681
Hemant Kumard2a54502016-03-22 16:35:16 -0700682 uadev[card_num].card_num = card_num;
683
684 /* cache intf specific info to use it for unmap and free xfer buf */
Hemant Kumarebbe6262017-01-10 19:26:40 -0800685 uadev[card_num].info[info_idx].data_xfer_ring_va = tr_data_va;
686 uadev[card_num].info[info_idx].data_xfer_ring_size = PAGE_SIZE;
687 uadev[card_num].info[info_idx].sync_xfer_ring_va = tr_sync_va;
688 uadev[card_num].info[info_idx].sync_xfer_ring_size = PAGE_SIZE;
689 uadev[card_num].info[info_idx].xfer_buf_va = xfer_buf_va;
690 uadev[card_num].info[info_idx].xfer_buf_pa = xfer_buf_pa;
691 uadev[card_num].info[info_idx].xfer_buf_size = len;
692 uadev[card_num].info[info_idx].xfer_buf = xfer_buf;
693 uadev[card_num].info[info_idx].pcm_card_num = card_num;
694 uadev[card_num].info[info_idx].pcm_dev_num = pcm_dev_num;
695 uadev[card_num].info[info_idx].direction = subs->direction;
696 uadev[card_num].info[info_idx].intf_num = subs->interface;
697 uadev[card_num].info[info_idx].in_use = true;
Hemant Kumard2a54502016-03-22 16:35:16 -0700698
699 set_bit(card_num, &uaudio_qdev->card_slot);
700
Hemant Kumar0ef9fbb2016-01-28 11:41:42 -0800701 return 0;
Hemant Kumard2a54502016-03-22 16:35:16 -0700702
703unmap_xfer_buf:
704 uaudio_iommu_unmap(MEM_XFER_BUF, xfer_buf_va, len);
705unmap_sync:
706 usb_free_coherent(subs->dev, len, xfer_buf, xfer_buf_pa);
707 uaudio_iommu_unmap(MEM_XFER_RING, tr_sync_va, PAGE_SIZE);
708unmap_data:
709 uaudio_iommu_unmap(MEM_XFER_RING, tr_data_va, PAGE_SIZE);
710unmap_dcba:
711 uaudio_iommu_unmap(MEM_DCBA, dcba_va, PAGE_SIZE);
712unmap_er:
713 uaudio_iommu_unmap(MEM_EVENT_RING, IOVA_BASE, PAGE_SIZE);
Hemant Kumar0ef9fbb2016-01-28 11:41:42 -0800714err:
Hemant Kumard2a54502016-03-22 16:35:16 -0700715 return ret;
Hemant Kumar0ef9fbb2016-01-28 11:41:42 -0800716}
717
Hemant Kumar89fa7b92016-10-27 19:56:31 -0700718static void uaudio_dev_intf_cleanup(struct usb_device *udev,
719 struct intf_info *info)
Hemant Kumar0ef9fbb2016-01-28 11:41:42 -0800720{
Hemant Kumar89fa7b92016-10-27 19:56:31 -0700721 uaudio_iommu_unmap(MEM_XFER_RING, info->data_xfer_ring_va,
722 info->data_xfer_ring_size);
723 info->data_xfer_ring_va = 0;
724 info->data_xfer_ring_size = 0;
725
726 uaudio_iommu_unmap(MEM_XFER_RING, info->sync_xfer_ring_va,
727 info->sync_xfer_ring_size);
728 info->sync_xfer_ring_va = 0;
729 info->sync_xfer_ring_size = 0;
730
731 uaudio_iommu_unmap(MEM_XFER_BUF, info->xfer_buf_va,
732 info->xfer_buf_size);
733 info->xfer_buf_va = 0;
734
735 usb_free_coherent(udev, info->xfer_buf_size,
736 info->xfer_buf, info->xfer_buf_pa);
737 info->xfer_buf_size = 0;
738 info->xfer_buf = NULL;
739 info->xfer_buf_pa = 0;
740
741 info->in_use = false;
742}
743
744static void uaudio_dev_cleanup(struct uaudio_dev *dev)
745{
746 int if_idx;
747
748 /* free xfer buffer and unmap xfer ring and buf per interface */
749 for (if_idx = 0; if_idx < dev->num_intf; if_idx++) {
750 if (!dev->info[if_idx].in_use)
751 continue;
752 uaudio_dev_intf_cleanup(dev->udev, &dev->info[if_idx]);
753 pr_debug("%s: release resources: intf# %d card# %d\n", __func__,
Hemant Kumarebbe6262017-01-10 19:26:40 -0800754 dev->info[if_idx].intf_num, dev->card_num);
Hemant Kumar89fa7b92016-10-27 19:56:31 -0700755 }
756
757 /* iommu_unmap dcba iova for a usb device */
758 uaudio_iommu_unmap(MEM_DCBA, dev->dcba_iova, dev->dcba_size);
759
760 dev->dcba_iova = 0;
761 dev->dcba_size = 0;
762 dev->num_intf = 0;
763
764 /* free interface info */
765 kfree(dev->info);
766 dev->info = NULL;
767
768 clear_bit(dev->card_num, &uaudio_qdev->card_slot);
769
770 /* all audio devices are disconnected */
771 if (!uaudio_qdev->card_slot) {
772 uaudio_iommu_unmap(MEM_EVENT_RING, IOVA_BASE, PAGE_SIZE);
773 usb_sec_event_ring_cleanup(dev->udev, uaudio_qdev->intr_num);
774 pr_debug("%s: all audio devices disconnected\n", __func__);
775 }
776
777 dev->udev = NULL;
778}
779
780static void uaudio_disconnect_cb(struct snd_usb_audio *chip)
781{
782 int ret;
Hemant Kumar0ef9fbb2016-01-28 11:41:42 -0800783 struct uaudio_dev *dev;
784 int card_num = chip->card_num;
Vamsi Krishna Samavedam1e634532016-09-13 14:09:37 -0700785 struct uaudio_qmi_svc *svc = uaudio_svc;
786 struct qmi_uaudio_stream_ind_msg_v01 disconnect_ind = {0};
Hemant Kumar0ef9fbb2016-01-28 11:41:42 -0800787
Hemant Kumard2a54502016-03-22 16:35:16 -0700788 pr_debug("%s: for card# %d\n", __func__, card_num);
789
Hemant Kumar0ef9fbb2016-01-28 11:41:42 -0800790 if (card_num >= SNDRV_CARDS) {
791 pr_err("%s: invalid card number\n", __func__);
Vamsi Krishna Samavedam1e634532016-09-13 14:09:37 -0700792 return;
Hemant Kumar0ef9fbb2016-01-28 11:41:42 -0800793 }
794
Vamsi Krishna Samavedam1e634532016-09-13 14:09:37 -0700795 mutex_lock(&chip->dev_lock);
Hemant Kumar0ef9fbb2016-01-28 11:41:42 -0800796 dev = &uadev[card_num];
Hemant Kumard2a54502016-03-22 16:35:16 -0700797
798 /* clean up */
799 if (!dev->udev) {
800 pr_debug("%s: no clean up required\n", __func__);
801 goto done;
802 }
803
Vamsi Krishna Samavedam1e634532016-09-13 14:09:37 -0700804 if (atomic_read(&dev->in_use)) {
805 mutex_unlock(&chip->dev_lock);
806
807 pr_debug("%s: sending qmi indication disconnect\n", __func__);
808 disconnect_ind.dev_event = USB_AUDIO_DEV_DISCONNECT_V01;
809 disconnect_ind.slot_id = dev->udev->slot_id;
810 ret = qmi_send_ind(svc->uaudio_svc_hdl, svc->curr_conn,
811 &uaudio_stream_ind_desc, &disconnect_ind,
812 sizeof(disconnect_ind));
813 if (ret < 0) {
814 pr_err("%s: qmi send failed wiht err: %d\n",
815 __func__, ret);
816 return;
817 }
818
819 ret = wait_event_interruptible(dev->disconnect_wq,
820 !atomic_read(&dev->in_use));
821 if (ret < 0) {
822 pr_debug("%s: failed with ret %d\n", __func__, ret);
823 return;
824 }
825 mutex_lock(&chip->dev_lock);
826 }
827
Hemant Kumar89fa7b92016-10-27 19:56:31 -0700828 uaudio_dev_cleanup(dev);
Hemant Kumar0ef9fbb2016-01-28 11:41:42 -0800829done:
830 mutex_unlock(&chip->dev_lock);
831}
832
833static void uaudio_dev_release(struct kref *kref)
834{
835 struct uaudio_dev *dev = container_of(kref, struct uaudio_dev, kref);
836
Vamsi Krishna Samavedam0836aae2016-11-03 17:21:02 -0700837 pr_debug("%s for dev %pK\n", __func__, dev);
Hemant Kumard2a54502016-03-22 16:35:16 -0700838
Hemant Kumar0ef9fbb2016-01-28 11:41:42 -0800839 atomic_set(&dev->in_use, 0);
Hemant Kumard2a54502016-03-22 16:35:16 -0700840
841 clear_bit(dev->card_num, &uaudio_qdev->card_slot);
842
843 /* all audio devices are disconnected */
844 if (!uaudio_qdev->card_slot) {
845 usb_sec_event_ring_cleanup(dev->udev, uaudio_qdev->intr_num);
846 uaudio_iommu_unmap(MEM_EVENT_RING, IOVA_BASE, PAGE_SIZE);
847 pr_debug("%s: all audio devices disconnected\n", __func__);
848 }
849
Hemant Kumar0ef9fbb2016-01-28 11:41:42 -0800850 wake_up(&dev->disconnect_wq);
851}
852
Hemant Kumara4f61012016-10-13 15:41:55 -0700853/* maps audio format received over QMI to asound.h based pcm format */
Hemant Kumar89fa7b92016-10-27 19:56:31 -0700854static int map_pcm_format(unsigned int fmt_received)
Hemant Kumara4f61012016-10-13 15:41:55 -0700855{
856 switch (fmt_received) {
857 case USB_QMI_PCM_FORMAT_S8:
858 return SNDRV_PCM_FORMAT_S8;
859 case USB_QMI_PCM_FORMAT_U8:
860 return SNDRV_PCM_FORMAT_U8;
861 case USB_QMI_PCM_FORMAT_S16_LE:
862 return SNDRV_PCM_FORMAT_S16_LE;
863 case USB_QMI_PCM_FORMAT_S16_BE:
864 return SNDRV_PCM_FORMAT_S16_BE;
865 case USB_QMI_PCM_FORMAT_U16_LE:
866 return SNDRV_PCM_FORMAT_U16_LE;
867 case USB_QMI_PCM_FORMAT_U16_BE:
868 return SNDRV_PCM_FORMAT_U16_BE;
869 case USB_QMI_PCM_FORMAT_S24_LE:
870 return SNDRV_PCM_FORMAT_S24_LE;
871 case USB_QMI_PCM_FORMAT_S24_BE:
872 return SNDRV_PCM_FORMAT_S24_BE;
873 case USB_QMI_PCM_FORMAT_U24_LE:
874 return SNDRV_PCM_FORMAT_U24_LE;
875 case USB_QMI_PCM_FORMAT_U24_BE:
876 return SNDRV_PCM_FORMAT_U24_BE;
877 case USB_QMI_PCM_FORMAT_S24_3LE:
878 return SNDRV_PCM_FORMAT_S24_3LE;
879 case USB_QMI_PCM_FORMAT_S24_3BE:
880 return SNDRV_PCM_FORMAT_S24_3BE;
881 case USB_QMI_PCM_FORMAT_U24_3LE:
882 return SNDRV_PCM_FORMAT_U24_3LE;
883 case USB_QMI_PCM_FORMAT_U24_3BE:
884 return SNDRV_PCM_FORMAT_U24_3BE;
885 case USB_QMI_PCM_FORMAT_S32_LE:
886 return SNDRV_PCM_FORMAT_S32_LE;
887 case USB_QMI_PCM_FORMAT_S32_BE:
888 return SNDRV_PCM_FORMAT_S32_BE;
889 case USB_QMI_PCM_FORMAT_U32_LE:
890 return SNDRV_PCM_FORMAT_U32_LE;
891 case USB_QMI_PCM_FORMAT_U32_BE:
892 return SNDRV_PCM_FORMAT_U32_BE;
893 default:
894 return -EINVAL;
895 }
896}
897
Hemant Kumarebbe6262017-01-10 19:26:40 -0800898static int info_idx_from_ifnum(int card_num, int intf_num, bool enable)
899{
900 int i;
901
902 /*
903 * default index 0 is used when info is allocated upon
904 * first enable audio stream req for a pcm device
905 */
906 if (enable && !uadev[card_num].info)
907 return 0;
908
909 for (i = 0; i < uadev[card_num].num_intf; i++) {
910 if (enable && !uadev[card_num].info[i].in_use)
911 return i;
912 else if (!enable &&
913 uadev[card_num].info[i].intf_num == intf_num)
914 return i;
915 }
916
917 return -EINVAL;
918}
919
Hemant Kumar0ef9fbb2016-01-28 11:41:42 -0800920static int handle_uaudio_stream_req(void *req_h, void *req)
921{
922 struct qmi_uaudio_stream_req_msg_v01 *req_msg;
Hemant Kumaraa2fa3c2016-07-18 16:26:48 -0700923 struct qmi_uaudio_stream_resp_msg_v01 resp = {{0}, 0};
Hemant Kumar0ef9fbb2016-01-28 11:41:42 -0800924 struct snd_usb_substream *subs;
925 struct snd_usb_audio *chip = NULL;
926 struct uaudio_qmi_svc *svc = uaudio_svc;
Hemant Kumard2a54502016-03-22 16:35:16 -0700927 struct intf_info *info;
Hemant Kumara4f61012016-10-13 15:41:55 -0700928 int pcm_format;
Hemant Kumar0ef9fbb2016-01-28 11:41:42 -0800929 u8 pcm_card_num, pcm_dev_num, direction;
Hemant Kumarebbe6262017-01-10 19:26:40 -0800930 int info_idx = -EINVAL, ret = 0;
Hemant Kumar0ef9fbb2016-01-28 11:41:42 -0800931
932 req_msg = (struct qmi_uaudio_stream_req_msg_v01 *)req;
933
Hemant Kumaraa2fa3c2016-07-18 16:26:48 -0700934 if (!req_msg->audio_format_valid || !req_msg->bit_rate_valid ||
935 !req_msg->number_of_ch_valid || !req_msg->xfer_buff_size_valid) {
936 pr_err("%s: invalid request msg\n", __func__);
937 ret = -EINVAL;
938 goto response;
939 }
940
Hemant Kumar0ef9fbb2016-01-28 11:41:42 -0800941 direction = req_msg->usb_token & SND_PCM_STREAM_DIRECTION;
942 pcm_dev_num = (req_msg->usb_token & SND_PCM_DEV_NUM_MASK) >> 8;
943 pcm_card_num = (req_msg->usb_token & SND_PCM_CARD_NUM_MASK) >> 16;
944
945 pr_debug("%s:card#:%d dev#:%d dir:%d en:%d fmt:%d rate:%d #ch:%d\n",
946 __func__, pcm_card_num, pcm_dev_num, direction, req_msg->enable,
947 req_msg->audio_format, req_msg->bit_rate,
948 req_msg->number_of_ch);
949
950 if (pcm_card_num >= SNDRV_CARDS) {
951 pr_err("%s: invalid card # %u", __func__, pcm_card_num);
952 ret = -EINVAL;
953 goto response;
954 }
955
Hemant Kumara4f61012016-10-13 15:41:55 -0700956 pcm_format = map_pcm_format(req_msg->audio_format);
957 if (pcm_format == -EINVAL) {
958 pr_err("%s: unsupported pcm format received %d\n",
959 __func__, req_msg->audio_format);
960 ret = -EINVAL;
961 goto response;
962 }
963
Hemant Kumar0ef9fbb2016-01-28 11:41:42 -0800964 subs = find_snd_usb_substream(pcm_card_num, pcm_dev_num, direction,
965 &chip, uaudio_disconnect_cb);
966 if (!subs || !chip || atomic_read(&chip->shutdown)) {
967 pr_err("%s: can't find substream for card# %u, dev# %u dir%u\n",
968 __func__, pcm_card_num, pcm_dev_num, direction);
969 ret = -ENODEV;
970 goto response;
971 }
972
973 mutex_lock(&chip->dev_lock);
Hemant Kumarebbe6262017-01-10 19:26:40 -0800974 info_idx = info_idx_from_ifnum(pcm_card_num, subs->interface,
975 req_msg->enable);
Hemant Kumar0ef9fbb2016-01-28 11:41:42 -0800976 if (atomic_read(&chip->shutdown) || !subs->stream || !subs->stream->pcm
977 || !subs->stream->chip) {
978 ret = -ENODEV;
979 mutex_unlock(&chip->dev_lock);
980 goto response;
981 }
982
Hemant Kumarebbe6262017-01-10 19:26:40 -0800983 if (req_msg->enable) {
984 if (info_idx < 0) {
985 pr_err("%s interface# %d already in use card# %d\n",
986 __func__, subs->interface, pcm_card_num);
987 ret = -EBUSY;
988 mutex_unlock(&chip->dev_lock);
989 goto response;
990 }
991 }
992
Hemant Kumara4f61012016-10-13 15:41:55 -0700993 subs->pcm_format = pcm_format;
Hemant Kumar0ef9fbb2016-01-28 11:41:42 -0800994 subs->channels = req_msg->number_of_ch;
995 subs->cur_rate = req_msg->bit_rate;
Hemant Kumare1578ed2016-12-14 13:19:40 -0800996 uadev[pcm_card_num].ctrl_intf = chip->ctrl_intf;
Hemant Kumar0ef9fbb2016-01-28 11:41:42 -0800997
998 ret = snd_usb_enable_audio_stream(subs, req_msg->enable);
999
1000 if (!ret && req_msg->enable)
Hemant Kumarebbe6262017-01-10 19:26:40 -08001001 ret = prepare_qmi_response(subs, req_msg, &resp, info_idx);
Hemant Kumar0ef9fbb2016-01-28 11:41:42 -08001002
1003 mutex_unlock(&chip->dev_lock);
1004
1005response:
1006 if (!req_msg->enable && ret != -EINVAL) {
Hemant Kumarebbe6262017-01-10 19:26:40 -08001007 if (info_idx >= 0) {
Hemant Kumard2a54502016-03-22 16:35:16 -07001008 mutex_lock(&chip->dev_lock);
Hemant Kumarebbe6262017-01-10 19:26:40 -08001009 info = &uadev[pcm_card_num].info[info_idx];
Hemant Kumar89fa7b92016-10-27 19:56:31 -07001010 uaudio_dev_intf_cleanup(uadev[pcm_card_num].udev, info);
Hemant Kumard2a54502016-03-22 16:35:16 -07001011 pr_debug("%s:release resources: intf# %d card# %d\n",
Hemant Kumarebbe6262017-01-10 19:26:40 -08001012 __func__, subs->interface, pcm_card_num);
Hemant Kumard2a54502016-03-22 16:35:16 -07001013 mutex_unlock(&chip->dev_lock);
1014 }
Hemant Kumar0ef9fbb2016-01-28 11:41:42 -08001015 if (atomic_read(&uadev[pcm_card_num].in_use))
1016 kref_put(&uadev[pcm_card_num].kref,
1017 uaudio_dev_release);
1018 }
1019
Hemant Kumaraa2fa3c2016-07-18 16:26:48 -07001020 resp.usb_token = req_msg->usb_token;
1021 resp.usb_token_valid = 1;
1022 resp.internal_status = ret;
1023 resp.internal_status_valid = 1;
1024 resp.status = ret ? USB_AUDIO_STREAM_REQ_FAILURE_V01 : ret;
1025 resp.status_valid = 1;
Hemant Kumar0ef9fbb2016-01-28 11:41:42 -08001026 ret = qmi_send_resp_from_cb(svc->uaudio_svc_hdl, svc->curr_conn, req_h,
1027 &uaudio_stream_resp_desc, &resp, sizeof(resp));
1028
1029 svc->t_resp_sent = ktime_get();
1030
1031 pr_debug("%s: t_resp sent - t_req recvd (in ms) %lld\n", __func__,
1032 ktime_to_ms(ktime_sub(svc->t_resp_sent, svc->t_request_recvd)));
1033
1034 return ret;
1035}
1036
1037static int uaudio_qmi_svc_connect_cb(struct qmi_handle *handle,
1038 void *conn_h)
1039{
1040 struct uaudio_qmi_svc *svc = uaudio_svc;
1041
1042 if (svc->uaudio_svc_hdl != handle || !conn_h) {
1043 pr_err("%s: handle mismatch\n", __func__);
1044 return -EINVAL;
1045 }
1046 if (svc->curr_conn) {
1047 pr_err("%s: Service is busy\n", __func__);
1048 return -ECONNREFUSED;
1049 }
1050 svc->curr_conn = conn_h;
1051 return 0;
1052}
1053
Hemant Kumar89fa7b92016-10-27 19:56:31 -07001054static void uaudio_qmi_disconnect_work(struct work_struct *w)
1055{
1056 struct intf_info *info;
1057 int idx, if_idx;
1058 struct snd_usb_substream *subs;
1059 struct snd_usb_audio *chip = NULL;
1060
1061 /* find all active intf for set alt 0 and cleanup usb audio dev */
1062 for (idx = 0; idx < SNDRV_CARDS; idx++) {
1063 if (!atomic_read(&uadev[idx].in_use))
1064 continue;
1065
1066 for (if_idx = 0; if_idx < uadev[idx].num_intf; if_idx++) {
1067 if (!uadev[idx].info || !uadev[idx].info[if_idx].in_use)
1068 continue;
1069 info = &uadev[idx].info[if_idx];
1070 subs = find_snd_usb_substream(info->pcm_card_num,
1071 info->pcm_dev_num,
1072 info->direction,
1073 &chip,
1074 uaudio_disconnect_cb);
1075 if (!subs || !chip || atomic_read(&chip->shutdown)) {
1076 pr_debug("%s:no subs for c#%u, dev#%u dir%u\n",
1077 __func__, info->pcm_card_num,
1078 info->pcm_dev_num,
1079 info->direction);
1080 continue;
1081 }
1082 snd_usb_enable_audio_stream(subs, 0);
1083 }
1084 atomic_set(&uadev[idx].in_use, 0);
1085 mutex_lock(&chip->dev_lock);
1086 uaudio_dev_cleanup(&uadev[idx]);
1087 mutex_unlock(&chip->dev_lock);
1088 }
1089}
1090
Hemant Kumar0ef9fbb2016-01-28 11:41:42 -08001091static int uaudio_qmi_svc_disconnect_cb(struct qmi_handle *handle,
1092 void *conn_h)
1093{
1094 struct uaudio_qmi_svc *svc = uaudio_svc;
1095
1096 if (svc->uaudio_svc_hdl != handle || svc->curr_conn != conn_h) {
1097 pr_err("%s: handle mismatch\n", __func__);
1098 return -EINVAL;
1099 }
1100
1101 svc->curr_conn = NULL;
Hemant Kumar89fa7b92016-10-27 19:56:31 -07001102 queue_work(svc->uaudio_wq, &svc->qmi_disconnect_work);
1103
Hemant Kumar0ef9fbb2016-01-28 11:41:42 -08001104 return 0;
1105}
1106
1107static int uaudio_qmi_svc_req_cb(struct qmi_handle *handle, void *conn_h,
1108 void *req_h, unsigned int msg_id, void *req)
1109{
1110 int ret;
1111 struct uaudio_qmi_svc *svc = uaudio_svc;
1112
1113 if (svc->uaudio_svc_hdl != handle || svc->curr_conn != conn_h) {
1114 pr_err("%s: handle mismatch\n", __func__);
1115 return -EINVAL;
1116 }
1117
1118 switch (msg_id) {
1119 case QMI_UAUDIO_STREAM_REQ_V01:
1120 ret = handle_uaudio_stream_req(req_h, req);
1121 break;
1122
1123 default:
1124 ret = -ENOTSUPP;
1125 break;
1126 }
1127 return ret;
1128}
1129
1130static int uaudio_qmi_svc_req_desc_cb(unsigned int msg_id,
1131 struct msg_desc **req_desc)
1132{
1133 int ret;
1134
1135 pr_debug("%s: msg_id %d\n", __func__, msg_id);
1136
1137 switch (msg_id) {
1138 case QMI_UAUDIO_STREAM_REQ_V01:
1139 *req_desc = &uaudio_stream_req_desc;
1140 ret = sizeof(struct qmi_uaudio_stream_req_msg_v01);
1141 break;
1142
1143 default:
1144 ret = -ENOTSUPP;
1145 break;
1146 }
1147 return ret;
1148}
1149
1150static void uaudio_qmi_svc_recv_msg(struct work_struct *w)
1151{
1152 int ret;
1153 struct uaudio_qmi_svc *svc = container_of(w, struct uaudio_qmi_svc,
1154 recv_msg_work);
1155
1156 do {
1157 pr_debug("%s: Notified about a Receive Event", __func__);
1158 } while ((ret = qmi_recv_msg(svc->uaudio_svc_hdl)) == 0);
1159
1160 if (ret != -ENOMSG)
1161 pr_err("%s: Error receiving message\n", __func__);
1162}
1163
1164static void uaudio_qmi_svc_ntfy(struct qmi_handle *handle,
1165 enum qmi_event_type event, void *priv)
1166{
1167 struct uaudio_qmi_svc *svc = uaudio_svc;
1168
1169 pr_debug("%s: event %d", __func__, event);
1170
1171 svc->t_request_recvd = ktime_get();
1172
1173 switch (event) {
1174 case QMI_RECV_MSG:
1175 queue_work(svc->uaudio_wq, &svc->recv_msg_work);
1176 break;
1177 default:
1178 break;
1179 }
1180}
1181
1182static struct qmi_svc_ops_options uaudio_svc_ops_options = {
1183 .version = 1,
1184 .service_id = UAUDIO_STREAM_SERVICE_ID_V01,
1185 .service_vers = UAUDIO_STREAM_SERVICE_VERS_V01,
1186 .connect_cb = uaudio_qmi_svc_connect_cb,
1187 .disconnect_cb = uaudio_qmi_svc_disconnect_cb,
1188 .req_desc_cb = uaudio_qmi_svc_req_desc_cb,
1189 .req_cb = uaudio_qmi_svc_req_cb,
1190};
1191
Hemant Kumard2a54502016-03-22 16:35:16 -07001192static int uaudio_qmi_plat_probe(struct platform_device *pdev)
1193{
1194 int ret;
1195 struct device_node *node = pdev->dev.of_node;
1196
1197 uaudio_qdev = devm_kzalloc(&pdev->dev, sizeof(struct uaudio_qmi_dev),
1198 GFP_KERNEL);
1199 if (!uaudio_qdev)
1200 return -ENOMEM;
1201
1202 uaudio_qdev->dev = &pdev->dev;
1203
1204 ret = of_property_read_u32(node, "qcom,usb-audio-stream-id",
1205 &uaudio_qdev->sid);
1206 if (ret) {
1207 dev_err(&pdev->dev, "failed to read sid.\n");
1208 return -ENODEV;
1209 }
1210
1211 ret = of_property_read_u32(node, "qcom,usb-audio-intr-num",
1212 &uaudio_qdev->intr_num);
1213 if (ret) {
1214 dev_err(&pdev->dev, "failed to read intr num.\n");
1215 return -ENODEV;
1216 }
1217
1218 uaudio_qdev->domain = iommu_domain_alloc(pdev->dev.bus);
Hemant Kumara2a80912016-08-22 19:31:35 -07001219 if (!uaudio_qdev->domain) {
1220 dev_err(&pdev->dev, "failed to allocate iommu domain\n");
Hemant Kumard2a54502016-03-22 16:35:16 -07001221 return -ENODEV;
1222 }
1223
1224 /* attach to external processor iommu */
1225 ret = iommu_attach_device(uaudio_qdev->domain, &pdev->dev);
1226 if (ret) {
1227 dev_err(&pdev->dev, "failed to attach device ret = %d\n", ret);
1228 goto free_domain;
1229 }
1230
1231 /* initialize dcba, xfer ring and xfer buf iova list */
1232 INIT_LIST_HEAD(&uaudio_qdev->dcba_list);
1233 uaudio_qdev->curr_dcba_iova = IOVA_DCBA_BASE;
1234 uaudio_qdev->dcba_iova_size = SNDRV_CARDS * PAGE_SIZE;
1235
1236 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");