1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3  *  Conexant Cx231xx audio extension
4  *
5  *  Copyright (C) 2008 <srinivasa.deevi at conexant dot com>
6  *       Based on em28xx driver
7  */
8 
9 #include "cx231xx.h"
10 #include <linux/kernel.h>
11 #include <linux/init.h>
12 #include <linux/sound.h>
13 #include <linux/spinlock.h>
14 #include <linux/soundcard.h>
15 #include <linux/slab.h>
16 #include <linux/vmalloc.h>
17 #include <linux/proc_fs.h>
18 #include <linux/module.h>
19 #include <sound/core.h>
20 #include <sound/pcm.h>
21 #include <sound/pcm_params.h>
22 #include <sound/info.h>
23 #include <sound/initval.h>
24 #include <sound/control.h>
25 #include <media/v4l2-common.h>
26 
27 static int debug;
28 module_param(debug, int, 0644);
29 MODULE_PARM_DESC(debug, "activates debug info");
30 
31 static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX;
32 
33 static int cx231xx_isoc_audio_deinit(struct cx231xx *dev)
34 {
35 	int i;
36 
37 	dev_dbg(dev->dev, "Stopping isoc\n");
38 
39 	for (i = 0; i < CX231XX_AUDIO_BUFS; i++) {
40 		if (dev->adev.urb[i]) {
41 			if (!irqs_disabled())
42 				usb_kill_urb(dev->adev.urb[i]);
43 			else
44 				usb_unlink_urb(dev->adev.urb[i]);
45 
46 			usb_free_urb(dev->adev.urb[i]);
47 			dev->adev.urb[i] = NULL;
48 
49 			kfree(dev->adev.transfer_buffer[i]);
50 			dev->adev.transfer_buffer[i] = NULL;
51 		}
52 	}
53 
54 	return 0;
55 }
56 
57 static int cx231xx_bulk_audio_deinit(struct cx231xx *dev)
58 {
59 	int i;
60 
61 	dev_dbg(dev->dev, "Stopping bulk\n");
62 
63 	for (i = 0; i < CX231XX_AUDIO_BUFS; i++) {
64 		if (dev->adev.urb[i]) {
65 			if (!irqs_disabled())
66 				usb_kill_urb(dev->adev.urb[i]);
67 			else
68 				usb_unlink_urb(dev->adev.urb[i]);
69 
70 			usb_free_urb(dev->adev.urb[i]);
71 			dev->adev.urb[i] = NULL;
72 
73 			kfree(dev->adev.transfer_buffer[i]);
74 			dev->adev.transfer_buffer[i] = NULL;
75 		}
76 	}
77 
78 	return 0;
79 }
80 
81 static void cx231xx_audio_isocirq(struct urb *urb)
82 {
83 	struct cx231xx *dev = urb->context;
84 	int i;
85 	unsigned int oldptr;
86 	int period_elapsed = 0;
87 	int status;
88 	unsigned char *cp;
89 	unsigned int stride;
90 	struct snd_pcm_substream *substream;
91 	struct snd_pcm_runtime *runtime;
92 
93 	if (dev->state & DEV_DISCONNECTED)
94 		return;
95 
96 	switch (urb->status) {
97 	case 0:		/* success */
98 	case -ETIMEDOUT:	/* NAK */
99 		break;
100 	case -ECONNRESET:	/* kill */
101 	case -ENOENT:
102 	case -ESHUTDOWN:
103 		return;
104 	default:		/* error */
105 		dev_dbg(dev->dev, "urb completion error %d.\n",
106 			urb->status);
107 		break;
108 	}
109 
110 	if (atomic_read(&dev->stream_started) == 0)
111 		return;
112 
113 	if (dev->adev.capture_pcm_substream) {
114 		substream = dev->adev.capture_pcm_substream;
115 		runtime = substream->runtime;
116 		stride = runtime->frame_bits >> 3;
117 
118 		for (i = 0; i < urb->number_of_packets; i++) {
119 			unsigned long flags;
120 			int length = urb->iso_frame_desc[i].actual_length /
121 				     stride;
122 			cp = (unsigned char *)urb->transfer_buffer +
123 					      urb->iso_frame_desc[i].offset;
124 
125 			if (!length)
126 				continue;
127 
128 			oldptr = dev->adev.hwptr_done_capture;
129 			if (oldptr + length >= runtime->buffer_size) {
130 				unsigned int cnt;
131 
132 				cnt = runtime->buffer_size - oldptr;
133 				memcpy(runtime->dma_area + oldptr * stride, cp,
134 				       cnt * stride);
135 				memcpy(runtime->dma_area, cp + cnt * stride,
136 				       length * stride - cnt * stride);
137 			} else {
138 				memcpy(runtime->dma_area + oldptr * stride, cp,
139 				       length * stride);
140 			}
141 
142 			snd_pcm_stream_lock_irqsave(substream, flags);
143 
144 			dev->adev.hwptr_done_capture += length;
145 			if (dev->adev.hwptr_done_capture >=
146 						runtime->buffer_size)
147 				dev->adev.hwptr_done_capture -=
148 						runtime->buffer_size;
149 
150 			dev->adev.capture_transfer_done += length;
151 			if (dev->adev.capture_transfer_done >=
152 				runtime->period_size) {
153 				dev->adev.capture_transfer_done -=
154 						runtime->period_size;
155 				period_elapsed = 1;
156 			}
157 			snd_pcm_stream_unlock_irqrestore(substream, flags);
158 		}
159 		if (period_elapsed)
160 			snd_pcm_period_elapsed(substream);
161 	}
162 	urb->status = 0;
163 
164 	status = usb_submit_urb(urb, GFP_ATOMIC);
165 	if (status < 0) {
166 		dev_err(dev->dev,
167 			"resubmit of audio urb failed (error=%i)\n",
168 			status);
169 	}
170 	return;
171 }
172 
173 static void cx231xx_audio_bulkirq(struct urb *urb)
174 {
175 	struct cx231xx *dev = urb->context;
176 	unsigned int oldptr;
177 	int period_elapsed = 0;
178 	int status;
179 	unsigned char *cp;
180 	unsigned int stride;
181 	struct snd_pcm_substream *substream;
182 	struct snd_pcm_runtime *runtime;
183 
184 	if (dev->state & DEV_DISCONNECTED)
185 		return;
186 
187 	switch (urb->status) {
188 	case 0:		/* success */
189 	case -ETIMEDOUT:	/* NAK */
190 		break;
191 	case -ECONNRESET:	/* kill */
192 	case -ENOENT:
193 	case -ESHUTDOWN:
194 		return;
195 	default:		/* error */
196 		dev_dbg(dev->dev, "urb completion error %d.\n",
197 			urb->status);
198 		break;
199 	}
200 
201 	if (atomic_read(&dev->stream_started) == 0)
202 		return;
203 
204 	if (dev->adev.capture_pcm_substream) {
205 		substream = dev->adev.capture_pcm_substream;
206 		runtime = substream->runtime;
207 		stride = runtime->frame_bits >> 3;
208 
209 		if (1) {
210 			unsigned long flags;
211 			int length = urb->actual_length /
212 				     stride;
213 			cp = (unsigned char *)urb->transfer_buffer;
214 
215 			oldptr = dev->adev.hwptr_done_capture;
216 			if (oldptr + length >= runtime->buffer_size) {
217 				unsigned int cnt;
218 
219 				cnt = runtime->buffer_size - oldptr;
220 				memcpy(runtime->dma_area + oldptr * stride, cp,
221 				       cnt * stride);
222 				memcpy(runtime->dma_area, cp + cnt * stride,
223 				       length * stride - cnt * stride);
224 			} else {
225 				memcpy(runtime->dma_area + oldptr * stride, cp,
226 				       length * stride);
227 			}
228 
229 			snd_pcm_stream_lock_irqsave(substream, flags);
230 
231 			dev->adev.hwptr_done_capture += length;
232 			if (dev->adev.hwptr_done_capture >=
233 						runtime->buffer_size)
234 				dev->adev.hwptr_done_capture -=
235 						runtime->buffer_size;
236 
237 			dev->adev.capture_transfer_done += length;
238 			if (dev->adev.capture_transfer_done >=
239 				runtime->period_size) {
240 				dev->adev.capture_transfer_done -=
241 						runtime->period_size;
242 				period_elapsed = 1;
243 			}
244 			snd_pcm_stream_unlock_irqrestore(substream, flags);
245 		}
246 		if (period_elapsed)
247 			snd_pcm_period_elapsed(substream);
248 	}
249 	urb->status = 0;
250 
251 	status = usb_submit_urb(urb, GFP_ATOMIC);
252 	if (status < 0) {
253 		dev_err(dev->dev,
254 			"resubmit of audio urb failed (error=%i)\n",
255 			status);
256 	}
257 	return;
258 }
259 
260 static int cx231xx_init_audio_isoc(struct cx231xx *dev)
261 {
262 	int i, errCode;
263 	int sb_size;
264 
265 	dev_dbg(dev->dev,
266 		"%s: Starting ISO AUDIO transfers\n", __func__);
267 
268 	if (dev->state & DEV_DISCONNECTED)
269 		return -ENODEV;
270 
271 	sb_size = CX231XX_ISO_NUM_AUDIO_PACKETS * dev->adev.max_pkt_size;
272 
273 	for (i = 0; i < CX231XX_AUDIO_BUFS; i++) {
274 		struct urb *urb;
275 		int j, k;
276 
277 		dev->adev.transfer_buffer[i] = kmalloc(sb_size, GFP_ATOMIC);
278 		if (!dev->adev.transfer_buffer[i])
279 			return -ENOMEM;
280 
281 		memset(dev->adev.transfer_buffer[i], 0x80, sb_size);
282 		urb = usb_alloc_urb(CX231XX_ISO_NUM_AUDIO_PACKETS, GFP_ATOMIC);
283 		if (!urb) {
284 			for (j = 0; j < i; j++) {
285 				usb_free_urb(dev->adev.urb[j]);
286 				kfree(dev->adev.transfer_buffer[j]);
287 			}
288 			return -ENOMEM;
289 		}
290 
291 		urb->dev = dev->udev;
292 		urb->context = dev;
293 		urb->pipe = usb_rcvisocpipe(dev->udev,
294 						dev->adev.end_point_addr);
295 		urb->transfer_flags = URB_ISO_ASAP;
296 		urb->transfer_buffer = dev->adev.transfer_buffer[i];
297 		urb->interval = 1;
298 		urb->complete = cx231xx_audio_isocirq;
299 		urb->number_of_packets = CX231XX_ISO_NUM_AUDIO_PACKETS;
300 		urb->transfer_buffer_length = sb_size;
301 
302 		for (j = k = 0; j < CX231XX_ISO_NUM_AUDIO_PACKETS;
303 			j++, k += dev->adev.max_pkt_size) {
304 			urb->iso_frame_desc[j].offset = k;
305 			urb->iso_frame_desc[j].length = dev->adev.max_pkt_size;
306 		}
307 		dev->adev.urb[i] = urb;
308 	}
309 
310 	for (i = 0; i < CX231XX_AUDIO_BUFS; i++) {
311 		errCode = usb_submit_urb(dev->adev.urb[i], GFP_ATOMIC);
312 		if (errCode < 0) {
313 			cx231xx_isoc_audio_deinit(dev);
314 			return errCode;
315 		}
316 	}
317 
318 	return errCode;
319 }
320 
321 static int cx231xx_init_audio_bulk(struct cx231xx *dev)
322 {
323 	int i, errCode;
324 	int sb_size;
325 
326 	dev_dbg(dev->dev,
327 		"%s: Starting BULK AUDIO transfers\n", __func__);
328 
329 	if (dev->state & DEV_DISCONNECTED)
330 		return -ENODEV;
331 
332 	sb_size = CX231XX_NUM_AUDIO_PACKETS * dev->adev.max_pkt_size;
333 
334 	for (i = 0; i < CX231XX_AUDIO_BUFS; i++) {
335 		struct urb *urb;
336 		int j;
337 
338 		dev->adev.transfer_buffer[i] = kmalloc(sb_size, GFP_ATOMIC);
339 		if (!dev->adev.transfer_buffer[i])
340 			return -ENOMEM;
341 
342 		memset(dev->adev.transfer_buffer[i], 0x80, sb_size);
343 		urb = usb_alloc_urb(CX231XX_NUM_AUDIO_PACKETS, GFP_ATOMIC);
344 		if (!urb) {
345 			for (j = 0; j < i; j++) {
346 				usb_free_urb(dev->adev.urb[j]);
347 				kfree(dev->adev.transfer_buffer[j]);
348 			}
349 			return -ENOMEM;
350 		}
351 
352 		urb->dev = dev->udev;
353 		urb->context = dev;
354 		urb->pipe = usb_rcvbulkpipe(dev->udev,
355 						dev->adev.end_point_addr);
356 		urb->transfer_flags = 0;
357 		urb->transfer_buffer = dev->adev.transfer_buffer[i];
358 		urb->complete = cx231xx_audio_bulkirq;
359 		urb->transfer_buffer_length = sb_size;
360 
361 		dev->adev.urb[i] = urb;
362 
363 	}
364 
365 	for (i = 0; i < CX231XX_AUDIO_BUFS; i++) {
366 		errCode = usb_submit_urb(dev->adev.urb[i], GFP_ATOMIC);
367 		if (errCode < 0) {
368 			cx231xx_bulk_audio_deinit(dev);
369 			return errCode;
370 		}
371 	}
372 
373 	return errCode;
374 }
375 
376 static int snd_pcm_alloc_vmalloc_buffer(struct snd_pcm_substream *subs,
377 					size_t size)
378 {
379 	struct snd_pcm_runtime *runtime = subs->runtime;
380 	struct cx231xx *dev = snd_pcm_substream_chip(subs);
381 
382 	dev_dbg(dev->dev, "Allocating vbuffer\n");
383 	if (runtime->dma_area) {
384 		if (runtime->dma_bytes > size)
385 			return 0;
386 
387 		vfree(runtime->dma_area);
388 	}
389 	runtime->dma_area = vmalloc(size);
390 	if (!runtime->dma_area)
391 		return -ENOMEM;
392 
393 	runtime->dma_bytes = size;
394 
395 	return 0;
396 }
397 
398 static const struct snd_pcm_hardware snd_cx231xx_hw_capture = {
399 	.info = SNDRV_PCM_INFO_BLOCK_TRANSFER	|
400 	    SNDRV_PCM_INFO_MMAP			|
401 	    SNDRV_PCM_INFO_INTERLEAVED		|
402 	    SNDRV_PCM_INFO_MMAP_VALID,
403 
404 	.formats = SNDRV_PCM_FMTBIT_S16_LE,
405 
406 	.rates = SNDRV_PCM_RATE_CONTINUOUS | SNDRV_PCM_RATE_KNOT,
407 
408 	.rate_min = 48000,
409 	.rate_max = 48000,
410 	.channels_min = 2,
411 	.channels_max = 2,
412 	.buffer_bytes_max = 62720 * 8,	/* just about the value in usbaudio.c */
413 	.period_bytes_min = 64,		/* 12544/2, */
414 	.period_bytes_max = 12544,
415 	.periods_min = 2,
416 	.periods_max = 98,		/* 12544, */
417 };
418 
419 static int snd_cx231xx_capture_open(struct snd_pcm_substream *substream)
420 {
421 	struct cx231xx *dev = snd_pcm_substream_chip(substream);
422 	struct snd_pcm_runtime *runtime = substream->runtime;
423 	int ret = 0;
424 
425 	dev_dbg(dev->dev,
426 		"opening device and trying to acquire exclusive lock\n");
427 
428 	if (dev->state & DEV_DISCONNECTED) {
429 		dev_err(dev->dev,
430 			"Can't open. the device was removed.\n");
431 		return -ENODEV;
432 	}
433 
434 	/* set alternate setting for audio interface */
435 	/* 1 - 48000 samples per sec */
436 	mutex_lock(&dev->lock);
437 	if (dev->USE_ISO)
438 		ret = cx231xx_set_alt_setting(dev, INDEX_AUDIO, 1);
439 	else
440 		ret = cx231xx_set_alt_setting(dev, INDEX_AUDIO, 0);
441 	mutex_unlock(&dev->lock);
442 	if (ret < 0) {
443 		dev_err(dev->dev,
444 			"failed to set alternate setting !\n");
445 
446 		return ret;
447 	}
448 
449 	runtime->hw = snd_cx231xx_hw_capture;
450 
451 	mutex_lock(&dev->lock);
452 	/* inform hardware to start streaming */
453 	ret = cx231xx_capture_start(dev, 1, Audio);
454 
455 	dev->adev.users++;
456 	mutex_unlock(&dev->lock);
457 
458 	snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS);
459 	dev->adev.capture_pcm_substream = substream;
460 	runtime->private_data = dev;
461 
462 	return 0;
463 }
464 
465 static int snd_cx231xx_pcm_close(struct snd_pcm_substream *substream)
466 {
467 	int ret;
468 	struct cx231xx *dev = snd_pcm_substream_chip(substream);
469 
470 	dev_dbg(dev->dev, "closing device\n");
471 
472 	/* inform hardware to stop streaming */
473 	mutex_lock(&dev->lock);
474 	ret = cx231xx_capture_start(dev, 0, Audio);
475 
476 	/* set alternate setting for audio interface */
477 	/* 1 - 48000 samples per sec */
478 	ret = cx231xx_set_alt_setting(dev, INDEX_AUDIO, 0);
479 	if (ret < 0) {
480 		dev_err(dev->dev,
481 			"failed to set alternate setting !\n");
482 
483 		mutex_unlock(&dev->lock);
484 		return ret;
485 	}
486 
487 	dev->adev.users--;
488 	if (substream->runtime->dma_area) {
489 		dev_dbg(dev->dev, "freeing\n");
490 		vfree(substream->runtime->dma_area);
491 		substream->runtime->dma_area = NULL;
492 	}
493 	mutex_unlock(&dev->lock);
494 
495 	if (dev->adev.users == 0 && dev->adev.shutdown == 1) {
496 		dev_dbg(dev->dev, "audio users: %d\n", dev->adev.users);
497 		dev_dbg(dev->dev, "disabling audio stream!\n");
498 		dev->adev.shutdown = 0;
499 		dev_dbg(dev->dev, "released lock\n");
500 		if (atomic_read(&dev->stream_started) > 0) {
501 			atomic_set(&dev->stream_started, 0);
502 			schedule_work(&dev->wq_trigger);
503 		}
504 	}
505 	return 0;
506 }
507 
508 static int snd_cx231xx_hw_capture_params(struct snd_pcm_substream *substream,
509 					 struct snd_pcm_hw_params *hw_params)
510 {
511 	struct cx231xx *dev = snd_pcm_substream_chip(substream);
512 	int ret;
513 
514 	dev_dbg(dev->dev, "Setting capture parameters\n");
515 
516 	ret = snd_pcm_alloc_vmalloc_buffer(substream,
517 					   params_buffer_bytes(hw_params));
518 #if 0
519 	/* TODO: set up cx231xx audio chip to deliver the correct audio format,
520 	   current default is 48000hz multiplexed => 96000hz mono
521 	   which shouldn't matter since analogue TV only supports mono */
522 	unsigned int channels, rate, format;
523 
524 	format = params_format(hw_params);
525 	rate = params_rate(hw_params);
526 	channels = params_channels(hw_params);
527 #endif
528 
529 	return ret;
530 }
531 
532 static int snd_cx231xx_hw_capture_free(struct snd_pcm_substream *substream)
533 {
534 	struct cx231xx *dev = snd_pcm_substream_chip(substream);
535 
536 	dev_dbg(dev->dev, "Stop capture, if needed\n");
537 
538 	if (atomic_read(&dev->stream_started) > 0) {
539 		atomic_set(&dev->stream_started, 0);
540 		schedule_work(&dev->wq_trigger);
541 	}
542 
543 	return 0;
544 }
545 
546 static int snd_cx231xx_prepare(struct snd_pcm_substream *substream)
547 {
548 	struct cx231xx *dev = snd_pcm_substream_chip(substream);
549 
550 	dev->adev.hwptr_done_capture = 0;
551 	dev->adev.capture_transfer_done = 0;
552 
553 	return 0;
554 }
555 
556 static void audio_trigger(struct work_struct *work)
557 {
558 	struct cx231xx *dev = container_of(work, struct cx231xx, wq_trigger);
559 
560 	if (atomic_read(&dev->stream_started)) {
561 		dev_dbg(dev->dev, "starting capture");
562 		if (is_fw_load(dev) == 0)
563 			cx25840_call(dev, core, load_fw);
564 		if (dev->USE_ISO)
565 			cx231xx_init_audio_isoc(dev);
566 		else
567 			cx231xx_init_audio_bulk(dev);
568 	} else {
569 		dev_dbg(dev->dev, "stopping capture");
570 		cx231xx_isoc_audio_deinit(dev);
571 	}
572 }
573 
574 static int snd_cx231xx_capture_trigger(struct snd_pcm_substream *substream,
575 				       int cmd)
576 {
577 	struct cx231xx *dev = snd_pcm_substream_chip(substream);
578 	int retval = 0;
579 
580 	if (dev->state & DEV_DISCONNECTED)
581 		return -ENODEV;
582 
583 	spin_lock(&dev->adev.slock);
584 	switch (cmd) {
585 	case SNDRV_PCM_TRIGGER_START:
586 		atomic_set(&dev->stream_started, 1);
587 		break;
588 	case SNDRV_PCM_TRIGGER_STOP:
589 		atomic_set(&dev->stream_started, 0);
590 		break;
591 	default:
592 		retval = -EINVAL;
593 		break;
594 	}
595 	spin_unlock(&dev->adev.slock);
596 
597 	schedule_work(&dev->wq_trigger);
598 
599 	return retval;
600 }
601 
602 static snd_pcm_uframes_t snd_cx231xx_capture_pointer(struct snd_pcm_substream
603 						     *substream)
604 {
605 	struct cx231xx *dev;
606 	unsigned long flags;
607 	snd_pcm_uframes_t hwptr_done;
608 
609 	dev = snd_pcm_substream_chip(substream);
610 
611 	spin_lock_irqsave(&dev->adev.slock, flags);
612 	hwptr_done = dev->adev.hwptr_done_capture;
613 	spin_unlock_irqrestore(&dev->adev.slock, flags);
614 
615 	return hwptr_done;
616 }
617 
618 static struct page *snd_pcm_get_vmalloc_page(struct snd_pcm_substream *subs,
619 					     unsigned long offset)
620 {
621 	void *pageptr = subs->runtime->dma_area + offset;
622 
623 	return vmalloc_to_page(pageptr);
624 }
625 
626 static const struct snd_pcm_ops snd_cx231xx_pcm_capture = {
627 	.open = snd_cx231xx_capture_open,
628 	.close = snd_cx231xx_pcm_close,
629 	.ioctl = snd_pcm_lib_ioctl,
630 	.hw_params = snd_cx231xx_hw_capture_params,
631 	.hw_free = snd_cx231xx_hw_capture_free,
632 	.prepare = snd_cx231xx_prepare,
633 	.trigger = snd_cx231xx_capture_trigger,
634 	.pointer = snd_cx231xx_capture_pointer,
635 	.page = snd_pcm_get_vmalloc_page,
636 };
637 
638 static int cx231xx_audio_init(struct cx231xx *dev)
639 {
640 	struct cx231xx_audio *adev = &dev->adev;
641 	struct snd_pcm *pcm;
642 	struct snd_card *card;
643 	static int devnr;
644 	int err;
645 	struct usb_interface *uif;
646 	int i, isoc_pipe = 0;
647 
648 	if (dev->has_alsa_audio != 1) {
649 		/* This device does not support the extension (in this case
650 		   the device is expecting the snd-usb-audio module or
651 		   doesn't have analog audio support at all) */
652 		return 0;
653 	}
654 
655 	dev_dbg(dev->dev,
656 		"probing for cx231xx non standard usbaudio\n");
657 
658 	err = snd_card_new(dev->dev, index[devnr], "Cx231xx Audio",
659 			   THIS_MODULE, 0, &card);
660 	if (err < 0)
661 		return err;
662 
663 	spin_lock_init(&adev->slock);
664 	err = snd_pcm_new(card, "Cx231xx Audio", 0, 0, 1, &pcm);
665 	if (err < 0)
666 		goto err_free_card;
667 
668 	snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE,
669 			&snd_cx231xx_pcm_capture);
670 	pcm->info_flags = 0;
671 	pcm->private_data = dev;
672 	strscpy(pcm->name, "Conexant cx231xx Capture", sizeof(pcm->name));
673 	strscpy(card->driver, "Cx231xx-Audio", sizeof(card->driver));
674 	strscpy(card->shortname, "Cx231xx Audio", sizeof(card->shortname));
675 	strscpy(card->longname, "Conexant cx231xx Audio", sizeof(card->longname));
676 
677 	INIT_WORK(&dev->wq_trigger, audio_trigger);
678 
679 	err = snd_card_register(card);
680 	if (err < 0)
681 		goto err_free_card;
682 
683 	adev->sndcard = card;
684 	adev->udev = dev->udev;
685 
686 	/* compute alternate max packet sizes for Audio */
687 	uif =
688 	    dev->udev->actconfig->interface[dev->current_pcb_config.
689 					    hs_config_info[0].interface_info.
690 					    audio_index + 1];
691 
692 	if (uif->altsetting[0].desc.bNumEndpoints < isoc_pipe + 1) {
693 		err = -ENODEV;
694 		goto err_free_card;
695 	}
696 
697 	adev->end_point_addr =
698 	    uif->altsetting[0].endpoint[isoc_pipe].desc.
699 			bEndpointAddress;
700 
701 	adev->num_alt = uif->num_altsetting;
702 	dev_info(dev->dev,
703 		"audio EndPoint Addr 0x%x, Alternate settings: %i\n",
704 		adev->end_point_addr, adev->num_alt);
705 	adev->alt_max_pkt_size = kmalloc_array(32, adev->num_alt, GFP_KERNEL);
706 	if (!adev->alt_max_pkt_size) {
707 		err = -ENOMEM;
708 		goto err_free_card;
709 	}
710 
711 	for (i = 0; i < adev->num_alt; i++) {
712 		u16 tmp;
713 
714 		if (uif->altsetting[i].desc.bNumEndpoints < isoc_pipe + 1) {
715 			err = -ENODEV;
716 			goto err_free_pkt_size;
717 		}
718 
719 		tmp = le16_to_cpu(uif->altsetting[i].endpoint[isoc_pipe].desc.
720 				wMaxPacketSize);
721 		adev->alt_max_pkt_size[i] =
722 		    (tmp & 0x07ff) * (((tmp & 0x1800) >> 11) + 1);
723 		dev_dbg(dev->dev,
724 			"audio alternate setting %i, max size= %i\n", i,
725 			adev->alt_max_pkt_size[i]);
726 	}
727 
728 	return 0;
729 
730 err_free_pkt_size:
731 	kfree(adev->alt_max_pkt_size);
732 err_free_card:
733 	snd_card_free(card);
734 
735 	return err;
736 }
737 
738 static int cx231xx_audio_fini(struct cx231xx *dev)
739 {
740 	if (dev == NULL)
741 		return 0;
742 
743 	if (dev->has_alsa_audio != 1) {
744 		/* This device does not support the extension (in this case
745 		   the device is expecting the snd-usb-audio module or
746 		   doesn't have analog audio support at all) */
747 		return 0;
748 	}
749 
750 	if (dev->adev.sndcard) {
751 		snd_card_free(dev->adev.sndcard);
752 		kfree(dev->adev.alt_max_pkt_size);
753 		dev->adev.sndcard = NULL;
754 	}
755 
756 	return 0;
757 }
758 
759 static struct cx231xx_ops audio_ops = {
760 	.id = CX231XX_AUDIO,
761 	.name = "Cx231xx Audio Extension",
762 	.init = cx231xx_audio_init,
763 	.fini = cx231xx_audio_fini,
764 };
765 
766 static int __init cx231xx_alsa_register(void)
767 {
768 	return cx231xx_register_extension(&audio_ops);
769 }
770 
771 static void __exit cx231xx_alsa_unregister(void)
772 {
773 	cx231xx_unregister_extension(&audio_ops);
774 }
775 
776 MODULE_LICENSE("GPL");
777 MODULE_AUTHOR("Srinivasa Deevi <srinivasa.deevi@conexant.com>");
778 MODULE_DESCRIPTION("Cx231xx Audio driver");
779 
780 module_init(cx231xx_alsa_register);
781 module_exit(cx231xx_alsa_unregister);
782