blob: aa02ac7813acda2153fdd5092bf3e0aca7ad54fb [file] [log] [blame]
Hemant Kumar068cf612018-01-12 15:59:10 -08001/* Copyright (c) 2016-2018, 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>
Patrick Dalyde1c64d2017-09-12 16:30:12 -070029#include <linux/dma-mapping.h>
Hemant Kumard2a54502016-03-22 16:35:16 -070030#include <linux/platform_device.h>
Ajay Agarwal2a39f672017-04-11 11:58:28 +053031#include <linux/usb/audio-v3.h>
Hemant Kumar0ef9fbb2016-01-28 11:41:42 -080032
33#include "usbaudio.h"
34#include "card.h"
35#include "helper.h"
36#include "pcm.h"
37#include "usb_audio_qmi_v01.h"
38
39#define SND_PCM_CARD_NUM_MASK 0xffff0000
40#define SND_PCM_DEV_NUM_MASK 0xff00
41#define SND_PCM_STREAM_DIRECTION 0xff
42
Hemant Kumard2a54502016-03-22 16:35:16 -070043#define PREPEND_SID_TO_IOVA(iova, sid) (u64)(((u64)(iova)) | \
44 (((u64)sid) << 32))
45
46/* event ring iova base address */
47#define IOVA_BASE 0x1000
48
Hemant Kumar81156ed2017-09-22 12:34:52 -070049#define IOVA_XFER_RING_BASE (IOVA_BASE + PAGE_SIZE * (SNDRV_CARDS + 1))
Hemant Kumard2a54502016-03-22 16:35:16 -070050#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;
Hemant Kumarc08fda62017-11-14 20:20:04 -080071 unsigned int data_ep_pipe;
72 unsigned int sync_ep_pipe;
Hemant Kumard2a54502016-03-22 16:35:16 -070073 u8 *xfer_buf;
Hemant Kumarebbe6262017-01-10 19:26:40 -080074 u8 intf_num;
Hemant Kumar89fa7b92016-10-27 19:56:31 -070075 u8 pcm_card_num;
76 u8 pcm_dev_num;
77 u8 direction;
Hemant Kumard2a54502016-03-22 16:35:16 -070078 bool in_use;
79};
80
Hemant Kumar0ef9fbb2016-01-28 11:41:42 -080081struct uaudio_dev {
Hemant Kumard2a54502016-03-22 16:35:16 -070082 struct usb_device *udev;
Hemant Kumare1578ed2016-12-14 13:19:40 -080083 /* audio control interface */
84 struct usb_host_interface *ctrl_intf;
Hemant Kumard2a54502016-03-22 16:35:16 -070085 unsigned int card_num;
Hemant Kumarc59cc942017-10-06 11:25:25 -070086 unsigned int usb_core_id;
Hemant Kumar0ef9fbb2016-01-28 11:41:42 -080087 atomic_t in_use;
88 struct kref kref;
89 wait_queue_head_t disconnect_wq;
Hemant Kumard2a54502016-03-22 16:35:16 -070090
91 /* interface specific */
92 int num_intf;
93 struct intf_info *info;
Hemant Kumar0ef9fbb2016-01-28 11:41:42 -080094};
95
96static struct uaudio_dev uadev[SNDRV_CARDS];
97
Hemant Kumard2a54502016-03-22 16:35:16 -070098struct uaudio_qmi_dev {
99 struct device *dev;
100 u32 sid;
101 u32 intr_num;
102 struct iommu_domain *domain;
103
104 /* list to keep track of available iova */
Hemant Kumard2a54502016-03-22 16:35:16 -0700105 struct list_head xfer_ring_list;
106 size_t xfer_ring_iova_size;
107 unsigned long curr_xfer_ring_iova;
108 struct list_head xfer_buf_list;
109 size_t xfer_buf_iova_size;
110 unsigned long curr_xfer_buf_iova;
111 /* bit fields representing pcm card enabled */
112 unsigned long card_slot;
Liangliang Lu0ae5cc32018-07-17 13:26:46 +0800113 /* indicate event ring mapped or not */
114 bool er_mapped;
Hemant Kumard2a54502016-03-22 16:35:16 -0700115};
116
117static struct uaudio_qmi_dev *uaudio_qdev;
118
Hemant Kumar0ef9fbb2016-01-28 11:41:42 -0800119struct uaudio_qmi_svc {
120 struct qmi_handle *uaudio_svc_hdl;
121 void *curr_conn;
122 struct work_struct recv_msg_work;
Hemant Kumar89fa7b92016-10-27 19:56:31 -0700123 struct work_struct qmi_disconnect_work;
Hemant Kumar0ef9fbb2016-01-28 11:41:42 -0800124 struct workqueue_struct *uaudio_wq;
125 ktime_t t_request_recvd;
126 ktime_t t_resp_sent;
127};
128
129static struct uaudio_qmi_svc *uaudio_svc;
130
131static struct msg_desc uaudio_stream_req_desc = {
132 .max_msg_len = QMI_UAUDIO_STREAM_REQ_MSG_V01_MAX_MSG_LEN,
133 .msg_id = QMI_UAUDIO_STREAM_REQ_V01,
134 .ei_array = qmi_uaudio_stream_req_msg_v01_ei,
135};
136
137static struct msg_desc uaudio_stream_resp_desc = {
138 .max_msg_len = QMI_UAUDIO_STREAM_RESP_MSG_V01_MAX_MSG_LEN,
139 .msg_id = QMI_UAUDIO_STREAM_RESP_V01,
140 .ei_array = qmi_uaudio_stream_resp_msg_v01_ei,
141};
142
Vamsi Krishna Samavedam1e634532016-09-13 14:09:37 -0700143static struct msg_desc uaudio_stream_ind_desc = {
144 .max_msg_len = QMI_UAUDIO_STREAM_IND_MSG_V01_MAX_MSG_LEN,
145 .msg_id = QMI_UADUIO_STREAM_IND_V01,
146 .ei_array = qmi_uaudio_stream_ind_msg_v01_ei,
147};
148
Hemant Kumard2a54502016-03-22 16:35:16 -0700149enum mem_type {
150 MEM_EVENT_RING,
Hemant Kumard2a54502016-03-22 16:35:16 -0700151 MEM_XFER_RING,
152 MEM_XFER_BUF,
153};
154
Hemant Kumara4f61012016-10-13 15:41:55 -0700155enum usb_qmi_audio_format {
156 USB_QMI_PCM_FORMAT_S8 = 0,
157 USB_QMI_PCM_FORMAT_U8,
158 USB_QMI_PCM_FORMAT_S16_LE,
159 USB_QMI_PCM_FORMAT_S16_BE,
160 USB_QMI_PCM_FORMAT_U16_LE,
161 USB_QMI_PCM_FORMAT_U16_BE,
162 USB_QMI_PCM_FORMAT_S24_LE,
163 USB_QMI_PCM_FORMAT_S24_BE,
164 USB_QMI_PCM_FORMAT_U24_LE,
165 USB_QMI_PCM_FORMAT_U24_BE,
166 USB_QMI_PCM_FORMAT_S24_3LE,
167 USB_QMI_PCM_FORMAT_S24_3BE,
168 USB_QMI_PCM_FORMAT_U24_3LE,
169 USB_QMI_PCM_FORMAT_U24_3BE,
170 USB_QMI_PCM_FORMAT_S32_LE,
171 USB_QMI_PCM_FORMAT_S32_BE,
172 USB_QMI_PCM_FORMAT_U32_LE,
173 USB_QMI_PCM_FORMAT_U32_BE,
174};
175
Hemant Kumar068cf612018-01-12 15:59:10 -0800176static void uaudio_iommu_unmap(enum mem_type mtype, unsigned long va,
177 size_t iova_size, size_t mapped_iova_size);
178
Hemant Kumar81156ed2017-09-22 12:34:52 -0700179static enum usb_audio_device_speed_enum_v01
180get_speed_info(enum usb_device_speed udev_speed)
181{
182 switch (udev_speed) {
183 case USB_SPEED_LOW:
184 return USB_AUDIO_DEVICE_SPEED_LOW_V01;
185 case USB_SPEED_FULL:
186 return USB_AUDIO_DEVICE_SPEED_FULL_V01;
187 case USB_SPEED_HIGH:
188 return USB_AUDIO_DEVICE_SPEED_HIGH_V01;
189 case USB_SPEED_SUPER:
190 return USB_AUDIO_DEVICE_SPEED_SUPER_V01;
Hemant Kumarc59cc942017-10-06 11:25:25 -0700191 case USB_SPEED_SUPER_PLUS:
192 return USB_AUDIO_DEVICE_SPEED_SUPER_PLUS_V01;
Hemant Kumar81156ed2017-09-22 12:34:52 -0700193 default:
194 pr_err("%s: udev speed %d\n", __func__, udev_speed);
195 return USB_AUDIO_DEVICE_SPEED_INVALID_V01;
196 }
197}
198
Hemant Kumard2a54502016-03-22 16:35:16 -0700199static unsigned long uaudio_get_iova(unsigned long *curr_iova,
200 size_t *curr_iova_size, struct list_head *head, size_t size)
Hemant Kumar0ef9fbb2016-01-28 11:41:42 -0800201{
Hemant Kumard2a54502016-03-22 16:35:16 -0700202 struct iova_info *info, *new_info = NULL;
203 struct list_head *curr_head;
204 unsigned long va = 0;
205 size_t tmp_size = size;
206 bool found = false;
207
208 if (size % PAGE_SIZE) {
209 pr_err("%s: size %zu is not page size multiple\n", __func__,
210 size);
211 goto done;
212 }
213
214 if (size > *curr_iova_size) {
215 pr_err("%s: size %zu > curr size %zu\n", __func__, size,
216 *curr_iova_size);
217 goto done;
218 }
219 if (*curr_iova_size == 0) {
220 pr_err("%s: iova mapping is full\n", __func__);
221 goto done;
222 }
223
224 list_for_each_entry(info, head, list) {
225 /* exact size iova_info */
226 if (!info->in_use && info->size == size) {
227 info->in_use = true;
228 va = info->start_iova;
229 *curr_iova_size -= size;
230 found = true;
231 pr_debug("%s: exact size :%zu found\n", __func__, size);
232 goto done;
233 } else if (!info->in_use && tmp_size >= info->size) {
234 if (!new_info)
235 new_info = info;
236 pr_debug("%s: partial size: %zu found\n", __func__,
237 info->size);
238 tmp_size -= info->size;
239 if (tmp_size)
240 continue;
241
242 va = new_info->start_iova;
243 for (curr_head = &new_info->list; curr_head !=
244 &info->list; curr_head = curr_head->next) {
245 new_info = list_entry(curr_head, struct
246 iova_info, list);
247 new_info->in_use = true;
248 }
249 info->in_use = true;
250 *curr_iova_size -= size;
251 found = true;
252 goto done;
253 } else {
254 /* iova region in use */
255 new_info = NULL;
256 tmp_size = size;
257 }
258 }
259
260 info = kzalloc(sizeof(struct iova_info), GFP_KERNEL);
261 if (!info) {
262 va = 0;
263 goto done;
264 }
265
266 va = info->start_iova = *curr_iova;
267 info->size = size;
268 info->in_use = true;
269 *curr_iova += size;
270 *curr_iova_size -= size;
271 found = true;
272 list_add_tail(&info->list, head);
273
274done:
275 if (!found)
276 pr_err("%s: unable to find %zu size iova\n", __func__, size);
277 else
278 pr_debug("%s: va:%lu curr_iova:%lu curr_iova_size:%zu\n",
279 __func__, va, *curr_iova, *curr_iova_size);
280
281 return va;
282}
283
284static unsigned long uaudio_iommu_map(enum mem_type mtype, phys_addr_t pa,
Hemant Kumar068cf612018-01-12 15:59:10 -0800285 size_t size, struct sg_table *sgt)
Hemant Kumard2a54502016-03-22 16:35:16 -0700286{
Hemant Kumar068cf612018-01-12 15:59:10 -0800287 unsigned long va_sg, va = 0;
Hemant Kumard2a54502016-03-22 16:35:16 -0700288 bool map = true;
Hemant Kumar068cf612018-01-12 15:59:10 -0800289 int i, ret;
290 size_t sg_len, total_len = 0;
291 struct scatterlist *sg;
292 phys_addr_t pa_sg;
Hemant Kumard2a54502016-03-22 16:35:16 -0700293
294 switch (mtype) {
295 case MEM_EVENT_RING:
296 va = IOVA_BASE;
297 /* er already mapped */
Liangliang Lu0ae5cc32018-07-17 13:26:46 +0800298 if (uaudio_qdev->er_mapped)
Hemant Kumard2a54502016-03-22 16:35:16 -0700299 map = false;
300 break;
Hemant Kumard2a54502016-03-22 16:35:16 -0700301 case MEM_XFER_RING:
302 va = uaudio_get_iova(&uaudio_qdev->curr_xfer_ring_iova,
303 &uaudio_qdev->xfer_ring_iova_size, &uaudio_qdev->xfer_ring_list,
304 size);
305 break;
306 case MEM_XFER_BUF:
307 va = uaudio_get_iova(&uaudio_qdev->curr_xfer_buf_iova,
308 &uaudio_qdev->xfer_buf_iova_size, &uaudio_qdev->xfer_buf_list,
309 size);
310 break;
311 default:
312 pr_err("%s: unknown mem type %d\n", __func__, mtype);
313 }
314
Hemant Kumar068cf612018-01-12 15:59:10 -0800315 if (!va || !map)
Hemant Kumard2a54502016-03-22 16:35:16 -0700316 goto done;
317
Hemant Kumar068cf612018-01-12 15:59:10 -0800318 if (!sgt)
319 goto skip_sgt_map;
320
321 va_sg = va;
322 for_each_sg(sgt->sgl, sg, sgt->nents, i) {
323 sg_len = PAGE_ALIGN(sg->offset + sg->length);
324 pa_sg = page_to_phys(sg_page(sg));
325 ret = iommu_map(uaudio_qdev->domain, va_sg, pa_sg, sg_len,
326 IOMMU_READ | IOMMU_WRITE | IOMMU_MMIO);
327 if (ret) {
328 pr_err("%s:mapping failed ret%d\n", __func__, ret);
329 pr_err("memtype:%d, pa:%pK iova:%lu sg_len:%zu\n",
330 mtype, &pa_sg, va_sg, sg_len);
331 uaudio_iommu_unmap(MEM_XFER_BUF, va, size, total_len);
332 va = 0;
333 goto done;
334 }
335 pr_debug("%s:memtype %d:map pa:%pK to iova:%lu len:%zu\n",
336 __func__, mtype, &pa_sg, va_sg, sg_len);
337 va_sg += sg_len;
338 total_len += sg_len;
339 }
340
341 if (size != total_len) {
342 pr_err("%s: iova size %zu != mapped iova size %zu\n", __func__,
343 size, total_len);
344 uaudio_iommu_unmap(MEM_XFER_BUF, va, size, total_len);
345 va = 0;
346 }
347 return va;
348
349skip_sgt_map:
350 pr_debug("%s:memtype:%d map pa:%pK to iova %lu size:%zu\n", __func__,
351 mtype, &pa, va, size);
352
Hemant Kumard2a54502016-03-22 16:35:16 -0700353 ret = iommu_map(uaudio_qdev->domain, va, pa, size,
354 IOMMU_READ | IOMMU_WRITE | IOMMU_MMIO);
355 if (ret)
Hemant Kumar068cf612018-01-12 15:59:10 -0800356 pr_err("%s:failed to map pa:%pK iova:%lu memtype:%d ret:%d\n",
Hemant Kumard2a54502016-03-22 16:35:16 -0700357 __func__, &pa, va, mtype, ret);
358done:
359 return va;
360}
361
362static void uaudio_put_iova(unsigned long va, size_t size, struct list_head
363 *head, size_t *curr_iova_size)
364{
365 struct iova_info *info;
366 size_t tmp_size = size;
367 bool found = false;
368
369 list_for_each_entry(info, head, list) {
370 if (info->start_iova == va) {
371 if (!info->in_use) {
372 pr_err("%s: va %lu is not in use\n", __func__,
373 va);
374 return;
375 }
376 found = true;
377 info->in_use = false;
378 if (info->size == size)
379 goto done;
380 }
381
382 if (found && tmp_size >= info->size) {
383 info->in_use = false;
384 tmp_size -= info->size;
385 if (!tmp_size)
386 goto done;
387 }
388 }
389
390 if (!found) {
391 pr_err("%s: unable to find the va %lu\n", __func__, va);
392 return;
393 }
394done:
395 *curr_iova_size += size;
396 pr_debug("%s: curr_iova_size %zu\n", __func__, *curr_iova_size);
397}
398
399static void uaudio_iommu_unmap(enum mem_type mtype, unsigned long va,
Hemant Kumar068cf612018-01-12 15:59:10 -0800400 size_t iova_size, size_t mapped_iova_size)
Hemant Kumard2a54502016-03-22 16:35:16 -0700401{
402 size_t umap_size;
403 bool unmap = true;
404
Hemant Kumar068cf612018-01-12 15:59:10 -0800405 if (!va || !iova_size)
Hemant Kumard2a54502016-03-22 16:35:16 -0700406 return;
407
408 switch (mtype) {
409 case MEM_EVENT_RING:
Liangliang Lu0ae5cc32018-07-17 13:26:46 +0800410 if (uaudio_qdev->er_mapped)
411 uaudio_qdev->er_mapped = false;
Hemant Kumard2a54502016-03-22 16:35:16 -0700412 else
413 unmap = false;
414 break;
Hemant Kumar81156ed2017-09-22 12:34:52 -0700415
Hemant Kumard2a54502016-03-22 16:35:16 -0700416 case MEM_XFER_RING:
Hemant Kumar068cf612018-01-12 15:59:10 -0800417 uaudio_put_iova(va, iova_size, &uaudio_qdev->xfer_ring_list,
Hemant Kumard2a54502016-03-22 16:35:16 -0700418 &uaudio_qdev->xfer_ring_iova_size);
419 break;
420 case MEM_XFER_BUF:
Hemant Kumar068cf612018-01-12 15:59:10 -0800421 uaudio_put_iova(va, iova_size, &uaudio_qdev->xfer_buf_list,
Hemant Kumard2a54502016-03-22 16:35:16 -0700422 &uaudio_qdev->xfer_buf_iova_size);
423 break;
424 default:
425 pr_err("%s: unknown mem type %d\n", __func__, mtype);
426 unmap = false;
427 }
428
Hemant Kumar068cf612018-01-12 15:59:10 -0800429 if (!unmap || !mapped_iova_size)
Hemant Kumard2a54502016-03-22 16:35:16 -0700430 return;
431
Hemant Kumar068cf612018-01-12 15:59:10 -0800432 pr_debug("%s:memtype %d: unmap iova %lu size %zu\n", __func__, mtype,
433 va, mapped_iova_size);
Hemant Kumard2a54502016-03-22 16:35:16 -0700434
Hemant Kumar068cf612018-01-12 15:59:10 -0800435 umap_size = iommu_unmap(uaudio_qdev->domain, va, mapped_iova_size);
436 if (umap_size != mapped_iova_size)
437 pr_err("%s:unmapped size %zu for iova %lu of mapped size %zu\n",
438 __func__, umap_size, va, mapped_iova_size);
Hemant Kumard2a54502016-03-22 16:35:16 -0700439}
440
441static int prepare_qmi_response(struct snd_usb_substream *subs,
Hemant Kumarebbe6262017-01-10 19:26:40 -0800442 struct qmi_uaudio_stream_req_msg_v01 *req_msg,
443 struct qmi_uaudio_stream_resp_msg_v01 *resp, int info_idx)
Hemant Kumard2a54502016-03-22 16:35:16 -0700444{
Hemant Kumar0ef9fbb2016-01-28 11:41:42 -0800445 struct usb_interface *iface;
446 struct usb_host_interface *alts;
447 struct usb_interface_descriptor *altsd;
448 struct usb_host_endpoint *ep;
449 struct uac_format_type_i_continuous_descriptor *fmt;
450 struct uac_format_type_i_discrete_descriptor *fmt_v1;
451 struct uac_format_type_i_ext_descriptor *fmt_v2;
452 struct uac1_as_header_descriptor *as;
Ajay Agarwalbf276f92018-09-05 14:16:28 +0530453 int ret;
Hemant Kumarebbe6262017-01-10 19:26:40 -0800454 int protocol, card_num, pcm_dev_num;
Hemant Kumare1578ed2016-12-14 13:19:40 -0800455 void *hdr_ptr;
Hemant Kumard2a54502016-03-22 16:35:16 -0700456 u8 *xfer_buf;
Hemant Kumarc08fda62017-11-14 20:20:04 -0800457 unsigned int data_ep_pipe = 0, sync_ep_pipe = 0;
Hemant Kumar068cf612018-01-12 15:59:10 -0800458 u32 len, mult, remainder, xfer_buf_len;
459 unsigned long va, tr_data_va = 0, tr_sync_va = 0;
Hemant Kumar1346a802017-09-22 15:03:45 -0700460 phys_addr_t xhci_pa, xfer_buf_pa, tr_data_pa = 0, tr_sync_pa = 0;
461 dma_addr_t dma;
462 struct sg_table sgt;
Hemant Kumar0ef9fbb2016-01-28 11:41:42 -0800463
464 iface = usb_ifnum_to_if(subs->dev, subs->interface);
465 if (!iface) {
466 pr_err("%s: interface # %d does not exist\n", __func__,
467 subs->interface);
Ajay Agarwalbf276f92018-09-05 14:16:28 +0530468 ret = -ENODEV;
Hemant Kumar0ef9fbb2016-01-28 11:41:42 -0800469 goto err;
470 }
471
Hemant Kumarebbe6262017-01-10 19:26:40 -0800472 pcm_dev_num = (req_msg->usb_token & SND_PCM_DEV_NUM_MASK) >> 8;
473 card_num = (req_msg->usb_token & SND_PCM_CARD_NUM_MASK) >> 16;
474 xfer_buf_len = req_msg->xfer_buff_size;
Hemant Kumar89fa7b92016-10-27 19:56:31 -0700475
Hemant Kumar0ef9fbb2016-01-28 11:41:42 -0800476 alts = &iface->altsetting[subs->altset_idx];
477 altsd = get_iface_desc(alts);
478 protocol = altsd->bInterfaceProtocol;
479
480 /* get format type */
Ajay Agarwal2a39f672017-04-11 11:58:28 +0530481 if (protocol != UAC_VERSION_3) {
482 fmt = snd_usb_find_csint_desc(alts->extra, alts->extralen, NULL,
483 UAC_FORMAT_TYPE);
484 if (!fmt) {
485 pr_err("%s: %u:%d : no UAC_FORMAT_TYPE desc\n",
486 __func__, subs->interface, subs->altset_idx);
Ajay Agarwalbf276f92018-09-05 14:16:28 +0530487 ret = -ENODEV;
Ajay Agarwal2a39f672017-04-11 11:58:28 +0530488 goto err;
489 }
Hemant Kumar0ef9fbb2016-01-28 11:41:42 -0800490 }
491
Hemant Kumare1578ed2016-12-14 13:19:40 -0800492 if (!uadev[card_num].ctrl_intf) {
493 pr_err("%s: audio ctrl intf info not cached\n", __func__);
Ajay Agarwalbf276f92018-09-05 14:16:28 +0530494 ret = -ENODEV;
Hemant Kumare1578ed2016-12-14 13:19:40 -0800495 goto err;
496 }
497
Ajay Agarwal2a39f672017-04-11 11:58:28 +0530498 if (protocol != UAC_VERSION_3) {
499 hdr_ptr = snd_usb_find_csint_desc(
500 uadev[card_num].ctrl_intf->extra,
501 uadev[card_num].ctrl_intf->extralen,
502 NULL, UAC_HEADER);
503 if (!hdr_ptr) {
504 pr_err("%s: no UAC_HEADER desc\n", __func__);
Ajay Agarwalbf276f92018-09-05 14:16:28 +0530505 ret = -ENODEV;
Ajay Agarwal2a39f672017-04-11 11:58:28 +0530506 goto err;
507 }
Hemant Kumare1578ed2016-12-14 13:19:40 -0800508 }
509
Hemant Kumar0ef9fbb2016-01-28 11:41:42 -0800510 if (protocol == UAC_VERSION_1) {
511 as = snd_usb_find_csint_desc(alts->extra, alts->extralen, NULL,
512 UAC_AS_GENERAL);
513 if (!as) {
514 pr_err("%s: %u:%d : no UAC_AS_GENERAL desc\n", __func__,
515 subs->interface, subs->altset_idx);
Ajay Agarwalbf276f92018-09-05 14:16:28 +0530516 ret = -ENODEV;
Hemant Kumar0ef9fbb2016-01-28 11:41:42 -0800517 goto err;
518 }
Hemant Kumaraa2fa3c2016-07-18 16:26:48 -0700519 resp->data_path_delay = as->bDelay;
520 resp->data_path_delay_valid = 1;
Hemant Kumar0ef9fbb2016-01-28 11:41:42 -0800521 fmt_v1 = (struct uac_format_type_i_discrete_descriptor *)fmt;
Hemant Kumaraa2fa3c2016-07-18 16:26:48 -0700522 resp->usb_audio_subslot_size = fmt_v1->bSubframeSize;
523 resp->usb_audio_subslot_size_valid = 1;
Hemant Kumare1578ed2016-12-14 13:19:40 -0800524
525 resp->usb_audio_spec_revision =
526 ((struct uac1_ac_header_descriptor *)hdr_ptr)->bcdADC;
527 resp->usb_audio_spec_revision_valid = 1;
Hemant Kumar0ef9fbb2016-01-28 11:41:42 -0800528 } else if (protocol == UAC_VERSION_2) {
529 fmt_v2 = (struct uac_format_type_i_ext_descriptor *)fmt;
Hemant Kumaraa2fa3c2016-07-18 16:26:48 -0700530 resp->usb_audio_subslot_size = fmt_v2->bSubslotSize;
531 resp->usb_audio_subslot_size_valid = 1;
Hemant Kumare1578ed2016-12-14 13:19:40 -0800532
533 resp->usb_audio_spec_revision =
534 ((struct uac2_ac_header_descriptor *)hdr_ptr)->bcdADC;
535 resp->usb_audio_spec_revision_valid = 1;
Ajay Agarwal2a39f672017-04-11 11:58:28 +0530536 } else if (protocol == UAC_VERSION_3) {
537 switch (le16_to_cpu(get_endpoint(alts, 0)->wMaxPacketSize)) {
538 case BADD_MAXPSIZE_SYNC_MONO_16:
539 case BADD_MAXPSIZE_SYNC_STEREO_16:
540 case BADD_MAXPSIZE_ASYNC_MONO_16:
541 case BADD_MAXPSIZE_ASYNC_STEREO_16: {
542 resp->usb_audio_subslot_size = SUBSLOTSIZE_16_BIT;
543 break;
544 }
545
546 case BADD_MAXPSIZE_SYNC_MONO_24:
547 case BADD_MAXPSIZE_SYNC_STEREO_24:
548 case BADD_MAXPSIZE_ASYNC_MONO_24:
549 case BADD_MAXPSIZE_ASYNC_STEREO_24: {
550 resp->usb_audio_subslot_size = SUBSLOTSIZE_24_BIT;
551 break;
552 }
553
554 default:
555 pr_err("%d: %u: Invalid wMaxPacketSize\n",
556 subs->interface, subs->altset_idx);
557 ret = -EINVAL;
558 goto err;
559 }
560 resp->usb_audio_subslot_size_valid = 1;
Hemant Kumar0ef9fbb2016-01-28 11:41:42 -0800561 } else {
562 pr_err("%s: unknown protocol version %x\n", __func__, protocol);
Ajay Agarwalbf276f92018-09-05 14:16:28 +0530563 ret = -ENODEV;
Hemant Kumar0ef9fbb2016-01-28 11:41:42 -0800564 goto err;
565 }
566
Hemant Kumar0ef9fbb2016-01-28 11:41:42 -0800567 resp->slot_id = subs->dev->slot_id;
Hemant Kumaraa2fa3c2016-07-18 16:26:48 -0700568 resp->slot_id_valid = 1;
Hemant Kumar0ef9fbb2016-01-28 11:41:42 -0800569
570 memcpy(&resp->std_as_opr_intf_desc, &alts->desc, sizeof(alts->desc));
Hemant Kumaraa2fa3c2016-07-18 16:26:48 -0700571 resp->std_as_opr_intf_desc_valid = 1;
Hemant Kumar0ef9fbb2016-01-28 11:41:42 -0800572
573 ep = usb_pipe_endpoint(subs->dev, subs->data_endpoint->pipe);
574 if (!ep) {
575 pr_err("%s: data ep # %d context is null\n", __func__,
576 subs->data_endpoint->ep_num);
Ajay Agarwalbf276f92018-09-05 14:16:28 +0530577 ret = -ENODEV;
Hemant Kumar0ef9fbb2016-01-28 11:41:42 -0800578 goto err;
579 }
Hemant Kumarc08fda62017-11-14 20:20:04 -0800580 data_ep_pipe = subs->data_endpoint->pipe;
Hemant Kumar0ef9fbb2016-01-28 11:41:42 -0800581 memcpy(&resp->std_as_data_ep_desc, &ep->desc, sizeof(ep->desc));
Hemant Kumaraa2fa3c2016-07-18 16:26:48 -0700582 resp->std_as_data_ep_desc_valid = 1;
Hemant Kumar0ef9fbb2016-01-28 11:41:42 -0800583
Hemant Kumar1346a802017-09-22 15:03:45 -0700584 tr_data_pa = usb_get_xfer_ring_phys_addr(subs->dev, ep, &dma);
585 if (!tr_data_pa) {
Hemant Kumard2a54502016-03-22 16:35:16 -0700586 pr_err("%s:failed to get data ep ring dma address\n", __func__);
Ajay Agarwalbf276f92018-09-05 14:16:28 +0530587 ret = -ENODEV;
Hemant Kumard2a54502016-03-22 16:35:16 -0700588 goto err;
589 }
590
Hemant Kumar1346a802017-09-22 15:03:45 -0700591 resp->xhci_mem_info.tr_data.pa = dma;
Hemant Kumard2a54502016-03-22 16:35:16 -0700592
Hemant Kumar0ef9fbb2016-01-28 11:41:42 -0800593 if (subs->sync_endpoint) {
594 ep = usb_pipe_endpoint(subs->dev, subs->sync_endpoint->pipe);
595 if (!ep) {
Hemant Kumar44cefc52016-12-06 18:34:40 -0800596 pr_debug("%s: implicit fb on data ep\n", __func__);
597 goto skip_sync_ep;
Hemant Kumar0ef9fbb2016-01-28 11:41:42 -0800598 }
Hemant Kumarc08fda62017-11-14 20:20:04 -0800599 sync_ep_pipe = subs->sync_endpoint->pipe;
Hemant Kumar0ef9fbb2016-01-28 11:41:42 -0800600 memcpy(&resp->std_as_sync_ep_desc, &ep->desc, sizeof(ep->desc));
Hemant Kumaraa2fa3c2016-07-18 16:26:48 -0700601 resp->std_as_sync_ep_desc_valid = 1;
602
Hemant Kumar1346a802017-09-22 15:03:45 -0700603 tr_sync_pa = usb_get_xfer_ring_phys_addr(subs->dev, ep, &dma);
604 if (!tr_sync_pa) {
Hemant Kumard2a54502016-03-22 16:35:16 -0700605 pr_err("%s:failed to get sync ep ring dma address\n",
606 __func__);
Ajay Agarwalbf276f92018-09-05 14:16:28 +0530607 ret = -ENODEV;
Hemant Kumard2a54502016-03-22 16:35:16 -0700608 goto err;
609 }
Hemant Kumar1346a802017-09-22 15:03:45 -0700610 resp->xhci_mem_info.tr_sync.pa = dma;
Hemant Kumar0ef9fbb2016-01-28 11:41:42 -0800611 }
612
Hemant Kumar44cefc52016-12-06 18:34:40 -0800613skip_sync_ep:
Hemant Kumard2a54502016-03-22 16:35:16 -0700614 resp->interrupter_num = uaudio_qdev->intr_num;
Hemant Kumaraa2fa3c2016-07-18 16:26:48 -0700615 resp->interrupter_num_valid = 1;
Hemant Kumard2a54502016-03-22 16:35:16 -0700616
Hemant Kumar746cc972017-08-17 17:34:05 -0700617 ret = usb_get_controller_id(subs->dev);
618 if (ret < 0)
619 goto err;
620
621 resp->controller_num = ret;
622 resp->controller_num_valid = 1;
623
Hemant Kumard2a54502016-03-22 16:35:16 -0700624 /* map xhci data structures PA memory to iova */
625
626 /* event ring */
627 ret = usb_sec_event_ring_setup(subs->dev, resp->interrupter_num);
628 if (ret) {
629 pr_err("%s: failed to setup sec event ring ret %d\n", __func__,
630 ret);
631 goto err;
632 }
Ajay Agarwalbf276f92018-09-05 14:16:28 +0530633
Hemant Kumar1346a802017-09-22 15:03:45 -0700634 xhci_pa = usb_get_sec_event_ring_phys_addr(subs->dev,
635 resp->interrupter_num, &dma);
Hemant Kumard2a54502016-03-22 16:35:16 -0700636 if (!xhci_pa) {
637 pr_err("%s: failed to get sec event ring dma address\n",
638 __func__);
Ajay Agarwalbf276f92018-09-05 14:16:28 +0530639 ret = -ENODEV;
Hemant Kumard2a54502016-03-22 16:35:16 -0700640 goto err;
641 }
642
Hemant Kumar068cf612018-01-12 15:59:10 -0800643 va = uaudio_iommu_map(MEM_EVENT_RING, xhci_pa, PAGE_SIZE, NULL);
Ajay Agarwalbf276f92018-09-05 14:16:28 +0530644 if (!va) {
645 ret = -ENOMEM;
Hemant Kumard2a54502016-03-22 16:35:16 -0700646 goto err;
Ajay Agarwalbf276f92018-09-05 14:16:28 +0530647 }
Hemant Kumard2a54502016-03-22 16:35:16 -0700648
649 resp->xhci_mem_info.evt_ring.va = PREPEND_SID_TO_IOVA(va,
650 uaudio_qdev->sid);
Hemant Kumar1346a802017-09-22 15:03:45 -0700651 resp->xhci_mem_info.evt_ring.pa = dma;
Hemant Kumard2a54502016-03-22 16:35:16 -0700652 resp->xhci_mem_info.evt_ring.size = PAGE_SIZE;
Liangliang Lu0ae5cc32018-07-17 13:26:46 +0800653 uaudio_qdev->er_mapped = true;
Hemant Kumard2a54502016-03-22 16:35:16 -0700654
Hemant Kumar81156ed2017-09-22 12:34:52 -0700655 resp->speed_info = get_speed_info(subs->dev->speed);
Ajay Agarwalbf276f92018-09-05 14:16:28 +0530656 if (resp->speed_info == USB_AUDIO_DEVICE_SPEED_INVALID_V01) {
657 ret = -ENODEV;
Hemant Kumard2a54502016-03-22 16:35:16 -0700658 goto unmap_er;
Ajay Agarwalbf276f92018-09-05 14:16:28 +0530659 }
Hemant Kumard2a54502016-03-22 16:35:16 -0700660
Hemant Kumar81156ed2017-09-22 12:34:52 -0700661 resp->speed_info_valid = 1;
Hemant Kumard2a54502016-03-22 16:35:16 -0700662
663 /* data transfer ring */
Hemant Kumar068cf612018-01-12 15:59:10 -0800664 va = uaudio_iommu_map(MEM_XFER_RING, tr_data_pa, PAGE_SIZE, NULL);
Ajay Agarwalbf276f92018-09-05 14:16:28 +0530665 if (!va) {
666 ret = -ENOMEM;
Hemant Kumar81156ed2017-09-22 12:34:52 -0700667 goto unmap_er;
Ajay Agarwalbf276f92018-09-05 14:16:28 +0530668 }
Hemant Kumard2a54502016-03-22 16:35:16 -0700669
670 tr_data_va = va;
671 resp->xhci_mem_info.tr_data.va = PREPEND_SID_TO_IOVA(va,
672 uaudio_qdev->sid);
673 resp->xhci_mem_info.tr_data.size = PAGE_SIZE;
674
675 /* sync transfer ring */
676 if (!resp->xhci_mem_info.tr_sync.pa)
677 goto skip_sync;
678
679 xhci_pa = resp->xhci_mem_info.tr_sync.pa;
Hemant Kumar068cf612018-01-12 15:59:10 -0800680 va = uaudio_iommu_map(MEM_XFER_RING, tr_sync_pa, PAGE_SIZE, NULL);
Ajay Agarwalbf276f92018-09-05 14:16:28 +0530681 if (!va) {
682 ret = -ENOMEM;
Hemant Kumard2a54502016-03-22 16:35:16 -0700683 goto unmap_data;
Ajay Agarwalbf276f92018-09-05 14:16:28 +0530684 }
Hemant Kumard2a54502016-03-22 16:35:16 -0700685
686 tr_sync_va = va;
687 resp->xhci_mem_info.tr_sync.va = PREPEND_SID_TO_IOVA(va,
688 uaudio_qdev->sid);
689 resp->xhci_mem_info.tr_sync.size = PAGE_SIZE;
690
691skip_sync:
692 /* xfer buffer, multiple of 4K only */
693 if (!xfer_buf_len)
694 xfer_buf_len = PAGE_SIZE;
695
696 mult = xfer_buf_len / PAGE_SIZE;
697 remainder = xfer_buf_len % PAGE_SIZE;
698 len = mult * PAGE_SIZE;
699 len += remainder ? PAGE_SIZE : 0;
700
701 if (len > MAX_XFER_BUFF_LEN) {
702 pr_err("%s: req buf len %d > max buf len %lu, setting %lu\n",
703 __func__, len, MAX_XFER_BUFF_LEN, MAX_XFER_BUFF_LEN);
704 len = MAX_XFER_BUFF_LEN;
705 }
706
707 xfer_buf = usb_alloc_coherent(subs->dev, len, GFP_KERNEL, &xfer_buf_pa);
Ajay Agarwalbf276f92018-09-05 14:16:28 +0530708 if (!xfer_buf) {
709 ret = -ENOMEM;
Hemant Kumard2a54502016-03-22 16:35:16 -0700710 goto unmap_sync;
Ajay Agarwalbf276f92018-09-05 14:16:28 +0530711 }
Hemant Kumard2a54502016-03-22 16:35:16 -0700712
Hemant Kumar1346a802017-09-22 15:03:45 -0700713 dma_get_sgtable(subs->dev->bus->sysdev, &sgt, xfer_buf, xfer_buf_pa,
714 len);
Hemant Kumar068cf612018-01-12 15:59:10 -0800715 va = uaudio_iommu_map(MEM_XFER_BUF, xfer_buf_pa, len, &sgt);
Ajay Agarwalbf276f92018-09-05 14:16:28 +0530716 if (!va) {
717 ret = -ENOMEM;
Hemant Kumar068cf612018-01-12 15:59:10 -0800718 goto unmap_sync;
Ajay Agarwalbf276f92018-09-05 14:16:28 +0530719 }
Hemant Kumar1346a802017-09-22 15:03:45 -0700720
Hemant Kumard2a54502016-03-22 16:35:16 -0700721 resp->xhci_mem_info.xfer_buff.pa = xfer_buf_pa;
722 resp->xhci_mem_info.xfer_buff.size = len;
723
Hemant Kumard2a54502016-03-22 16:35:16 -0700724 resp->xhci_mem_info.xfer_buff.va = PREPEND_SID_TO_IOVA(va,
725 uaudio_qdev->sid);
726
Hemant Kumaraa2fa3c2016-07-18 16:26:48 -0700727 resp->xhci_mem_info_valid = 1;
728
Hemant Kumar1346a802017-09-22 15:03:45 -0700729 sg_free_table(&sgt);
730
Hemant Kumar0ef9fbb2016-01-28 11:41:42 -0800731 if (!atomic_read(&uadev[card_num].in_use)) {
732 kref_init(&uadev[card_num].kref);
733 init_waitqueue_head(&uadev[card_num].disconnect_wq);
Hemant Kumard2a54502016-03-22 16:35:16 -0700734 uadev[card_num].num_intf =
735 subs->dev->config->desc.bNumInterfaces;
736 uadev[card_num].info =
737 kzalloc(sizeof(struct intf_info) *
738 uadev[card_num].num_intf, GFP_KERNEL);
739 if (!uadev[card_num].info) {
740 ret = -ENOMEM;
Hemant Kumar068cf612018-01-12 15:59:10 -0800741 goto unmap_sync;
Hemant Kumard2a54502016-03-22 16:35:16 -0700742 }
743 uadev[card_num].udev = subs->dev;
Hemant Kumar0ef9fbb2016-01-28 11:41:42 -0800744 atomic_set(&uadev[card_num].in_use, 1);
745 } else {
746 kref_get(&uadev[card_num].kref);
747 }
748
Hemant Kumard2a54502016-03-22 16:35:16 -0700749 uadev[card_num].card_num = card_num;
Hemant Kumarc59cc942017-10-06 11:25:25 -0700750 uadev[card_num].usb_core_id = resp->controller_num;
Hemant Kumard2a54502016-03-22 16:35:16 -0700751
752 /* cache intf specific info to use it for unmap and free xfer buf */
Hemant Kumarebbe6262017-01-10 19:26:40 -0800753 uadev[card_num].info[info_idx].data_xfer_ring_va = tr_data_va;
754 uadev[card_num].info[info_idx].data_xfer_ring_size = PAGE_SIZE;
755 uadev[card_num].info[info_idx].sync_xfer_ring_va = tr_sync_va;
756 uadev[card_num].info[info_idx].sync_xfer_ring_size = PAGE_SIZE;
Hemant Kumar1346a802017-09-22 15:03:45 -0700757 uadev[card_num].info[info_idx].xfer_buf_va = va;
Hemant Kumarebbe6262017-01-10 19:26:40 -0800758 uadev[card_num].info[info_idx].xfer_buf_pa = xfer_buf_pa;
759 uadev[card_num].info[info_idx].xfer_buf_size = len;
Hemant Kumarc08fda62017-11-14 20:20:04 -0800760 uadev[card_num].info[info_idx].data_ep_pipe = data_ep_pipe;
761 uadev[card_num].info[info_idx].sync_ep_pipe = sync_ep_pipe;
Hemant Kumarebbe6262017-01-10 19:26:40 -0800762 uadev[card_num].info[info_idx].xfer_buf = xfer_buf;
763 uadev[card_num].info[info_idx].pcm_card_num = card_num;
764 uadev[card_num].info[info_idx].pcm_dev_num = pcm_dev_num;
765 uadev[card_num].info[info_idx].direction = subs->direction;
766 uadev[card_num].info[info_idx].intf_num = subs->interface;
767 uadev[card_num].info[info_idx].in_use = true;
Hemant Kumard2a54502016-03-22 16:35:16 -0700768
769 set_bit(card_num, &uaudio_qdev->card_slot);
770
Hemant Kumar0ef9fbb2016-01-28 11:41:42 -0800771 return 0;
Hemant Kumard2a54502016-03-22 16:35:16 -0700772
Hemant Kumard2a54502016-03-22 16:35:16 -0700773unmap_sync:
774 usb_free_coherent(subs->dev, len, xfer_buf, xfer_buf_pa);
Hemant Kumar068cf612018-01-12 15:59:10 -0800775 uaudio_iommu_unmap(MEM_XFER_RING, tr_sync_va, PAGE_SIZE, PAGE_SIZE);
Hemant Kumard2a54502016-03-22 16:35:16 -0700776unmap_data:
Hemant Kumar068cf612018-01-12 15:59:10 -0800777 uaudio_iommu_unmap(MEM_XFER_RING, tr_data_va, PAGE_SIZE, PAGE_SIZE);
Hemant Kumard2a54502016-03-22 16:35:16 -0700778unmap_er:
Hemant Kumar068cf612018-01-12 15:59:10 -0800779 uaudio_iommu_unmap(MEM_EVENT_RING, IOVA_BASE, PAGE_SIZE, PAGE_SIZE);
Hemant Kumar0ef9fbb2016-01-28 11:41:42 -0800780err:
Hemant Kumard2a54502016-03-22 16:35:16 -0700781 return ret;
Hemant Kumar0ef9fbb2016-01-28 11:41:42 -0800782}
783
Hemant Kumar89fa7b92016-10-27 19:56:31 -0700784static void uaudio_dev_intf_cleanup(struct usb_device *udev,
785 struct intf_info *info)
Hemant Kumar0ef9fbb2016-01-28 11:41:42 -0800786{
Hemant Kumarc08fda62017-11-14 20:20:04 -0800787
Hemant Kumar89fa7b92016-10-27 19:56:31 -0700788 uaudio_iommu_unmap(MEM_XFER_RING, info->data_xfer_ring_va,
Hemant Kumar068cf612018-01-12 15:59:10 -0800789 info->data_xfer_ring_size, info->data_xfer_ring_size);
Hemant Kumar89fa7b92016-10-27 19:56:31 -0700790 info->data_xfer_ring_va = 0;
791 info->data_xfer_ring_size = 0;
792
793 uaudio_iommu_unmap(MEM_XFER_RING, info->sync_xfer_ring_va,
Hemant Kumar068cf612018-01-12 15:59:10 -0800794 info->sync_xfer_ring_size, info->sync_xfer_ring_size);
Hemant Kumar89fa7b92016-10-27 19:56:31 -0700795 info->sync_xfer_ring_va = 0;
796 info->sync_xfer_ring_size = 0;
797
798 uaudio_iommu_unmap(MEM_XFER_BUF, info->xfer_buf_va,
Hemant Kumar068cf612018-01-12 15:59:10 -0800799 info->xfer_buf_size, info->xfer_buf_size);
Hemant Kumar89fa7b92016-10-27 19:56:31 -0700800 info->xfer_buf_va = 0;
801
802 usb_free_coherent(udev, info->xfer_buf_size,
803 info->xfer_buf, info->xfer_buf_pa);
804 info->xfer_buf_size = 0;
805 info->xfer_buf = NULL;
806 info->xfer_buf_pa = 0;
807
808 info->in_use = false;
809}
810
811static void uaudio_dev_cleanup(struct uaudio_dev *dev)
812{
813 int if_idx;
814
815 /* free xfer buffer and unmap xfer ring and buf per interface */
816 for (if_idx = 0; if_idx < dev->num_intf; if_idx++) {
817 if (!dev->info[if_idx].in_use)
818 continue;
819 uaudio_dev_intf_cleanup(dev->udev, &dev->info[if_idx]);
820 pr_debug("%s: release resources: intf# %d card# %d\n", __func__,
Hemant Kumarebbe6262017-01-10 19:26:40 -0800821 dev->info[if_idx].intf_num, dev->card_num);
Hemant Kumar89fa7b92016-10-27 19:56:31 -0700822 }
823
Hemant Kumar89fa7b92016-10-27 19:56:31 -0700824 dev->num_intf = 0;
825
826 /* free interface info */
827 kfree(dev->info);
828 dev->info = NULL;
829
830 clear_bit(dev->card_num, &uaudio_qdev->card_slot);
831
832 /* all audio devices are disconnected */
833 if (!uaudio_qdev->card_slot) {
Hemant Kumar068cf612018-01-12 15:59:10 -0800834 uaudio_iommu_unmap(MEM_EVENT_RING, IOVA_BASE, PAGE_SIZE,
835 PAGE_SIZE);
Hemant Kumar89fa7b92016-10-27 19:56:31 -0700836 usb_sec_event_ring_cleanup(dev->udev, uaudio_qdev->intr_num);
837 pr_debug("%s: all audio devices disconnected\n", __func__);
838 }
839
840 dev->udev = NULL;
841}
842
843static void uaudio_disconnect_cb(struct snd_usb_audio *chip)
844{
845 int ret;
Hemant Kumar0ef9fbb2016-01-28 11:41:42 -0800846 struct uaudio_dev *dev;
847 int card_num = chip->card_num;
Vamsi Krishna Samavedam1e634532016-09-13 14:09:37 -0700848 struct uaudio_qmi_svc *svc = uaudio_svc;
849 struct qmi_uaudio_stream_ind_msg_v01 disconnect_ind = {0};
Hemant Kumar0ef9fbb2016-01-28 11:41:42 -0800850
Hemant Kumard2a54502016-03-22 16:35:16 -0700851 pr_debug("%s: for card# %d\n", __func__, card_num);
852
Hemant Kumar0ef9fbb2016-01-28 11:41:42 -0800853 if (card_num >= SNDRV_CARDS) {
854 pr_err("%s: invalid card number\n", __func__);
Vamsi Krishna Samavedam1e634532016-09-13 14:09:37 -0700855 return;
Hemant Kumar0ef9fbb2016-01-28 11:41:42 -0800856 }
857
Vamsi Krishna Samavedam1e634532016-09-13 14:09:37 -0700858 mutex_lock(&chip->dev_lock);
Hemant Kumar0ef9fbb2016-01-28 11:41:42 -0800859 dev = &uadev[card_num];
Hemant Kumard2a54502016-03-22 16:35:16 -0700860
861 /* clean up */
862 if (!dev->udev) {
863 pr_debug("%s: no clean up required\n", __func__);
864 goto done;
865 }
866
Vamsi Krishna Samavedam1e634532016-09-13 14:09:37 -0700867 if (atomic_read(&dev->in_use)) {
868 mutex_unlock(&chip->dev_lock);
869
870 pr_debug("%s: sending qmi indication disconnect\n", __func__);
871 disconnect_ind.dev_event = USB_AUDIO_DEV_DISCONNECT_V01;
872 disconnect_ind.slot_id = dev->udev->slot_id;
Hemant Kumarc59cc942017-10-06 11:25:25 -0700873 disconnect_ind.controller_num = dev->usb_core_id;
874 disconnect_ind.controller_num_valid = 1;
Vamsi Krishna Samavedam1e634532016-09-13 14:09:37 -0700875 ret = qmi_send_ind(svc->uaudio_svc_hdl, svc->curr_conn,
876 &uaudio_stream_ind_desc, &disconnect_ind,
877 sizeof(disconnect_ind));
878 if (ret < 0) {
879 pr_err("%s: qmi send failed wiht err: %d\n",
880 __func__, ret);
881 return;
882 }
883
884 ret = wait_event_interruptible(dev->disconnect_wq,
885 !atomic_read(&dev->in_use));
886 if (ret < 0) {
887 pr_debug("%s: failed with ret %d\n", __func__, ret);
888 return;
889 }
890 mutex_lock(&chip->dev_lock);
891 }
892
Hemant Kumar89fa7b92016-10-27 19:56:31 -0700893 uaudio_dev_cleanup(dev);
Hemant Kumar0ef9fbb2016-01-28 11:41:42 -0800894done:
895 mutex_unlock(&chip->dev_lock);
896}
897
898static void uaudio_dev_release(struct kref *kref)
899{
900 struct uaudio_dev *dev = container_of(kref, struct uaudio_dev, kref);
901
Vamsi Krishna Samavedam0836aae2016-11-03 17:21:02 -0700902 pr_debug("%s for dev %pK\n", __func__, dev);
Hemant Kumard2a54502016-03-22 16:35:16 -0700903
Hemant Kumar0ef9fbb2016-01-28 11:41:42 -0800904 atomic_set(&dev->in_use, 0);
Hemant Kumard2a54502016-03-22 16:35:16 -0700905
906 clear_bit(dev->card_num, &uaudio_qdev->card_slot);
907
908 /* all audio devices are disconnected */
909 if (!uaudio_qdev->card_slot) {
910 usb_sec_event_ring_cleanup(dev->udev, uaudio_qdev->intr_num);
Hemant Kumar068cf612018-01-12 15:59:10 -0800911 uaudio_iommu_unmap(MEM_EVENT_RING, IOVA_BASE, PAGE_SIZE,
912 PAGE_SIZE);
Hemant Kumard2a54502016-03-22 16:35:16 -0700913 pr_debug("%s: all audio devices disconnected\n", __func__);
914 }
915
Hemant Kumar0ef9fbb2016-01-28 11:41:42 -0800916 wake_up(&dev->disconnect_wq);
917}
918
Hemant Kumara4f61012016-10-13 15:41:55 -0700919/* maps audio format received over QMI to asound.h based pcm format */
Hemant Kumar89fa7b92016-10-27 19:56:31 -0700920static int map_pcm_format(unsigned int fmt_received)
Hemant Kumara4f61012016-10-13 15:41:55 -0700921{
922 switch (fmt_received) {
923 case USB_QMI_PCM_FORMAT_S8:
924 return SNDRV_PCM_FORMAT_S8;
925 case USB_QMI_PCM_FORMAT_U8:
926 return SNDRV_PCM_FORMAT_U8;
927 case USB_QMI_PCM_FORMAT_S16_LE:
928 return SNDRV_PCM_FORMAT_S16_LE;
929 case USB_QMI_PCM_FORMAT_S16_BE:
930 return SNDRV_PCM_FORMAT_S16_BE;
931 case USB_QMI_PCM_FORMAT_U16_LE:
932 return SNDRV_PCM_FORMAT_U16_LE;
933 case USB_QMI_PCM_FORMAT_U16_BE:
934 return SNDRV_PCM_FORMAT_U16_BE;
935 case USB_QMI_PCM_FORMAT_S24_LE:
936 return SNDRV_PCM_FORMAT_S24_LE;
937 case USB_QMI_PCM_FORMAT_S24_BE:
938 return SNDRV_PCM_FORMAT_S24_BE;
939 case USB_QMI_PCM_FORMAT_U24_LE:
940 return SNDRV_PCM_FORMAT_U24_LE;
941 case USB_QMI_PCM_FORMAT_U24_BE:
942 return SNDRV_PCM_FORMAT_U24_BE;
943 case USB_QMI_PCM_FORMAT_S24_3LE:
944 return SNDRV_PCM_FORMAT_S24_3LE;
945 case USB_QMI_PCM_FORMAT_S24_3BE:
946 return SNDRV_PCM_FORMAT_S24_3BE;
947 case USB_QMI_PCM_FORMAT_U24_3LE:
948 return SNDRV_PCM_FORMAT_U24_3LE;
949 case USB_QMI_PCM_FORMAT_U24_3BE:
950 return SNDRV_PCM_FORMAT_U24_3BE;
951 case USB_QMI_PCM_FORMAT_S32_LE:
952 return SNDRV_PCM_FORMAT_S32_LE;
953 case USB_QMI_PCM_FORMAT_S32_BE:
954 return SNDRV_PCM_FORMAT_S32_BE;
955 case USB_QMI_PCM_FORMAT_U32_LE:
956 return SNDRV_PCM_FORMAT_U32_LE;
957 case USB_QMI_PCM_FORMAT_U32_BE:
958 return SNDRV_PCM_FORMAT_U32_BE;
959 default:
960 return -EINVAL;
961 }
962}
963
Hemant Kumarebbe6262017-01-10 19:26:40 -0800964static int info_idx_from_ifnum(int card_num, int intf_num, bool enable)
965{
966 int i;
967
968 /*
969 * default index 0 is used when info is allocated upon
970 * first enable audio stream req for a pcm device
971 */
972 if (enable && !uadev[card_num].info)
973 return 0;
974
975 for (i = 0; i < uadev[card_num].num_intf; i++) {
976 if (enable && !uadev[card_num].info[i].in_use)
977 return i;
978 else if (!enable &&
979 uadev[card_num].info[i].intf_num == intf_num)
980 return i;
981 }
982
983 return -EINVAL;
984}
985
Hemant Kumar0ef9fbb2016-01-28 11:41:42 -0800986static int handle_uaudio_stream_req(void *req_h, void *req)
987{
988 struct qmi_uaudio_stream_req_msg_v01 *req_msg;
Hemant Kumaraa2fa3c2016-07-18 16:26:48 -0700989 struct qmi_uaudio_stream_resp_msg_v01 resp = {{0}, 0};
Hemant Kumar0ef9fbb2016-01-28 11:41:42 -0800990 struct snd_usb_substream *subs;
991 struct snd_usb_audio *chip = NULL;
992 struct uaudio_qmi_svc *svc = uaudio_svc;
Hemant Kumard2a54502016-03-22 16:35:16 -0700993 struct intf_info *info;
Hemant Kumare5020482018-03-05 18:01:22 -0800994 struct usb_host_endpoint *ep;
Hemant Kumara4f61012016-10-13 15:41:55 -0700995 int pcm_format;
Hemant Kumar0ef9fbb2016-01-28 11:41:42 -0800996 u8 pcm_card_num, pcm_dev_num, direction;
Hemant Kumarebbe6262017-01-10 19:26:40 -0800997 int info_idx = -EINVAL, ret = 0;
Hemant Kumar0ef9fbb2016-01-28 11:41:42 -0800998
999 req_msg = (struct qmi_uaudio_stream_req_msg_v01 *)req;
1000
Hemant Kumaraa2fa3c2016-07-18 16:26:48 -07001001 if (!req_msg->audio_format_valid || !req_msg->bit_rate_valid ||
1002 !req_msg->number_of_ch_valid || !req_msg->xfer_buff_size_valid) {
1003 pr_err("%s: invalid request msg\n", __func__);
1004 ret = -EINVAL;
1005 goto response;
1006 }
1007
Hemant Kumar0ef9fbb2016-01-28 11:41:42 -08001008 direction = req_msg->usb_token & SND_PCM_STREAM_DIRECTION;
1009 pcm_dev_num = (req_msg->usb_token & SND_PCM_DEV_NUM_MASK) >> 8;
1010 pcm_card_num = (req_msg->usb_token & SND_PCM_CARD_NUM_MASK) >> 16;
1011
1012 pr_debug("%s:card#:%d dev#:%d dir:%d en:%d fmt:%d rate:%d #ch:%d\n",
1013 __func__, pcm_card_num, pcm_dev_num, direction, req_msg->enable,
1014 req_msg->audio_format, req_msg->bit_rate,
1015 req_msg->number_of_ch);
1016
1017 if (pcm_card_num >= SNDRV_CARDS) {
1018 pr_err("%s: invalid card # %u", __func__, pcm_card_num);
1019 ret = -EINVAL;
1020 goto response;
1021 }
1022
Hemant Kumara4f61012016-10-13 15:41:55 -07001023 pcm_format = map_pcm_format(req_msg->audio_format);
1024 if (pcm_format == -EINVAL) {
1025 pr_err("%s: unsupported pcm format received %d\n",
1026 __func__, req_msg->audio_format);
1027 ret = -EINVAL;
1028 goto response;
1029 }
1030
Hemant Kumar0ef9fbb2016-01-28 11:41:42 -08001031 subs = find_snd_usb_substream(pcm_card_num, pcm_dev_num, direction,
1032 &chip, uaudio_disconnect_cb);
1033 if (!subs || !chip || atomic_read(&chip->shutdown)) {
1034 pr_err("%s: can't find substream for card# %u, dev# %u dir%u\n",
1035 __func__, pcm_card_num, pcm_dev_num, direction);
1036 ret = -ENODEV;
1037 goto response;
1038 }
1039
1040 mutex_lock(&chip->dev_lock);
Hemant Kumarebbe6262017-01-10 19:26:40 -08001041 info_idx = info_idx_from_ifnum(pcm_card_num, subs->interface,
1042 req_msg->enable);
Hemant Kumar0ef9fbb2016-01-28 11:41:42 -08001043 if (atomic_read(&chip->shutdown) || !subs->stream || !subs->stream->pcm
1044 || !subs->stream->chip) {
1045 ret = -ENODEV;
1046 mutex_unlock(&chip->dev_lock);
1047 goto response;
1048 }
1049
Hemant Kumarebbe6262017-01-10 19:26:40 -08001050 if (req_msg->enable) {
1051 if (info_idx < 0) {
1052 pr_err("%s interface# %d already in use card# %d\n",
1053 __func__, subs->interface, pcm_card_num);
1054 ret = -EBUSY;
1055 mutex_unlock(&chip->dev_lock);
1056 goto response;
1057 }
1058 }
1059
Hemant Kumara4f61012016-10-13 15:41:55 -07001060 subs->pcm_format = pcm_format;
Hemant Kumar0ef9fbb2016-01-28 11:41:42 -08001061 subs->channels = req_msg->number_of_ch;
1062 subs->cur_rate = req_msg->bit_rate;
Hemant Kumare1578ed2016-12-14 13:19:40 -08001063 uadev[pcm_card_num].ctrl_intf = chip->ctrl_intf;
Hemant Kumar0ef9fbb2016-01-28 11:41:42 -08001064
Hemant Kumare5020482018-03-05 18:01:22 -08001065 if (!req_msg->enable) {
1066 info = &uadev[pcm_card_num].info[info_idx];
1067 if (info->data_ep_pipe) {
1068 ep = usb_pipe_endpoint(uadev[pcm_card_num].udev,
1069 info->data_ep_pipe);
1070 if (!ep)
1071 pr_debug("%s: no data ep\n", __func__);
1072 else
1073 usb_stop_endpoint(uadev[pcm_card_num].udev, ep);
1074 info->data_ep_pipe = 0;
1075 }
1076
1077 if (info->sync_ep_pipe) {
1078 ep = usb_pipe_endpoint(uadev[pcm_card_num].udev,
1079 info->sync_ep_pipe);
1080 if (!ep)
1081 pr_debug("%s: no sync ep\n", __func__);
1082 else
1083 usb_stop_endpoint(uadev[pcm_card_num].udev, ep);
1084 info->sync_ep_pipe = 0;
1085 }
1086 }
1087
Hemant Kumar0ef9fbb2016-01-28 11:41:42 -08001088 ret = snd_usb_enable_audio_stream(subs, req_msg->enable);
1089
1090 if (!ret && req_msg->enable)
Hemant Kumarebbe6262017-01-10 19:26:40 -08001091 ret = prepare_qmi_response(subs, req_msg, &resp, info_idx);
Hemant Kumar0ef9fbb2016-01-28 11:41:42 -08001092
1093 mutex_unlock(&chip->dev_lock);
1094
1095response:
1096 if (!req_msg->enable && ret != -EINVAL) {
Hemant Kumarebbe6262017-01-10 19:26:40 -08001097 if (info_idx >= 0) {
Hemant Kumard2a54502016-03-22 16:35:16 -07001098 mutex_lock(&chip->dev_lock);
Hemant Kumarebbe6262017-01-10 19:26:40 -08001099 info = &uadev[pcm_card_num].info[info_idx];
Hemant Kumar89fa7b92016-10-27 19:56:31 -07001100 uaudio_dev_intf_cleanup(uadev[pcm_card_num].udev, info);
Hemant Kumard2a54502016-03-22 16:35:16 -07001101 pr_debug("%s:release resources: intf# %d card# %d\n",
Hemant Kumarebbe6262017-01-10 19:26:40 -08001102 __func__, subs->interface, pcm_card_num);
Hemant Kumard2a54502016-03-22 16:35:16 -07001103 mutex_unlock(&chip->dev_lock);
1104 }
Hemant Kumar0ef9fbb2016-01-28 11:41:42 -08001105 if (atomic_read(&uadev[pcm_card_num].in_use))
1106 kref_put(&uadev[pcm_card_num].kref,
1107 uaudio_dev_release);
1108 }
1109
Hemant Kumaraa2fa3c2016-07-18 16:26:48 -07001110 resp.usb_token = req_msg->usb_token;
1111 resp.usb_token_valid = 1;
1112 resp.internal_status = ret;
1113 resp.internal_status_valid = 1;
1114 resp.status = ret ? USB_AUDIO_STREAM_REQ_FAILURE_V01 : ret;
1115 resp.status_valid = 1;
Hemant Kumar0ef9fbb2016-01-28 11:41:42 -08001116 ret = qmi_send_resp_from_cb(svc->uaudio_svc_hdl, svc->curr_conn, req_h,
1117 &uaudio_stream_resp_desc, &resp, sizeof(resp));
1118
1119 svc->t_resp_sent = ktime_get();
1120
1121 pr_debug("%s: t_resp sent - t_req recvd (in ms) %lld\n", __func__,
1122 ktime_to_ms(ktime_sub(svc->t_resp_sent, svc->t_request_recvd)));
1123
1124 return ret;
1125}
1126
1127static int uaudio_qmi_svc_connect_cb(struct qmi_handle *handle,
1128 void *conn_h)
1129{
1130 struct uaudio_qmi_svc *svc = uaudio_svc;
1131
1132 if (svc->uaudio_svc_hdl != handle || !conn_h) {
1133 pr_err("%s: handle mismatch\n", __func__);
1134 return -EINVAL;
1135 }
1136 if (svc->curr_conn) {
1137 pr_err("%s: Service is busy\n", __func__);
1138 return -ECONNREFUSED;
1139 }
1140 svc->curr_conn = conn_h;
1141 return 0;
1142}
1143
Hemant Kumar89fa7b92016-10-27 19:56:31 -07001144static void uaudio_qmi_disconnect_work(struct work_struct *w)
1145{
1146 struct intf_info *info;
1147 int idx, if_idx;
1148 struct snd_usb_substream *subs;
1149 struct snd_usb_audio *chip = NULL;
1150
1151 /* find all active intf for set alt 0 and cleanup usb audio dev */
1152 for (idx = 0; idx < SNDRV_CARDS; idx++) {
1153 if (!atomic_read(&uadev[idx].in_use))
1154 continue;
1155
1156 for (if_idx = 0; if_idx < uadev[idx].num_intf; if_idx++) {
1157 if (!uadev[idx].info || !uadev[idx].info[if_idx].in_use)
1158 continue;
1159 info = &uadev[idx].info[if_idx];
1160 subs = find_snd_usb_substream(info->pcm_card_num,
1161 info->pcm_dev_num,
1162 info->direction,
1163 &chip,
1164 uaudio_disconnect_cb);
1165 if (!subs || !chip || atomic_read(&chip->shutdown)) {
1166 pr_debug("%s:no subs for c#%u, dev#%u dir%u\n",
1167 __func__, info->pcm_card_num,
1168 info->pcm_dev_num,
1169 info->direction);
1170 continue;
1171 }
1172 snd_usb_enable_audio_stream(subs, 0);
1173 }
1174 atomic_set(&uadev[idx].in_use, 0);
1175 mutex_lock(&chip->dev_lock);
1176 uaudio_dev_cleanup(&uadev[idx]);
1177 mutex_unlock(&chip->dev_lock);
1178 }
1179}
1180
Hemant Kumar0ef9fbb2016-01-28 11:41:42 -08001181static int uaudio_qmi_svc_disconnect_cb(struct qmi_handle *handle,
1182 void *conn_h)
1183{
1184 struct uaudio_qmi_svc *svc = uaudio_svc;
1185
1186 if (svc->uaudio_svc_hdl != handle || svc->curr_conn != conn_h) {
1187 pr_err("%s: handle mismatch\n", __func__);
1188 return -EINVAL;
1189 }
1190
1191 svc->curr_conn = NULL;
Hemant Kumar89fa7b92016-10-27 19:56:31 -07001192 queue_work(svc->uaudio_wq, &svc->qmi_disconnect_work);
1193
Hemant Kumar0ef9fbb2016-01-28 11:41:42 -08001194 return 0;
1195}
1196
1197static int uaudio_qmi_svc_req_cb(struct qmi_handle *handle, void *conn_h,
1198 void *req_h, unsigned int msg_id, void *req)
1199{
1200 int ret;
1201 struct uaudio_qmi_svc *svc = uaudio_svc;
1202
1203 if (svc->uaudio_svc_hdl != handle || svc->curr_conn != conn_h) {
1204 pr_err("%s: handle mismatch\n", __func__);
1205 return -EINVAL;
1206 }
1207
1208 switch (msg_id) {
1209 case QMI_UAUDIO_STREAM_REQ_V01:
1210 ret = handle_uaudio_stream_req(req_h, req);
1211 break;
1212
1213 default:
1214 ret = -ENOTSUPP;
1215 break;
1216 }
1217 return ret;
1218}
1219
1220static int uaudio_qmi_svc_req_desc_cb(unsigned int msg_id,
1221 struct msg_desc **req_desc)
1222{
1223 int ret;
1224
1225 pr_debug("%s: msg_id %d\n", __func__, msg_id);
1226
1227 switch (msg_id) {
1228 case QMI_UAUDIO_STREAM_REQ_V01:
1229 *req_desc = &uaudio_stream_req_desc;
1230 ret = sizeof(struct qmi_uaudio_stream_req_msg_v01);
1231 break;
1232
1233 default:
1234 ret = -ENOTSUPP;
1235 break;
1236 }
1237 return ret;
1238}
1239
1240static void uaudio_qmi_svc_recv_msg(struct work_struct *w)
1241{
1242 int ret;
1243 struct uaudio_qmi_svc *svc = container_of(w, struct uaudio_qmi_svc,
1244 recv_msg_work);
1245
1246 do {
1247 pr_debug("%s: Notified about a Receive Event", __func__);
1248 } while ((ret = qmi_recv_msg(svc->uaudio_svc_hdl)) == 0);
1249
1250 if (ret != -ENOMSG)
1251 pr_err("%s: Error receiving message\n", __func__);
1252}
1253
1254static void uaudio_qmi_svc_ntfy(struct qmi_handle *handle,
1255 enum qmi_event_type event, void *priv)
1256{
1257 struct uaudio_qmi_svc *svc = uaudio_svc;
1258
1259 pr_debug("%s: event %d", __func__, event);
1260
1261 svc->t_request_recvd = ktime_get();
1262
1263 switch (event) {
1264 case QMI_RECV_MSG:
1265 queue_work(svc->uaudio_wq, &svc->recv_msg_work);
1266 break;
1267 default:
1268 break;
1269 }
1270}
1271
1272static struct qmi_svc_ops_options uaudio_svc_ops_options = {
1273 .version = 1,
1274 .service_id = UAUDIO_STREAM_SERVICE_ID_V01,
1275 .service_vers = UAUDIO_STREAM_SERVICE_VERS_V01,
1276 .connect_cb = uaudio_qmi_svc_connect_cb,
1277 .disconnect_cb = uaudio_qmi_svc_disconnect_cb,
1278 .req_desc_cb = uaudio_qmi_svc_req_desc_cb,
1279 .req_cb = uaudio_qmi_svc_req_cb,
1280};
1281
Hemant Kumard2a54502016-03-22 16:35:16 -07001282static int uaudio_qmi_plat_probe(struct platform_device *pdev)
1283{
1284 int ret;
1285 struct device_node *node = pdev->dev.of_node;
1286
1287 uaudio_qdev = devm_kzalloc(&pdev->dev, sizeof(struct uaudio_qmi_dev),
1288 GFP_KERNEL);
1289 if (!uaudio_qdev)
1290 return -ENOMEM;
1291
1292 uaudio_qdev->dev = &pdev->dev;
1293
1294 ret = of_property_read_u32(node, "qcom,usb-audio-stream-id",
1295 &uaudio_qdev->sid);
1296 if (ret) {
1297 dev_err(&pdev->dev, "failed to read sid.\n");
1298 return -ENODEV;
1299 }
1300
1301 ret = of_property_read_u32(node, "qcom,usb-audio-intr-num",
1302 &uaudio_qdev->intr_num);
1303 if (ret) {
1304 dev_err(&pdev->dev, "failed to read intr num.\n");
1305 return -ENODEV;
1306 }
1307
1308 uaudio_qdev->domain = iommu_domain_alloc(pdev->dev.bus);
Hemant Kumara2a80912016-08-22 19:31:35 -07001309 if (!uaudio_qdev->domain) {
1310 dev_err(&pdev->dev, "failed to allocate iommu domain\n");
Hemant Kumard2a54502016-03-22 16:35:16 -07001311 return -ENODEV;
1312 }
1313
1314 /* attach to external processor iommu */
1315 ret = iommu_attach_device(uaudio_qdev->domain, &pdev->dev);
1316 if (ret) {
1317 dev_err(&pdev->dev, "failed to attach device ret = %d\n", ret);
1318 goto free_domain;
1319 }
1320
Hemant Kumar81156ed2017-09-22 12:34:52 -07001321 /* initialize xfer ring and xfer buf iova list */
Hemant Kumard2a54502016-03-22 16:35:16 -07001322 INIT_LIST_HEAD(&uaudio_qdev->xfer_ring_list);
1323 uaudio_qdev->curr_xfer_ring_iova = IOVA_XFER_RING_BASE;
1324 uaudio_qdev->xfer_ring_iova_size =
1325 IOVA_XFER_RING_MAX - IOVA_XFER_RING_BASE;
1326
1327 INIT_LIST_HEAD(&uaudio_qdev->xfer_buf_list);
1328 uaudio_qdev->curr_xfer_buf_iova = IOVA_XFER_BUF_BASE;
1329 uaudio_qdev->xfer_buf_iova_size =
1330 IOVA_XFER_BUF_MAX - IOVA_XFER_BUF_BASE;
1331
1332 return 0;
1333
1334free_domain:
1335 iommu_domain_free(uaudio_qdev->domain);
1336 return ret;
1337}
1338
1339static int uaudio_qmi_plat_remove(struct platform_device *pdev)
1340{
1341 iommu_detach_device(uaudio_qdev->domain, &pdev->dev);
1342 iommu_domain_free(uaudio_qdev->domain);
1343 uaudio_qdev->domain = NULL;
1344
1345 return 0;
1346}
1347
1348static const struct of_device_id of_uaudio_matach[] = {
1349 {
1350 .compatible = "qcom,usb-audio-qmi-dev",
1351 },
1352 { },
1353};
1354MODULE_DEVICE_TABLE(of, of_uaudio_matach);
1355
1356static struct platform_driver uaudio_qmi_driver = {
1357 .probe = uaudio_qmi_plat_probe,
1358 .remove = uaudio_qmi_plat_remove,
1359 .driver = {
1360 .name = "uaudio-qmi",
1361 .of_match_table = of_uaudio_matach,
1362 },
1363};
1364
1365static int uaudio_qmi_svc_init(void)
Hemant Kumar0ef9fbb2016-01-28 11:41:42 -08001366{
1367 int ret;
1368 struct uaudio_qmi_svc *svc;
1369
1370 svc = kzalloc(sizeof(struct uaudio_qmi_svc), GFP_KERNEL);
1371 if (!svc)
1372 return -ENOMEM;
1373
1374 svc->uaudio_wq = create_singlethread_workqueue("uaudio_svc");
1375 if (!svc->uaudio_wq) {
1376 ret = -ENOMEM;
1377 goto free_svc;
1378 }
1379
1380 svc->uaudio_svc_hdl = qmi_handle_create(uaudio_qmi_svc_ntfy, NULL);
1381 if (!svc->uaudio_svc_hdl) {
1382 pr_err("%s: Error creating svc_hdl\n", __func__);
1383 ret = -EFAULT;
1384 goto destroy_uaudio_wq;
1385 }
1386
1387 ret = qmi_svc_register(svc->uaudio_svc_hdl, &uaudio_svc_ops_options);
1388 if (ret < 0) {
1389 pr_err("%s:Error registering uaudio svc %d\n", __func__, ret);
1390 goto destroy_svc_handle;
1391 }
1392
1393 INIT_WORK(&svc->recv_msg_work, uaudio_qmi_svc_recv_msg);
Hemant Kumar89fa7b92016-10-27 19:56:31 -07001394 INIT_WORK(&svc->qmi_disconnect_work, uaudio_qmi_disconnect_work);
Hemant Kumar0ef9fbb2016-01-28 11:41:42 -08001395
1396 uaudio_svc = svc;
1397
1398 return 0;
1399
1400destroy_svc_handle:
1401 qmi_handle_destroy(svc->uaudio_svc_hdl);
1402destroy_uaudio_wq:
1403 destroy_workqueue(svc->uaudio_wq);
1404free_svc:
1405 kfree(svc);
1406 return ret;
1407}
1408
Hemant Kumard2a54502016-03-22 16:35:16 -07001409static void uaudio_qmi_svc_exit(void)
Hemant Kumar0ef9fbb2016-01-28 11:41:42 -08001410{
1411 struct uaudio_qmi_svc *svc = uaudio_svc;
1412
1413 qmi_svc_unregister(svc->uaudio_svc_hdl);
1414 flush_workqueue(svc->uaudio_wq);
1415 qmi_handle_destroy(svc->uaudio_svc_hdl);
1416 destroy_workqueue(svc->uaudio_wq);
1417 kfree(svc);
1418 uaudio_svc = NULL;
1419}
1420
Hemant Kumard2a54502016-03-22 16:35:16 -07001421static int __init uaudio_qmi_plat_init(void)
1422{
1423 int ret;
1424
1425 ret = platform_driver_register(&uaudio_qmi_driver);
1426 if (ret)
1427 return ret;
1428
1429 return uaudio_qmi_svc_init();
1430}
1431
1432static void __exit uaudio_qmi_plat_exit(void)
1433{
1434 uaudio_qmi_svc_exit();
1435 platform_driver_unregister(&uaudio_qmi_driver);
1436}
1437
1438module_init(uaudio_qmi_plat_init);
1439module_exit(uaudio_qmi_plat_exit);
Hemant Kumar0ef9fbb2016-01-28 11:41:42 -08001440
1441MODULE_DESCRIPTION("USB AUDIO QMI Service Driver");
1442MODULE_LICENSE("GPL v2");