blob: fe29aed3766010c1270bc7f33d11534e0b90b6aa [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;
Hemant Kumarebbe6262017-01-10 19:26:40 -0800453 int ret = -ENODEV;
454 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);
468 goto err;
469 }
470
Hemant Kumarebbe6262017-01-10 19:26:40 -0800471 pcm_dev_num = (req_msg->usb_token & SND_PCM_DEV_NUM_MASK) >> 8;
472 card_num = (req_msg->usb_token & SND_PCM_CARD_NUM_MASK) >> 16;
473 xfer_buf_len = req_msg->xfer_buff_size;
Hemant Kumar89fa7b92016-10-27 19:56:31 -0700474
Hemant Kumar0ef9fbb2016-01-28 11:41:42 -0800475 alts = &iface->altsetting[subs->altset_idx];
476 altsd = get_iface_desc(alts);
477 protocol = altsd->bInterfaceProtocol;
478
479 /* get format type */
Ajay Agarwal2a39f672017-04-11 11:58:28 +0530480 if (protocol != UAC_VERSION_3) {
481 fmt = snd_usb_find_csint_desc(alts->extra, alts->extralen, NULL,
482 UAC_FORMAT_TYPE);
483 if (!fmt) {
484 pr_err("%s: %u:%d : no UAC_FORMAT_TYPE desc\n",
485 __func__, subs->interface, subs->altset_idx);
486 goto err;
487 }
Hemant Kumar0ef9fbb2016-01-28 11:41:42 -0800488 }
489
Hemant Kumare1578ed2016-12-14 13:19:40 -0800490 if (!uadev[card_num].ctrl_intf) {
491 pr_err("%s: audio ctrl intf info not cached\n", __func__);
492 goto err;
493 }
494
Ajay Agarwal2a39f672017-04-11 11:58:28 +0530495 if (protocol != UAC_VERSION_3) {
496 hdr_ptr = snd_usb_find_csint_desc(
497 uadev[card_num].ctrl_intf->extra,
498 uadev[card_num].ctrl_intf->extralen,
499 NULL, UAC_HEADER);
500 if (!hdr_ptr) {
501 pr_err("%s: no UAC_HEADER desc\n", __func__);
502 goto err;
503 }
Hemant Kumare1578ed2016-12-14 13:19:40 -0800504 }
505
Hemant Kumar0ef9fbb2016-01-28 11:41:42 -0800506 if (protocol == UAC_VERSION_1) {
507 as = snd_usb_find_csint_desc(alts->extra, alts->extralen, NULL,
508 UAC_AS_GENERAL);
509 if (!as) {
510 pr_err("%s: %u:%d : no UAC_AS_GENERAL desc\n", __func__,
511 subs->interface, subs->altset_idx);
512 goto err;
513 }
Hemant Kumaraa2fa3c2016-07-18 16:26:48 -0700514 resp->data_path_delay = as->bDelay;
515 resp->data_path_delay_valid = 1;
Hemant Kumar0ef9fbb2016-01-28 11:41:42 -0800516 fmt_v1 = (struct uac_format_type_i_discrete_descriptor *)fmt;
Hemant Kumaraa2fa3c2016-07-18 16:26:48 -0700517 resp->usb_audio_subslot_size = fmt_v1->bSubframeSize;
518 resp->usb_audio_subslot_size_valid = 1;
Hemant Kumare1578ed2016-12-14 13:19:40 -0800519
520 resp->usb_audio_spec_revision =
521 ((struct uac1_ac_header_descriptor *)hdr_ptr)->bcdADC;
522 resp->usb_audio_spec_revision_valid = 1;
Hemant Kumar0ef9fbb2016-01-28 11:41:42 -0800523 } else if (protocol == UAC_VERSION_2) {
524 fmt_v2 = (struct uac_format_type_i_ext_descriptor *)fmt;
Hemant Kumaraa2fa3c2016-07-18 16:26:48 -0700525 resp->usb_audio_subslot_size = fmt_v2->bSubslotSize;
526 resp->usb_audio_subslot_size_valid = 1;
Hemant Kumare1578ed2016-12-14 13:19:40 -0800527
528 resp->usb_audio_spec_revision =
529 ((struct uac2_ac_header_descriptor *)hdr_ptr)->bcdADC;
530 resp->usb_audio_spec_revision_valid = 1;
Ajay Agarwal2a39f672017-04-11 11:58:28 +0530531 } else if (protocol == UAC_VERSION_3) {
532 switch (le16_to_cpu(get_endpoint(alts, 0)->wMaxPacketSize)) {
533 case BADD_MAXPSIZE_SYNC_MONO_16:
534 case BADD_MAXPSIZE_SYNC_STEREO_16:
535 case BADD_MAXPSIZE_ASYNC_MONO_16:
536 case BADD_MAXPSIZE_ASYNC_STEREO_16: {
537 resp->usb_audio_subslot_size = SUBSLOTSIZE_16_BIT;
538 break;
539 }
540
541 case BADD_MAXPSIZE_SYNC_MONO_24:
542 case BADD_MAXPSIZE_SYNC_STEREO_24:
543 case BADD_MAXPSIZE_ASYNC_MONO_24:
544 case BADD_MAXPSIZE_ASYNC_STEREO_24: {
545 resp->usb_audio_subslot_size = SUBSLOTSIZE_24_BIT;
546 break;
547 }
548
549 default:
550 pr_err("%d: %u: Invalid wMaxPacketSize\n",
551 subs->interface, subs->altset_idx);
552 ret = -EINVAL;
553 goto err;
554 }
555 resp->usb_audio_subslot_size_valid = 1;
Hemant Kumar0ef9fbb2016-01-28 11:41:42 -0800556 } else {
557 pr_err("%s: unknown protocol version %x\n", __func__, protocol);
558 goto err;
559 }
560
Hemant Kumar0ef9fbb2016-01-28 11:41:42 -0800561 resp->slot_id = subs->dev->slot_id;
Hemant Kumaraa2fa3c2016-07-18 16:26:48 -0700562 resp->slot_id_valid = 1;
Hemant Kumar0ef9fbb2016-01-28 11:41:42 -0800563
564 memcpy(&resp->std_as_opr_intf_desc, &alts->desc, sizeof(alts->desc));
Hemant Kumaraa2fa3c2016-07-18 16:26:48 -0700565 resp->std_as_opr_intf_desc_valid = 1;
Hemant Kumar0ef9fbb2016-01-28 11:41:42 -0800566
567 ep = usb_pipe_endpoint(subs->dev, subs->data_endpoint->pipe);
568 if (!ep) {
569 pr_err("%s: data ep # %d context is null\n", __func__,
570 subs->data_endpoint->ep_num);
571 goto err;
572 }
Hemant Kumarc08fda62017-11-14 20:20:04 -0800573 data_ep_pipe = subs->data_endpoint->pipe;
Hemant Kumar0ef9fbb2016-01-28 11:41:42 -0800574 memcpy(&resp->std_as_data_ep_desc, &ep->desc, sizeof(ep->desc));
Hemant Kumaraa2fa3c2016-07-18 16:26:48 -0700575 resp->std_as_data_ep_desc_valid = 1;
Hemant Kumar0ef9fbb2016-01-28 11:41:42 -0800576
Hemant Kumar1346a802017-09-22 15:03:45 -0700577 tr_data_pa = usb_get_xfer_ring_phys_addr(subs->dev, ep, &dma);
578 if (!tr_data_pa) {
Hemant Kumard2a54502016-03-22 16:35:16 -0700579 pr_err("%s:failed to get data ep ring dma address\n", __func__);
580 goto err;
581 }
582
Hemant Kumar1346a802017-09-22 15:03:45 -0700583 resp->xhci_mem_info.tr_data.pa = dma;
Hemant Kumard2a54502016-03-22 16:35:16 -0700584
Hemant Kumar0ef9fbb2016-01-28 11:41:42 -0800585 if (subs->sync_endpoint) {
586 ep = usb_pipe_endpoint(subs->dev, subs->sync_endpoint->pipe);
587 if (!ep) {
Hemant Kumar44cefc52016-12-06 18:34:40 -0800588 pr_debug("%s: implicit fb on data ep\n", __func__);
589 goto skip_sync_ep;
Hemant Kumar0ef9fbb2016-01-28 11:41:42 -0800590 }
Hemant Kumarc08fda62017-11-14 20:20:04 -0800591 sync_ep_pipe = subs->sync_endpoint->pipe;
Hemant Kumar0ef9fbb2016-01-28 11:41:42 -0800592 memcpy(&resp->std_as_sync_ep_desc, &ep->desc, sizeof(ep->desc));
Hemant Kumaraa2fa3c2016-07-18 16:26:48 -0700593 resp->std_as_sync_ep_desc_valid = 1;
594
Hemant Kumar1346a802017-09-22 15:03:45 -0700595 tr_sync_pa = usb_get_xfer_ring_phys_addr(subs->dev, ep, &dma);
596 if (!tr_sync_pa) {
Hemant Kumard2a54502016-03-22 16:35:16 -0700597 pr_err("%s:failed to get sync ep ring dma address\n",
598 __func__);
599 goto err;
600 }
Hemant Kumar1346a802017-09-22 15:03:45 -0700601 resp->xhci_mem_info.tr_sync.pa = dma;
Hemant Kumar0ef9fbb2016-01-28 11:41:42 -0800602 }
603
Hemant Kumar44cefc52016-12-06 18:34:40 -0800604skip_sync_ep:
Hemant Kumard2a54502016-03-22 16:35:16 -0700605 resp->interrupter_num = uaudio_qdev->intr_num;
Hemant Kumaraa2fa3c2016-07-18 16:26:48 -0700606 resp->interrupter_num_valid = 1;
Hemant Kumard2a54502016-03-22 16:35:16 -0700607
Hemant Kumar746cc972017-08-17 17:34:05 -0700608 ret = usb_get_controller_id(subs->dev);
609 if (ret < 0)
610 goto err;
611
612 resp->controller_num = ret;
613 resp->controller_num_valid = 1;
614
Hemant Kumard2a54502016-03-22 16:35:16 -0700615 /* map xhci data structures PA memory to iova */
616
617 /* event ring */
618 ret = usb_sec_event_ring_setup(subs->dev, resp->interrupter_num);
619 if (ret) {
620 pr_err("%s: failed to setup sec event ring ret %d\n", __func__,
621 ret);
622 goto err;
623 }
Hemant Kumar1346a802017-09-22 15:03:45 -0700624 xhci_pa = usb_get_sec_event_ring_phys_addr(subs->dev,
625 resp->interrupter_num, &dma);
Hemant Kumard2a54502016-03-22 16:35:16 -0700626 if (!xhci_pa) {
627 pr_err("%s: failed to get sec event ring dma address\n",
628 __func__);
629 goto err;
630 }
631
Hemant Kumar068cf612018-01-12 15:59:10 -0800632 va = uaudio_iommu_map(MEM_EVENT_RING, xhci_pa, PAGE_SIZE, NULL);
Hemant Kumard2a54502016-03-22 16:35:16 -0700633 if (!va)
634 goto err;
635
636 resp->xhci_mem_info.evt_ring.va = PREPEND_SID_TO_IOVA(va,
637 uaudio_qdev->sid);
Hemant Kumar1346a802017-09-22 15:03:45 -0700638 resp->xhci_mem_info.evt_ring.pa = dma;
Hemant Kumard2a54502016-03-22 16:35:16 -0700639 resp->xhci_mem_info.evt_ring.size = PAGE_SIZE;
Liangliang Lu0ae5cc32018-07-17 13:26:46 +0800640 uaudio_qdev->er_mapped = true;
Hemant Kumard2a54502016-03-22 16:35:16 -0700641
Hemant Kumar81156ed2017-09-22 12:34:52 -0700642 resp->speed_info = get_speed_info(subs->dev->speed);
643 if (resp->speed_info == USB_AUDIO_DEVICE_SPEED_INVALID_V01)
Hemant Kumard2a54502016-03-22 16:35:16 -0700644 goto unmap_er;
Hemant Kumard2a54502016-03-22 16:35:16 -0700645
Hemant Kumar81156ed2017-09-22 12:34:52 -0700646 resp->speed_info_valid = 1;
Hemant Kumard2a54502016-03-22 16:35:16 -0700647
648 /* data transfer ring */
Hemant Kumar068cf612018-01-12 15:59:10 -0800649 va = uaudio_iommu_map(MEM_XFER_RING, tr_data_pa, PAGE_SIZE, NULL);
Hemant Kumard2a54502016-03-22 16:35:16 -0700650 if (!va)
Hemant Kumar81156ed2017-09-22 12:34:52 -0700651 goto unmap_er;
Hemant Kumard2a54502016-03-22 16:35:16 -0700652
653 tr_data_va = va;
654 resp->xhci_mem_info.tr_data.va = PREPEND_SID_TO_IOVA(va,
655 uaudio_qdev->sid);
656 resp->xhci_mem_info.tr_data.size = PAGE_SIZE;
657
658 /* sync transfer ring */
659 if (!resp->xhci_mem_info.tr_sync.pa)
660 goto skip_sync;
661
662 xhci_pa = resp->xhci_mem_info.tr_sync.pa;
Hemant Kumar068cf612018-01-12 15:59:10 -0800663 va = uaudio_iommu_map(MEM_XFER_RING, tr_sync_pa, PAGE_SIZE, NULL);
Hemant Kumard2a54502016-03-22 16:35:16 -0700664 if (!va)
665 goto unmap_data;
666
667 tr_sync_va = va;
668 resp->xhci_mem_info.tr_sync.va = PREPEND_SID_TO_IOVA(va,
669 uaudio_qdev->sid);
670 resp->xhci_mem_info.tr_sync.size = PAGE_SIZE;
671
672skip_sync:
673 /* xfer buffer, multiple of 4K only */
674 if (!xfer_buf_len)
675 xfer_buf_len = PAGE_SIZE;
676
677 mult = xfer_buf_len / PAGE_SIZE;
678 remainder = xfer_buf_len % PAGE_SIZE;
679 len = mult * PAGE_SIZE;
680 len += remainder ? PAGE_SIZE : 0;
681
682 if (len > MAX_XFER_BUFF_LEN) {
683 pr_err("%s: req buf len %d > max buf len %lu, setting %lu\n",
684 __func__, len, MAX_XFER_BUFF_LEN, MAX_XFER_BUFF_LEN);
685 len = MAX_XFER_BUFF_LEN;
686 }
687
688 xfer_buf = usb_alloc_coherent(subs->dev, len, GFP_KERNEL, &xfer_buf_pa);
689 if (!xfer_buf)
690 goto unmap_sync;
691
Hemant Kumar1346a802017-09-22 15:03:45 -0700692 dma_get_sgtable(subs->dev->bus->sysdev, &sgt, xfer_buf, xfer_buf_pa,
693 len);
Hemant Kumar068cf612018-01-12 15:59:10 -0800694 va = uaudio_iommu_map(MEM_XFER_BUF, xfer_buf_pa, len, &sgt);
695 if (!va)
696 goto unmap_sync;
Hemant Kumar1346a802017-09-22 15:03:45 -0700697
Hemant Kumard2a54502016-03-22 16:35:16 -0700698 resp->xhci_mem_info.xfer_buff.pa = xfer_buf_pa;
699 resp->xhci_mem_info.xfer_buff.size = len;
700
Hemant Kumard2a54502016-03-22 16:35:16 -0700701 resp->xhci_mem_info.xfer_buff.va = PREPEND_SID_TO_IOVA(va,
702 uaudio_qdev->sid);
703
Hemant Kumaraa2fa3c2016-07-18 16:26:48 -0700704 resp->xhci_mem_info_valid = 1;
705
Hemant Kumar1346a802017-09-22 15:03:45 -0700706 sg_free_table(&sgt);
707
Hemant Kumar0ef9fbb2016-01-28 11:41:42 -0800708 if (!atomic_read(&uadev[card_num].in_use)) {
709 kref_init(&uadev[card_num].kref);
710 init_waitqueue_head(&uadev[card_num].disconnect_wq);
Hemant Kumard2a54502016-03-22 16:35:16 -0700711 uadev[card_num].num_intf =
712 subs->dev->config->desc.bNumInterfaces;
713 uadev[card_num].info =
714 kzalloc(sizeof(struct intf_info) *
715 uadev[card_num].num_intf, GFP_KERNEL);
716 if (!uadev[card_num].info) {
717 ret = -ENOMEM;
Hemant Kumar068cf612018-01-12 15:59:10 -0800718 goto unmap_sync;
Hemant Kumard2a54502016-03-22 16:35:16 -0700719 }
720 uadev[card_num].udev = subs->dev;
Hemant Kumar0ef9fbb2016-01-28 11:41:42 -0800721 atomic_set(&uadev[card_num].in_use, 1);
722 } else {
723 kref_get(&uadev[card_num].kref);
724 }
725
Hemant Kumard2a54502016-03-22 16:35:16 -0700726 uadev[card_num].card_num = card_num;
Hemant Kumarc59cc942017-10-06 11:25:25 -0700727 uadev[card_num].usb_core_id = resp->controller_num;
Hemant Kumard2a54502016-03-22 16:35:16 -0700728
729 /* cache intf specific info to use it for unmap and free xfer buf */
Hemant Kumarebbe6262017-01-10 19:26:40 -0800730 uadev[card_num].info[info_idx].data_xfer_ring_va = tr_data_va;
731 uadev[card_num].info[info_idx].data_xfer_ring_size = PAGE_SIZE;
732 uadev[card_num].info[info_idx].sync_xfer_ring_va = tr_sync_va;
733 uadev[card_num].info[info_idx].sync_xfer_ring_size = PAGE_SIZE;
Hemant Kumar1346a802017-09-22 15:03:45 -0700734 uadev[card_num].info[info_idx].xfer_buf_va = va;
Hemant Kumarebbe6262017-01-10 19:26:40 -0800735 uadev[card_num].info[info_idx].xfer_buf_pa = xfer_buf_pa;
736 uadev[card_num].info[info_idx].xfer_buf_size = len;
Hemant Kumarc08fda62017-11-14 20:20:04 -0800737 uadev[card_num].info[info_idx].data_ep_pipe = data_ep_pipe;
738 uadev[card_num].info[info_idx].sync_ep_pipe = sync_ep_pipe;
Hemant Kumarebbe6262017-01-10 19:26:40 -0800739 uadev[card_num].info[info_idx].xfer_buf = xfer_buf;
740 uadev[card_num].info[info_idx].pcm_card_num = card_num;
741 uadev[card_num].info[info_idx].pcm_dev_num = pcm_dev_num;
742 uadev[card_num].info[info_idx].direction = subs->direction;
743 uadev[card_num].info[info_idx].intf_num = subs->interface;
744 uadev[card_num].info[info_idx].in_use = true;
Hemant Kumard2a54502016-03-22 16:35:16 -0700745
746 set_bit(card_num, &uaudio_qdev->card_slot);
747
Hemant Kumar0ef9fbb2016-01-28 11:41:42 -0800748 return 0;
Hemant Kumard2a54502016-03-22 16:35:16 -0700749
Hemant Kumard2a54502016-03-22 16:35:16 -0700750unmap_sync:
751 usb_free_coherent(subs->dev, len, xfer_buf, xfer_buf_pa);
Hemant Kumar068cf612018-01-12 15:59:10 -0800752 uaudio_iommu_unmap(MEM_XFER_RING, tr_sync_va, PAGE_SIZE, PAGE_SIZE);
Hemant Kumard2a54502016-03-22 16:35:16 -0700753unmap_data:
Hemant Kumar068cf612018-01-12 15:59:10 -0800754 uaudio_iommu_unmap(MEM_XFER_RING, tr_data_va, PAGE_SIZE, PAGE_SIZE);
Hemant Kumard2a54502016-03-22 16:35:16 -0700755unmap_er:
Hemant Kumar068cf612018-01-12 15:59:10 -0800756 uaudio_iommu_unmap(MEM_EVENT_RING, IOVA_BASE, PAGE_SIZE, PAGE_SIZE);
Hemant Kumar0ef9fbb2016-01-28 11:41:42 -0800757err:
Hemant Kumard2a54502016-03-22 16:35:16 -0700758 return ret;
Hemant Kumar0ef9fbb2016-01-28 11:41:42 -0800759}
760
Hemant Kumar89fa7b92016-10-27 19:56:31 -0700761static void uaudio_dev_intf_cleanup(struct usb_device *udev,
762 struct intf_info *info)
Hemant Kumar0ef9fbb2016-01-28 11:41:42 -0800763{
Hemant Kumarc08fda62017-11-14 20:20:04 -0800764
Hemant Kumar89fa7b92016-10-27 19:56:31 -0700765 uaudio_iommu_unmap(MEM_XFER_RING, info->data_xfer_ring_va,
Hemant Kumar068cf612018-01-12 15:59:10 -0800766 info->data_xfer_ring_size, info->data_xfer_ring_size);
Hemant Kumar89fa7b92016-10-27 19:56:31 -0700767 info->data_xfer_ring_va = 0;
768 info->data_xfer_ring_size = 0;
769
770 uaudio_iommu_unmap(MEM_XFER_RING, info->sync_xfer_ring_va,
Hemant Kumar068cf612018-01-12 15:59:10 -0800771 info->sync_xfer_ring_size, info->sync_xfer_ring_size);
Hemant Kumar89fa7b92016-10-27 19:56:31 -0700772 info->sync_xfer_ring_va = 0;
773 info->sync_xfer_ring_size = 0;
774
775 uaudio_iommu_unmap(MEM_XFER_BUF, info->xfer_buf_va,
Hemant Kumar068cf612018-01-12 15:59:10 -0800776 info->xfer_buf_size, info->xfer_buf_size);
Hemant Kumar89fa7b92016-10-27 19:56:31 -0700777 info->xfer_buf_va = 0;
778
779 usb_free_coherent(udev, info->xfer_buf_size,
780 info->xfer_buf, info->xfer_buf_pa);
781 info->xfer_buf_size = 0;
782 info->xfer_buf = NULL;
783 info->xfer_buf_pa = 0;
784
785 info->in_use = false;
786}
787
788static void uaudio_dev_cleanup(struct uaudio_dev *dev)
789{
790 int if_idx;
791
792 /* free xfer buffer and unmap xfer ring and buf per interface */
793 for (if_idx = 0; if_idx < dev->num_intf; if_idx++) {
794 if (!dev->info[if_idx].in_use)
795 continue;
796 uaudio_dev_intf_cleanup(dev->udev, &dev->info[if_idx]);
797 pr_debug("%s: release resources: intf# %d card# %d\n", __func__,
Hemant Kumarebbe6262017-01-10 19:26:40 -0800798 dev->info[if_idx].intf_num, dev->card_num);
Hemant Kumar89fa7b92016-10-27 19:56:31 -0700799 }
800
Hemant Kumar89fa7b92016-10-27 19:56:31 -0700801 dev->num_intf = 0;
802
803 /* free interface info */
804 kfree(dev->info);
805 dev->info = NULL;
806
807 clear_bit(dev->card_num, &uaudio_qdev->card_slot);
808
809 /* all audio devices are disconnected */
810 if (!uaudio_qdev->card_slot) {
Hemant Kumar068cf612018-01-12 15:59:10 -0800811 uaudio_iommu_unmap(MEM_EVENT_RING, IOVA_BASE, PAGE_SIZE,
812 PAGE_SIZE);
Hemant Kumar89fa7b92016-10-27 19:56:31 -0700813 usb_sec_event_ring_cleanup(dev->udev, uaudio_qdev->intr_num);
814 pr_debug("%s: all audio devices disconnected\n", __func__);
815 }
816
817 dev->udev = NULL;
818}
819
820static void uaudio_disconnect_cb(struct snd_usb_audio *chip)
821{
822 int ret;
Hemant Kumar0ef9fbb2016-01-28 11:41:42 -0800823 struct uaudio_dev *dev;
824 int card_num = chip->card_num;
Vamsi Krishna Samavedam1e634532016-09-13 14:09:37 -0700825 struct uaudio_qmi_svc *svc = uaudio_svc;
826 struct qmi_uaudio_stream_ind_msg_v01 disconnect_ind = {0};
Hemant Kumar0ef9fbb2016-01-28 11:41:42 -0800827
Hemant Kumard2a54502016-03-22 16:35:16 -0700828 pr_debug("%s: for card# %d\n", __func__, card_num);
829
Hemant Kumar0ef9fbb2016-01-28 11:41:42 -0800830 if (card_num >= SNDRV_CARDS) {
831 pr_err("%s: invalid card number\n", __func__);
Vamsi Krishna Samavedam1e634532016-09-13 14:09:37 -0700832 return;
Hemant Kumar0ef9fbb2016-01-28 11:41:42 -0800833 }
834
Vamsi Krishna Samavedam1e634532016-09-13 14:09:37 -0700835 mutex_lock(&chip->dev_lock);
Hemant Kumar0ef9fbb2016-01-28 11:41:42 -0800836 dev = &uadev[card_num];
Hemant Kumard2a54502016-03-22 16:35:16 -0700837
838 /* clean up */
839 if (!dev->udev) {
840 pr_debug("%s: no clean up required\n", __func__);
841 goto done;
842 }
843
Vamsi Krishna Samavedam1e634532016-09-13 14:09:37 -0700844 if (atomic_read(&dev->in_use)) {
845 mutex_unlock(&chip->dev_lock);
846
847 pr_debug("%s: sending qmi indication disconnect\n", __func__);
848 disconnect_ind.dev_event = USB_AUDIO_DEV_DISCONNECT_V01;
849 disconnect_ind.slot_id = dev->udev->slot_id;
Hemant Kumarc59cc942017-10-06 11:25:25 -0700850 disconnect_ind.controller_num = dev->usb_core_id;
851 disconnect_ind.controller_num_valid = 1;
Vamsi Krishna Samavedam1e634532016-09-13 14:09:37 -0700852 ret = qmi_send_ind(svc->uaudio_svc_hdl, svc->curr_conn,
853 &uaudio_stream_ind_desc, &disconnect_ind,
854 sizeof(disconnect_ind));
855 if (ret < 0) {
856 pr_err("%s: qmi send failed wiht err: %d\n",
857 __func__, ret);
858 return;
859 }
860
861 ret = wait_event_interruptible(dev->disconnect_wq,
862 !atomic_read(&dev->in_use));
863 if (ret < 0) {
864 pr_debug("%s: failed with ret %d\n", __func__, ret);
865 return;
866 }
867 mutex_lock(&chip->dev_lock);
868 }
869
Hemant Kumar89fa7b92016-10-27 19:56:31 -0700870 uaudio_dev_cleanup(dev);
Hemant Kumar0ef9fbb2016-01-28 11:41:42 -0800871done:
872 mutex_unlock(&chip->dev_lock);
873}
874
875static void uaudio_dev_release(struct kref *kref)
876{
877 struct uaudio_dev *dev = container_of(kref, struct uaudio_dev, kref);
878
Vamsi Krishna Samavedam0836aae2016-11-03 17:21:02 -0700879 pr_debug("%s for dev %pK\n", __func__, dev);
Hemant Kumard2a54502016-03-22 16:35:16 -0700880
Hemant Kumar0ef9fbb2016-01-28 11:41:42 -0800881 atomic_set(&dev->in_use, 0);
Hemant Kumard2a54502016-03-22 16:35:16 -0700882
883 clear_bit(dev->card_num, &uaudio_qdev->card_slot);
884
885 /* all audio devices are disconnected */
886 if (!uaudio_qdev->card_slot) {
887 usb_sec_event_ring_cleanup(dev->udev, uaudio_qdev->intr_num);
Hemant Kumar068cf612018-01-12 15:59:10 -0800888 uaudio_iommu_unmap(MEM_EVENT_RING, IOVA_BASE, PAGE_SIZE,
889 PAGE_SIZE);
Hemant Kumard2a54502016-03-22 16:35:16 -0700890 pr_debug("%s: all audio devices disconnected\n", __func__);
891 }
892
Hemant Kumar0ef9fbb2016-01-28 11:41:42 -0800893 wake_up(&dev->disconnect_wq);
894}
895
Hemant Kumara4f61012016-10-13 15:41:55 -0700896/* maps audio format received over QMI to asound.h based pcm format */
Hemant Kumar89fa7b92016-10-27 19:56:31 -0700897static int map_pcm_format(unsigned int fmt_received)
Hemant Kumara4f61012016-10-13 15:41:55 -0700898{
899 switch (fmt_received) {
900 case USB_QMI_PCM_FORMAT_S8:
901 return SNDRV_PCM_FORMAT_S8;
902 case USB_QMI_PCM_FORMAT_U8:
903 return SNDRV_PCM_FORMAT_U8;
904 case USB_QMI_PCM_FORMAT_S16_LE:
905 return SNDRV_PCM_FORMAT_S16_LE;
906 case USB_QMI_PCM_FORMAT_S16_BE:
907 return SNDRV_PCM_FORMAT_S16_BE;
908 case USB_QMI_PCM_FORMAT_U16_LE:
909 return SNDRV_PCM_FORMAT_U16_LE;
910 case USB_QMI_PCM_FORMAT_U16_BE:
911 return SNDRV_PCM_FORMAT_U16_BE;
912 case USB_QMI_PCM_FORMAT_S24_LE:
913 return SNDRV_PCM_FORMAT_S24_LE;
914 case USB_QMI_PCM_FORMAT_S24_BE:
915 return SNDRV_PCM_FORMAT_S24_BE;
916 case USB_QMI_PCM_FORMAT_U24_LE:
917 return SNDRV_PCM_FORMAT_U24_LE;
918 case USB_QMI_PCM_FORMAT_U24_BE:
919 return SNDRV_PCM_FORMAT_U24_BE;
920 case USB_QMI_PCM_FORMAT_S24_3LE:
921 return SNDRV_PCM_FORMAT_S24_3LE;
922 case USB_QMI_PCM_FORMAT_S24_3BE:
923 return SNDRV_PCM_FORMAT_S24_3BE;
924 case USB_QMI_PCM_FORMAT_U24_3LE:
925 return SNDRV_PCM_FORMAT_U24_3LE;
926 case USB_QMI_PCM_FORMAT_U24_3BE:
927 return SNDRV_PCM_FORMAT_U24_3BE;
928 case USB_QMI_PCM_FORMAT_S32_LE:
929 return SNDRV_PCM_FORMAT_S32_LE;
930 case USB_QMI_PCM_FORMAT_S32_BE:
931 return SNDRV_PCM_FORMAT_S32_BE;
932 case USB_QMI_PCM_FORMAT_U32_LE:
933 return SNDRV_PCM_FORMAT_U32_LE;
934 case USB_QMI_PCM_FORMAT_U32_BE:
935 return SNDRV_PCM_FORMAT_U32_BE;
936 default:
937 return -EINVAL;
938 }
939}
940
Hemant Kumarebbe6262017-01-10 19:26:40 -0800941static int info_idx_from_ifnum(int card_num, int intf_num, bool enable)
942{
943 int i;
944
945 /*
946 * default index 0 is used when info is allocated upon
947 * first enable audio stream req for a pcm device
948 */
949 if (enable && !uadev[card_num].info)
950 return 0;
951
952 for (i = 0; i < uadev[card_num].num_intf; i++) {
953 if (enable && !uadev[card_num].info[i].in_use)
954 return i;
955 else if (!enable &&
956 uadev[card_num].info[i].intf_num == intf_num)
957 return i;
958 }
959
960 return -EINVAL;
961}
962
Hemant Kumar0ef9fbb2016-01-28 11:41:42 -0800963static int handle_uaudio_stream_req(void *req_h, void *req)
964{
965 struct qmi_uaudio_stream_req_msg_v01 *req_msg;
Hemant Kumaraa2fa3c2016-07-18 16:26:48 -0700966 struct qmi_uaudio_stream_resp_msg_v01 resp = {{0}, 0};
Hemant Kumar0ef9fbb2016-01-28 11:41:42 -0800967 struct snd_usb_substream *subs;
968 struct snd_usb_audio *chip = NULL;
969 struct uaudio_qmi_svc *svc = uaudio_svc;
Hemant Kumard2a54502016-03-22 16:35:16 -0700970 struct intf_info *info;
Hemant Kumare5020482018-03-05 18:01:22 -0800971 struct usb_host_endpoint *ep;
Hemant Kumara4f61012016-10-13 15:41:55 -0700972 int pcm_format;
Hemant Kumar0ef9fbb2016-01-28 11:41:42 -0800973 u8 pcm_card_num, pcm_dev_num, direction;
Hemant Kumarebbe6262017-01-10 19:26:40 -0800974 int info_idx = -EINVAL, ret = 0;
Hemant Kumar0ef9fbb2016-01-28 11:41:42 -0800975
976 req_msg = (struct qmi_uaudio_stream_req_msg_v01 *)req;
977
Hemant Kumaraa2fa3c2016-07-18 16:26:48 -0700978 if (!req_msg->audio_format_valid || !req_msg->bit_rate_valid ||
979 !req_msg->number_of_ch_valid || !req_msg->xfer_buff_size_valid) {
980 pr_err("%s: invalid request msg\n", __func__);
981 ret = -EINVAL;
982 goto response;
983 }
984
Hemant Kumar0ef9fbb2016-01-28 11:41:42 -0800985 direction = req_msg->usb_token & SND_PCM_STREAM_DIRECTION;
986 pcm_dev_num = (req_msg->usb_token & SND_PCM_DEV_NUM_MASK) >> 8;
987 pcm_card_num = (req_msg->usb_token & SND_PCM_CARD_NUM_MASK) >> 16;
988
989 pr_debug("%s:card#:%d dev#:%d dir:%d en:%d fmt:%d rate:%d #ch:%d\n",
990 __func__, pcm_card_num, pcm_dev_num, direction, req_msg->enable,
991 req_msg->audio_format, req_msg->bit_rate,
992 req_msg->number_of_ch);
993
994 if (pcm_card_num >= SNDRV_CARDS) {
995 pr_err("%s: invalid card # %u", __func__, pcm_card_num);
996 ret = -EINVAL;
997 goto response;
998 }
999
Hemant Kumara4f61012016-10-13 15:41:55 -07001000 pcm_format = map_pcm_format(req_msg->audio_format);
1001 if (pcm_format == -EINVAL) {
1002 pr_err("%s: unsupported pcm format received %d\n",
1003 __func__, req_msg->audio_format);
1004 ret = -EINVAL;
1005 goto response;
1006 }
1007
Hemant Kumar0ef9fbb2016-01-28 11:41:42 -08001008 subs = find_snd_usb_substream(pcm_card_num, pcm_dev_num, direction,
1009 &chip, uaudio_disconnect_cb);
1010 if (!subs || !chip || atomic_read(&chip->shutdown)) {
1011 pr_err("%s: can't find substream for card# %u, dev# %u dir%u\n",
1012 __func__, pcm_card_num, pcm_dev_num, direction);
1013 ret = -ENODEV;
1014 goto response;
1015 }
1016
1017 mutex_lock(&chip->dev_lock);
Hemant Kumarebbe6262017-01-10 19:26:40 -08001018 info_idx = info_idx_from_ifnum(pcm_card_num, subs->interface,
1019 req_msg->enable);
Hemant Kumar0ef9fbb2016-01-28 11:41:42 -08001020 if (atomic_read(&chip->shutdown) || !subs->stream || !subs->stream->pcm
1021 || !subs->stream->chip) {
1022 ret = -ENODEV;
1023 mutex_unlock(&chip->dev_lock);
1024 goto response;
1025 }
1026
Hemant Kumarebbe6262017-01-10 19:26:40 -08001027 if (req_msg->enable) {
1028 if (info_idx < 0) {
1029 pr_err("%s interface# %d already in use card# %d\n",
1030 __func__, subs->interface, pcm_card_num);
1031 ret = -EBUSY;
1032 mutex_unlock(&chip->dev_lock);
1033 goto response;
1034 }
1035 }
1036
Hemant Kumara4f61012016-10-13 15:41:55 -07001037 subs->pcm_format = pcm_format;
Hemant Kumar0ef9fbb2016-01-28 11:41:42 -08001038 subs->channels = req_msg->number_of_ch;
1039 subs->cur_rate = req_msg->bit_rate;
Hemant Kumare1578ed2016-12-14 13:19:40 -08001040 uadev[pcm_card_num].ctrl_intf = chip->ctrl_intf;
Hemant Kumar0ef9fbb2016-01-28 11:41:42 -08001041
Hemant Kumare5020482018-03-05 18:01:22 -08001042 if (!req_msg->enable) {
1043 info = &uadev[pcm_card_num].info[info_idx];
1044 if (info->data_ep_pipe) {
1045 ep = usb_pipe_endpoint(uadev[pcm_card_num].udev,
1046 info->data_ep_pipe);
1047 if (!ep)
1048 pr_debug("%s: no data ep\n", __func__);
1049 else
1050 usb_stop_endpoint(uadev[pcm_card_num].udev, ep);
1051 info->data_ep_pipe = 0;
1052 }
1053
1054 if (info->sync_ep_pipe) {
1055 ep = usb_pipe_endpoint(uadev[pcm_card_num].udev,
1056 info->sync_ep_pipe);
1057 if (!ep)
1058 pr_debug("%s: no sync ep\n", __func__);
1059 else
1060 usb_stop_endpoint(uadev[pcm_card_num].udev, ep);
1061 info->sync_ep_pipe = 0;
1062 }
1063 }
1064
Hemant Kumar0ef9fbb2016-01-28 11:41:42 -08001065 ret = snd_usb_enable_audio_stream(subs, req_msg->enable);
1066
1067 if (!ret && req_msg->enable)
Hemant Kumarebbe6262017-01-10 19:26:40 -08001068 ret = prepare_qmi_response(subs, req_msg, &resp, info_idx);
Hemant Kumar0ef9fbb2016-01-28 11:41:42 -08001069
1070 mutex_unlock(&chip->dev_lock);
1071
1072response:
1073 if (!req_msg->enable && ret != -EINVAL) {
Hemant Kumarebbe6262017-01-10 19:26:40 -08001074 if (info_idx >= 0) {
Hemant Kumard2a54502016-03-22 16:35:16 -07001075 mutex_lock(&chip->dev_lock);
Hemant Kumarebbe6262017-01-10 19:26:40 -08001076 info = &uadev[pcm_card_num].info[info_idx];
Hemant Kumar89fa7b92016-10-27 19:56:31 -07001077 uaudio_dev_intf_cleanup(uadev[pcm_card_num].udev, info);
Hemant Kumard2a54502016-03-22 16:35:16 -07001078 pr_debug("%s:release resources: intf# %d card# %d\n",
Hemant Kumarebbe6262017-01-10 19:26:40 -08001079 __func__, subs->interface, pcm_card_num);
Hemant Kumard2a54502016-03-22 16:35:16 -07001080 mutex_unlock(&chip->dev_lock);
1081 }
Hemant Kumar0ef9fbb2016-01-28 11:41:42 -08001082 if (atomic_read(&uadev[pcm_card_num].in_use))
1083 kref_put(&uadev[pcm_card_num].kref,
1084 uaudio_dev_release);
1085 }
1086
Hemant Kumaraa2fa3c2016-07-18 16:26:48 -07001087 resp.usb_token = req_msg->usb_token;
1088 resp.usb_token_valid = 1;
1089 resp.internal_status = ret;
1090 resp.internal_status_valid = 1;
1091 resp.status = ret ? USB_AUDIO_STREAM_REQ_FAILURE_V01 : ret;
1092 resp.status_valid = 1;
Hemant Kumar0ef9fbb2016-01-28 11:41:42 -08001093 ret = qmi_send_resp_from_cb(svc->uaudio_svc_hdl, svc->curr_conn, req_h,
1094 &uaudio_stream_resp_desc, &resp, sizeof(resp));
1095
1096 svc->t_resp_sent = ktime_get();
1097
1098 pr_debug("%s: t_resp sent - t_req recvd (in ms) %lld\n", __func__,
1099 ktime_to_ms(ktime_sub(svc->t_resp_sent, svc->t_request_recvd)));
1100
1101 return ret;
1102}
1103
1104static int uaudio_qmi_svc_connect_cb(struct qmi_handle *handle,
1105 void *conn_h)
1106{
1107 struct uaudio_qmi_svc *svc = uaudio_svc;
1108
1109 if (svc->uaudio_svc_hdl != handle || !conn_h) {
1110 pr_err("%s: handle mismatch\n", __func__);
1111 return -EINVAL;
1112 }
1113 if (svc->curr_conn) {
1114 pr_err("%s: Service is busy\n", __func__);
1115 return -ECONNREFUSED;
1116 }
1117 svc->curr_conn = conn_h;
1118 return 0;
1119}
1120
Hemant Kumar89fa7b92016-10-27 19:56:31 -07001121static void uaudio_qmi_disconnect_work(struct work_struct *w)
1122{
1123 struct intf_info *info;
1124 int idx, if_idx;
1125 struct snd_usb_substream *subs;
1126 struct snd_usb_audio *chip = NULL;
1127
1128 /* find all active intf for set alt 0 and cleanup usb audio dev */
1129 for (idx = 0; idx < SNDRV_CARDS; idx++) {
1130 if (!atomic_read(&uadev[idx].in_use))
1131 continue;
1132
1133 for (if_idx = 0; if_idx < uadev[idx].num_intf; if_idx++) {
1134 if (!uadev[idx].info || !uadev[idx].info[if_idx].in_use)
1135 continue;
1136 info = &uadev[idx].info[if_idx];
1137 subs = find_snd_usb_substream(info->pcm_card_num,
1138 info->pcm_dev_num,
1139 info->direction,
1140 &chip,
1141 uaudio_disconnect_cb);
1142 if (!subs || !chip || atomic_read(&chip->shutdown)) {
1143 pr_debug("%s:no subs for c#%u, dev#%u dir%u\n",
1144 __func__, info->pcm_card_num,
1145 info->pcm_dev_num,
1146 info->direction);
1147 continue;
1148 }
1149 snd_usb_enable_audio_stream(subs, 0);
1150 }
1151 atomic_set(&uadev[idx].in_use, 0);
1152 mutex_lock(&chip->dev_lock);
1153 uaudio_dev_cleanup(&uadev[idx]);
1154 mutex_unlock(&chip->dev_lock);
1155 }
1156}
1157
Hemant Kumar0ef9fbb2016-01-28 11:41:42 -08001158static int uaudio_qmi_svc_disconnect_cb(struct qmi_handle *handle,
1159 void *conn_h)
1160{
1161 struct uaudio_qmi_svc *svc = uaudio_svc;
1162
1163 if (svc->uaudio_svc_hdl != handle || svc->curr_conn != conn_h) {
1164 pr_err("%s: handle mismatch\n", __func__);
1165 return -EINVAL;
1166 }
1167
1168 svc->curr_conn = NULL;
Hemant Kumar89fa7b92016-10-27 19:56:31 -07001169 queue_work(svc->uaudio_wq, &svc->qmi_disconnect_work);
1170
Hemant Kumar0ef9fbb2016-01-28 11:41:42 -08001171 return 0;
1172}
1173
1174static int uaudio_qmi_svc_req_cb(struct qmi_handle *handle, void *conn_h,
1175 void *req_h, unsigned int msg_id, void *req)
1176{
1177 int ret;
1178 struct uaudio_qmi_svc *svc = uaudio_svc;
1179
1180 if (svc->uaudio_svc_hdl != handle || svc->curr_conn != conn_h) {
1181 pr_err("%s: handle mismatch\n", __func__);
1182 return -EINVAL;
1183 }
1184
1185 switch (msg_id) {
1186 case QMI_UAUDIO_STREAM_REQ_V01:
1187 ret = handle_uaudio_stream_req(req_h, req);
1188 break;
1189
1190 default:
1191 ret = -ENOTSUPP;
1192 break;
1193 }
1194 return ret;
1195}
1196
1197static int uaudio_qmi_svc_req_desc_cb(unsigned int msg_id,
1198 struct msg_desc **req_desc)
1199{
1200 int ret;
1201
1202 pr_debug("%s: msg_id %d\n", __func__, msg_id);
1203
1204 switch (msg_id) {
1205 case QMI_UAUDIO_STREAM_REQ_V01:
1206 *req_desc = &uaudio_stream_req_desc;
1207 ret = sizeof(struct qmi_uaudio_stream_req_msg_v01);
1208 break;
1209
1210 default:
1211 ret = -ENOTSUPP;
1212 break;
1213 }
1214 return ret;
1215}
1216
1217static void uaudio_qmi_svc_recv_msg(struct work_struct *w)
1218{
1219 int ret;
1220 struct uaudio_qmi_svc *svc = container_of(w, struct uaudio_qmi_svc,
1221 recv_msg_work);
1222
1223 do {
1224 pr_debug("%s: Notified about a Receive Event", __func__);
1225 } while ((ret = qmi_recv_msg(svc->uaudio_svc_hdl)) == 0);
1226
1227 if (ret != -ENOMSG)
1228 pr_err("%s: Error receiving message\n", __func__);
1229}
1230
1231static void uaudio_qmi_svc_ntfy(struct qmi_handle *handle,
1232 enum qmi_event_type event, void *priv)
1233{
1234 struct uaudio_qmi_svc *svc = uaudio_svc;
1235
1236 pr_debug("%s: event %d", __func__, event);
1237
1238 svc->t_request_recvd = ktime_get();
1239
1240 switch (event) {
1241 case QMI_RECV_MSG:
1242 queue_work(svc->uaudio_wq, &svc->recv_msg_work);
1243 break;
1244 default:
1245 break;
1246 }
1247}
1248
1249static struct qmi_svc_ops_options uaudio_svc_ops_options = {
1250 .version = 1,
1251 .service_id = UAUDIO_STREAM_SERVICE_ID_V01,
1252 .service_vers = UAUDIO_STREAM_SERVICE_VERS_V01,
1253 .connect_cb = uaudio_qmi_svc_connect_cb,
1254 .disconnect_cb = uaudio_qmi_svc_disconnect_cb,
1255 .req_desc_cb = uaudio_qmi_svc_req_desc_cb,
1256 .req_cb = uaudio_qmi_svc_req_cb,
1257};
1258
Hemant Kumard2a54502016-03-22 16:35:16 -07001259static int uaudio_qmi_plat_probe(struct platform_device *pdev)
1260{
1261 int ret;
1262 struct device_node *node = pdev->dev.of_node;
1263
1264 uaudio_qdev = devm_kzalloc(&pdev->dev, sizeof(struct uaudio_qmi_dev),
1265 GFP_KERNEL);
1266 if (!uaudio_qdev)
1267 return -ENOMEM;
1268
1269 uaudio_qdev->dev = &pdev->dev;
1270
1271 ret = of_property_read_u32(node, "qcom,usb-audio-stream-id",
1272 &uaudio_qdev->sid);
1273 if (ret) {
1274 dev_err(&pdev->dev, "failed to read sid.\n");
1275 return -ENODEV;
1276 }
1277
1278 ret = of_property_read_u32(node, "qcom,usb-audio-intr-num",
1279 &uaudio_qdev->intr_num);
1280 if (ret) {
1281 dev_err(&pdev->dev, "failed to read intr num.\n");
1282 return -ENODEV;
1283 }
1284
1285 uaudio_qdev->domain = iommu_domain_alloc(pdev->dev.bus);
Hemant Kumara2a80912016-08-22 19:31:35 -07001286 if (!uaudio_qdev->domain) {
1287 dev_err(&pdev->dev, "failed to allocate iommu domain\n");
Hemant Kumard2a54502016-03-22 16:35:16 -07001288 return -ENODEV;
1289 }
1290
1291 /* attach to external processor iommu */
1292 ret = iommu_attach_device(uaudio_qdev->domain, &pdev->dev);
1293 if (ret) {
1294 dev_err(&pdev->dev, "failed to attach device ret = %d\n", ret);
1295 goto free_domain;
1296 }
1297
Hemant Kumar81156ed2017-09-22 12:34:52 -07001298 /* initialize xfer ring and xfer buf iova list */
Hemant Kumard2a54502016-03-22 16:35:16 -07001299 INIT_LIST_HEAD(&uaudio_qdev->xfer_ring_list);
1300 uaudio_qdev->curr_xfer_ring_iova = IOVA_XFER_RING_BASE;
1301 uaudio_qdev->xfer_ring_iova_size =
1302 IOVA_XFER_RING_MAX - IOVA_XFER_RING_BASE;
1303
1304 INIT_LIST_HEAD(&uaudio_qdev->xfer_buf_list);
1305 uaudio_qdev->curr_xfer_buf_iova = IOVA_XFER_BUF_BASE;
1306 uaudio_qdev->xfer_buf_iova_size =
1307 IOVA_XFER_BUF_MAX - IOVA_XFER_BUF_BASE;
1308
1309 return 0;
1310
1311free_domain:
1312 iommu_domain_free(uaudio_qdev->domain);
1313 return ret;
1314}
1315
1316static int uaudio_qmi_plat_remove(struct platform_device *pdev)
1317{
1318 iommu_detach_device(uaudio_qdev->domain, &pdev->dev);
1319 iommu_domain_free(uaudio_qdev->domain);
1320 uaudio_qdev->domain = NULL;
1321
1322 return 0;
1323}
1324
1325static const struct of_device_id of_uaudio_matach[] = {
1326 {
1327 .compatible = "qcom,usb-audio-qmi-dev",
1328 },
1329 { },
1330};
1331MODULE_DEVICE_TABLE(of, of_uaudio_matach);
1332
1333static struct platform_driver uaudio_qmi_driver = {
1334 .probe = uaudio_qmi_plat_probe,
1335 .remove = uaudio_qmi_plat_remove,
1336 .driver = {
1337 .name = "uaudio-qmi",
1338 .of_match_table = of_uaudio_matach,
1339 },
1340};
1341
1342static int uaudio_qmi_svc_init(void)
Hemant Kumar0ef9fbb2016-01-28 11:41:42 -08001343{
1344 int ret;
1345 struct uaudio_qmi_svc *svc;
1346
1347 svc = kzalloc(sizeof(struct uaudio_qmi_svc), GFP_KERNEL);
1348 if (!svc)
1349 return -ENOMEM;
1350
1351 svc->uaudio_wq = create_singlethread_workqueue("uaudio_svc");
1352 if (!svc->uaudio_wq) {
1353 ret = -ENOMEM;
1354 goto free_svc;
1355 }
1356
1357 svc->uaudio_svc_hdl = qmi_handle_create(uaudio_qmi_svc_ntfy, NULL);
1358 if (!svc->uaudio_svc_hdl) {
1359 pr_err("%s: Error creating svc_hdl\n", __func__);
1360 ret = -EFAULT;
1361 goto destroy_uaudio_wq;
1362 }
1363
1364 ret = qmi_svc_register(svc->uaudio_svc_hdl, &uaudio_svc_ops_options);
1365 if (ret < 0) {
1366 pr_err("%s:Error registering uaudio svc %d\n", __func__, ret);
1367 goto destroy_svc_handle;
1368 }
1369
1370 INIT_WORK(&svc->recv_msg_work, uaudio_qmi_svc_recv_msg);
Hemant Kumar89fa7b92016-10-27 19:56:31 -07001371 INIT_WORK(&svc->qmi_disconnect_work, uaudio_qmi_disconnect_work);
Hemant Kumar0ef9fbb2016-01-28 11:41:42 -08001372
1373 uaudio_svc = svc;
1374
1375 return 0;
1376
1377destroy_svc_handle:
1378 qmi_handle_destroy(svc->uaudio_svc_hdl);
1379destroy_uaudio_wq:
1380 destroy_workqueue(svc->uaudio_wq);
1381free_svc:
1382 kfree(svc);
1383 return ret;
1384}
1385
Hemant Kumard2a54502016-03-22 16:35:16 -07001386static void uaudio_qmi_svc_exit(void)
Hemant Kumar0ef9fbb2016-01-28 11:41:42 -08001387{
1388 struct uaudio_qmi_svc *svc = uaudio_svc;
1389
1390 qmi_svc_unregister(svc->uaudio_svc_hdl);
1391 flush_workqueue(svc->uaudio_wq);
1392 qmi_handle_destroy(svc->uaudio_svc_hdl);
1393 destroy_workqueue(svc->uaudio_wq);
1394 kfree(svc);
1395 uaudio_svc = NULL;
1396}
1397
Hemant Kumard2a54502016-03-22 16:35:16 -07001398static int __init uaudio_qmi_plat_init(void)
1399{
1400 int ret;
1401
1402 ret = platform_driver_register(&uaudio_qmi_driver);
1403 if (ret)
1404 return ret;
1405
1406 return uaudio_qmi_svc_init();
1407}
1408
1409static void __exit uaudio_qmi_plat_exit(void)
1410{
1411 uaudio_qmi_svc_exit();
1412 platform_driver_unregister(&uaudio_qmi_driver);
1413}
1414
1415module_init(uaudio_qmi_plat_init);
1416module_exit(uaudio_qmi_plat_exit);
Hemant Kumar0ef9fbb2016-01-28 11:41:42 -08001417
1418MODULE_DESCRIPTION("USB AUDIO QMI Service Driver");
1419MODULE_LICENSE("GPL v2");