cx231xx-audio.c 18.6 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
/*
 *  Conexant Cx231xx audio extension
 *
 *  Copyright (C) 2008 <srinivasa.deevi at conexant dot com>
 *       Based on em28xx driver
 *
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, write to the Free Software
 *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 */

23
#include "cx231xx.h"
24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46
#include <linux/kernel.h>
#include <linux/usb.h>
#include <linux/init.h>
#include <linux/sound.h>
#include <linux/spinlock.h>
#include <linux/soundcard.h>
#include <linux/slab.h>
#include <linux/vmalloc.h>
#include <linux/proc_fs.h>
#include <linux/module.h>
#include <sound/core.h>
#include <sound/pcm.h>
#include <sound/pcm_params.h>
#include <sound/info.h>
#include <sound/initval.h>
#include <sound/control.h>
#include <media/v4l2-common.h>

static int debug;
module_param(debug, int, 0644);
MODULE_PARM_DESC(debug, "activates debug info");

#define dprintk(fmt, arg...) do {					\
47 48 49
		if (debug)						\
			printk(KERN_INFO "cx231xx-audio %s: " fmt,	\
				__func__, ##arg); 			\
50 51 52 53 54 55 56 57 58 59 60
	} while (0)

static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX;

static int cx231xx_isoc_audio_deinit(struct cx231xx *dev)
{
	int i;

	dprintk("Stopping isoc\n");

	for (i = 0; i < CX231XX_AUDIO_BUFS; i++) {
61 62 63 64 65
		if (dev->adev.urb[i]) {
			if (!irqs_disabled())
				usb_kill_urb(dev->adev.urb[i]);
			else
				usb_unlink_urb(dev->adev.urb[i]);
66

67 68
			usb_free_urb(dev->adev.urb[i]);
			dev->adev.urb[i] = NULL;
69

70 71 72
			kfree(dev->adev.transfer_buffer[i]);
			dev->adev.transfer_buffer[i] = NULL;
		}
73 74 75 76 77
	}

	return 0;
}

78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101
static int cx231xx_bulk_audio_deinit(struct cx231xx *dev)
{
	int i;

	dprintk("Stopping bulk\n");

	for (i = 0; i < CX231XX_AUDIO_BUFS; i++) {
		if (dev->adev.urb[i]) {
			if (!irqs_disabled())
				usb_kill_urb(dev->adev.urb[i]);
			else
				usb_unlink_urb(dev->adev.urb[i]);

			usb_free_urb(dev->adev.urb[i]);
			dev->adev.urb[i] = NULL;

			kfree(dev->adev.transfer_buffer[i]);
			dev->adev.transfer_buffer[i] = NULL;
		}
	}

	return 0;
}

102 103
static void cx231xx_audio_isocirq(struct urb *urb)
{
104 105 106 107 108 109 110
	struct cx231xx *dev = urb->context;
	int i;
	unsigned int oldptr;
	int period_elapsed = 0;
	int status;
	unsigned char *cp;
	unsigned int stride;
111
	struct snd_pcm_substream *substream;
112 113
	struct snd_pcm_runtime *runtime;

114 115 116
	if (dev->state & DEV_DISCONNECTED)
		return;

117 118 119 120 121 122 123 124 125 126 127
	switch (urb->status) {
	case 0:		/* success */
	case -ETIMEDOUT:	/* NAK */
		break;
	case -ECONNRESET:	/* kill */
	case -ENOENT:
	case -ESHUTDOWN:
		return;
	default:		/* error */
		dprintk("urb completition error %d.\n", urb->status);
		break;
128 129
	}

130 131 132
	if (atomic_read(&dev->stream_started) == 0)
		return;

133 134 135 136 137 138
	if (dev->adev.capture_pcm_substream) {
		substream = dev->adev.capture_pcm_substream;
		runtime = substream->runtime;
		stride = runtime->frame_bits >> 3;

		for (i = 0; i < urb->number_of_packets; i++) {
139 140
			int length = urb->iso_frame_desc[i].actual_length /
				     stride;
141
			cp = (unsigned char *)urb->transfer_buffer +
142
					      urb->iso_frame_desc[i].offset;
143 144 145 146 147 148

			if (!length)
				continue;

			oldptr = dev->adev.hwptr_done_capture;
			if (oldptr + length >= runtime->buffer_size) {
149 150 151
				unsigned int cnt;

				cnt = runtime->buffer_size - oldptr;
152 153 154 155 156 157 158 159 160 161 162 163
				memcpy(runtime->dma_area + oldptr * stride, cp,
				       cnt * stride);
				memcpy(runtime->dma_area, cp + cnt * stride,
				       length * stride - cnt * stride);
			} else {
				memcpy(runtime->dma_area + oldptr * stride, cp,
				       length * stride);
			}

			snd_pcm_stream_lock(substream);

			dev->adev.hwptr_done_capture += length;
164 165 166 167
			if (dev->adev.hwptr_done_capture >=
						runtime->buffer_size)
				dev->adev.hwptr_done_capture -=
						runtime->buffer_size;
168 169

			dev->adev.capture_transfer_done += length;
170 171 172 173
			if (dev->adev.capture_transfer_done >=
				runtime->period_size) {
				dev->adev.capture_transfer_done -=
						runtime->period_size;
174 175 176 177 178 179 180 181 182 183 184
				period_elapsed = 1;
			}
			snd_pcm_stream_unlock(substream);
		}
		if (period_elapsed)
			snd_pcm_period_elapsed(substream);
	}
	urb->status = 0;

	status = usb_submit_urb(urb, GFP_ATOMIC);
	if (status < 0) {
185
		pr_err("resubmit of audio urb failed (error=%i)\n",
186
			       status);
187 188 189 190
	}
	return;
}

191 192 193 194 195 196 197 198 199 200 201
static void cx231xx_audio_bulkirq(struct urb *urb)
{
	struct cx231xx *dev = urb->context;
	unsigned int oldptr;
	int period_elapsed = 0;
	int status;
	unsigned char *cp;
	unsigned int stride;
	struct snd_pcm_substream *substream;
	struct snd_pcm_runtime *runtime;

202 203 204
	if (dev->state & DEV_DISCONNECTED)
		return;

205 206 207 208 209 210 211 212 213 214 215 216 217
	switch (urb->status) {
	case 0:		/* success */
	case -ETIMEDOUT:	/* NAK */
		break;
	case -ECONNRESET:	/* kill */
	case -ENOENT:
	case -ESHUTDOWN:
		return;
	default:		/* error */
		dprintk("urb completition error %d.\n", urb->status);
		break;
	}

218 219 220
	if (atomic_read(&dev->stream_started) == 0)
		return;

221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268
	if (dev->adev.capture_pcm_substream) {
		substream = dev->adev.capture_pcm_substream;
		runtime = substream->runtime;
		stride = runtime->frame_bits >> 3;

		if (1) {
			int length = urb->actual_length /
				     stride;
			cp = (unsigned char *)urb->transfer_buffer;

			oldptr = dev->adev.hwptr_done_capture;
			if (oldptr + length >= runtime->buffer_size) {
				unsigned int cnt;

				cnt = runtime->buffer_size - oldptr;
				memcpy(runtime->dma_area + oldptr * stride, cp,
				       cnt * stride);
				memcpy(runtime->dma_area, cp + cnt * stride,
				       length * stride - cnt * stride);
			} else {
				memcpy(runtime->dma_area + oldptr * stride, cp,
				       length * stride);
			}

			snd_pcm_stream_lock(substream);

			dev->adev.hwptr_done_capture += length;
			if (dev->adev.hwptr_done_capture >=
						runtime->buffer_size)
				dev->adev.hwptr_done_capture -=
						runtime->buffer_size;

			dev->adev.capture_transfer_done += length;
			if (dev->adev.capture_transfer_done >=
				runtime->period_size) {
				dev->adev.capture_transfer_done -=
						runtime->period_size;
				period_elapsed = 1;
			}
			snd_pcm_stream_unlock(substream);
		}
		if (period_elapsed)
			snd_pcm_period_elapsed(substream);
	}
	urb->status = 0;

	status = usb_submit_urb(urb, GFP_ATOMIC);
	if (status < 0) {
269
		pr_err("resubmit of audio urb failed (error=%i)\n",
270 271 272 273 274
			       status);
	}
	return;
}

275 276
static int cx231xx_init_audio_isoc(struct cx231xx *dev)
{
277 278
	int i, errCode;
	int sb_size;
279

280
	pr_info("%s: Starting ISO AUDIO transfers\n", __func__);
281

282 283 284
	if (dev->state & DEV_DISCONNECTED)
		return -ENODEV;

285
	sb_size = CX231XX_ISO_NUM_AUDIO_PACKETS * dev->adev.max_pkt_size;
286 287 288 289 290 291 292 293 294 295

	for (i = 0; i < CX231XX_AUDIO_BUFS; i++) {
		struct urb *urb;
		int j, k;

		dev->adev.transfer_buffer[i] = kmalloc(sb_size, GFP_ATOMIC);
		if (!dev->adev.transfer_buffer[i])
			return -ENOMEM;

		memset(dev->adev.transfer_buffer[i], 0x80, sb_size);
296
		urb = usb_alloc_urb(CX231XX_ISO_NUM_AUDIO_PACKETS, GFP_ATOMIC);
297
		if (!urb) {
298
			pr_err("usb_alloc_urb failed!\n");
299 300 301 302 303 304 305 306 307
			for (j = 0; j < i; j++) {
				usb_free_urb(dev->adev.urb[j]);
				kfree(dev->adev.transfer_buffer[j]);
			}
			return -ENOMEM;
		}

		urb->dev = dev->udev;
		urb->context = dev;
308 309
		urb->pipe = usb_rcvisocpipe(dev->udev,
						dev->adev.end_point_addr);
310
		urb->transfer_flags = URB_ISO_ASAP;
311 312 313
		urb->transfer_buffer = dev->adev.transfer_buffer[i];
		urb->interval = 1;
		urb->complete = cx231xx_audio_isocirq;
314
		urb->number_of_packets = CX231XX_ISO_NUM_AUDIO_PACKETS;
315 316
		urb->transfer_buffer_length = sb_size;

317
		for (j = k = 0; j < CX231XX_ISO_NUM_AUDIO_PACKETS;
318
			j++, k += dev->adev.max_pkt_size) {
319
			urb->iso_frame_desc[j].offset = k;
320
			urb->iso_frame_desc[j].length = dev->adev.max_pkt_size;
321 322 323 324 325 326 327 328 329 330 331 332 333 334 335
		}
		dev->adev.urb[i] = urb;
	}

	for (i = 0; i < CX231XX_AUDIO_BUFS; i++) {
		errCode = usb_submit_urb(dev->adev.urb[i], GFP_ATOMIC);
		if (errCode < 0) {
			cx231xx_isoc_audio_deinit(dev);
			return errCode;
		}
	}

	return errCode;
}

336 337 338 339 340
static int cx231xx_init_audio_bulk(struct cx231xx *dev)
{
	int i, errCode;
	int sb_size;

341
	pr_info("%s: Starting BULK AUDIO transfers\n", __func__);
342

343 344 345
	if (dev->state & DEV_DISCONNECTED)
		return -ENODEV;

346 347 348 349 350 351 352 353 354 355 356 357 358
	sb_size = CX231XX_NUM_AUDIO_PACKETS * dev->adev.max_pkt_size;

	for (i = 0; i < CX231XX_AUDIO_BUFS; i++) {
		struct urb *urb;
		int j;

		dev->adev.transfer_buffer[i] = kmalloc(sb_size, GFP_ATOMIC);
		if (!dev->adev.transfer_buffer[i])
			return -ENOMEM;

		memset(dev->adev.transfer_buffer[i], 0x80, sb_size);
		urb = usb_alloc_urb(CX231XX_NUM_AUDIO_PACKETS, GFP_ATOMIC);
		if (!urb) {
359
			pr_err("usb_alloc_urb failed!\n");
360 361 362 363 364 365 366 367 368 369 370
			for (j = 0; j < i; j++) {
				usb_free_urb(dev->adev.urb[j]);
				kfree(dev->adev.transfer_buffer[j]);
			}
			return -ENOMEM;
		}

		urb->dev = dev->udev;
		urb->context = dev;
		urb->pipe = usb_rcvbulkpipe(dev->udev,
						dev->adev.end_point_addr);
371
		urb->transfer_flags = 0;
372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390
		urb->transfer_buffer = dev->adev.transfer_buffer[i];
		urb->complete = cx231xx_audio_bulkirq;
		urb->transfer_buffer_length = sb_size;

		dev->adev.urb[i] = urb;

	}

	for (i = 0; i < CX231XX_AUDIO_BUFS; i++) {
		errCode = usb_submit_urb(dev->adev.urb[i], GFP_ATOMIC);
		if (errCode < 0) {
			cx231xx_bulk_audio_deinit(dev);
			return errCode;
		}
	}

	return errCode;
}

391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412
static int snd_pcm_alloc_vmalloc_buffer(struct snd_pcm_substream *subs,
					size_t size)
{
	struct snd_pcm_runtime *runtime = subs->runtime;

	dprintk("Allocating vbuffer\n");
	if (runtime->dma_area) {
		if (runtime->dma_bytes > size)
			return 0;

		vfree(runtime->dma_area);
	}
	runtime->dma_area = vmalloc(size);
	if (!runtime->dma_area)
		return -ENOMEM;

	runtime->dma_bytes = size;

	return 0;
}

static struct snd_pcm_hardware snd_cx231xx_hw_capture = {
413 414 415 416
	.info = SNDRV_PCM_INFO_BLOCK_TRANSFER 	|
	    SNDRV_PCM_INFO_MMAP 		|
	    SNDRV_PCM_INFO_INTERLEAVED 		|
	    SNDRV_PCM_INFO_MMAP_VALID,
417 418 419 420 421 422 423 424 425 426

	.formats = SNDRV_PCM_FMTBIT_S16_LE,

	.rates = SNDRV_PCM_RATE_CONTINUOUS | SNDRV_PCM_RATE_KNOT,

	.rate_min = 48000,
	.rate_max = 48000,
	.channels_min = 2,
	.channels_max = 2,
	.buffer_bytes_max = 62720 * 8,	/* just about the value in usbaudio.c */
427
	.period_bytes_min = 64,		/* 12544/2, */
428 429
	.period_bytes_max = 12544,
	.periods_min = 2,
430
	.periods_max = 98,		/* 12544, */
431 432 433 434 435 436 437 438 439 440 441
};

static int snd_cx231xx_capture_open(struct snd_pcm_substream *substream)
{
	struct cx231xx *dev = snd_pcm_substream_chip(substream);
	struct snd_pcm_runtime *runtime = substream->runtime;
	int ret = 0;

	dprintk("opening device and trying to acquire exclusive lock\n");

	if (!dev) {
442
		pr_err("BUG: cx231xx can't find device struct."
443
			       " Can't proceed with open\n");
444 445 446
		return -ENODEV;
	}

447
	if (dev->state & DEV_DISCONNECTED) {
448
		pr_err("Can't open. the device was removed.\n");
449 450 451
		return -ENODEV;
	}

452
	/* set alternate setting for audio interface */
453
	/* 1 - 48000 samples per sec */
454
	mutex_lock(&dev->lock);
455 456 457 458
	if (dev->USE_ISO)
		ret = cx231xx_set_alt_setting(dev, INDEX_AUDIO, 1);
	else
		ret = cx231xx_set_alt_setting(dev, INDEX_AUDIO, 0);
459
	mutex_unlock(&dev->lock);
460
	if (ret < 0) {
461
		pr_err("failed to set alternate setting !\n");
462

463 464
		return ret;
	}
465 466 467

	runtime->hw = snd_cx231xx_hw_capture;

468
	mutex_lock(&dev->lock);
469 470 471
	/* inform hardware to start streaming */
	ret = cx231xx_capture_start(dev, 1, Audio);

472
	dev->adev.users++;
473
	mutex_unlock(&dev->lock);
474 475 476 477 478 479 480 481 482 483

	snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS);
	dev->adev.capture_pcm_substream = substream;
	runtime->private_data = dev;

	return 0;
}

static int snd_cx231xx_pcm_close(struct snd_pcm_substream *substream)
{
484
	int ret;
485 486 487 488
	struct cx231xx *dev = snd_pcm_substream_chip(substream);

	dprintk("closing device\n");

489 490
	/* inform hardware to stop streaming */
	mutex_lock(&dev->lock);
491 492
	ret = cx231xx_capture_start(dev, 0, Audio);

493
	/* set alternate setting for audio interface */
494 495
	/* 1 - 48000 samples per sec */
	ret = cx231xx_set_alt_setting(dev, INDEX_AUDIO, 0);
496
	if (ret < 0) {
497
		pr_err("failed to set alternate setting !\n");
498

499
		mutex_unlock(&dev->lock);
500 501
		return ret;
	}
502

503
	dev->adev.users--;
504 505 506 507 508 509 510
	mutex_unlock(&dev->lock);

	if (dev->adev.users == 0 && dev->adev.shutdown == 1) {
		dprintk("audio users: %d\n", dev->adev.users);
		dprintk("disabling audio stream!\n");
		dev->adev.shutdown = 0;
		dprintk("released lock\n");
511 512 513 514
		if (atomic_read(&dev->stream_started) > 0) {
			atomic_set(&dev->stream_started, 0);
			schedule_work(&dev->wq_trigger);
		}
515 516 517 518 519
	}
	return 0;
}

static int snd_cx231xx_hw_capture_params(struct snd_pcm_substream *substream,
520
					 struct snd_pcm_hw_params *hw_params)
521 522 523 524 525 526
{
	int ret;

	dprintk("Setting capture parameters\n");

	ret = snd_pcm_alloc_vmalloc_buffer(substream,
527
					   params_buffer_bytes(hw_params));
528 529 530 531 532 533
#if 0
	/* TODO: set up cx231xx audio chip to deliver the correct audio format,
	   current default is 48000hz multiplexed => 96000hz mono
	   which shouldn't matter since analogue TV only supports mono */
	unsigned int channels, rate, format;

534 535 536
	format = params_format(hw_params);
	rate = params_rate(hw_params);
	channels = params_channels(hw_params);
537
#endif
538

539
	return ret;
540 541 542 543 544 545 546 547
}

static int snd_cx231xx_hw_capture_free(struct snd_pcm_substream *substream)
{
	struct cx231xx *dev = snd_pcm_substream_chip(substream);

	dprintk("Stop capture, if needed\n");

548 549 550 551
	if (atomic_read(&dev->stream_started) > 0) {
		atomic_set(&dev->stream_started, 0);
		schedule_work(&dev->wq_trigger);
	}
552 553 554 555 556 557

	return 0;
}

static int snd_cx231xx_prepare(struct snd_pcm_substream *substream)
{
558 559 560 561 562
	struct cx231xx *dev = snd_pcm_substream_chip(substream);

	dev->adev.hwptr_done_capture = 0;
	dev->adev.capture_transfer_done = 0;

563 564 565
	return 0;
}

566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583
static void audio_trigger(struct work_struct *work)
{
	struct cx231xx *dev = container_of(work, struct cx231xx, wq_trigger);

	if (atomic_read(&dev->stream_started)) {
		dprintk("starting capture");
		if (is_fw_load(dev) == 0)
			cx25840_call(dev, core, load_fw);
		if (dev->USE_ISO)
			cx231xx_init_audio_isoc(dev);
		else
			cx231xx_init_audio_bulk(dev);
	} else {
		dprintk("stopping capture");
		cx231xx_isoc_audio_deinit(dev);
	}
}

584
static int snd_cx231xx_capture_trigger(struct snd_pcm_substream *substream,
585
				       int cmd)
586 587
{
	struct cx231xx *dev = snd_pcm_substream_chip(substream);
588
	int retval = 0;
589

590 591 592
	if (dev->state & DEV_DISCONNECTED)
		return -ENODEV;

593
	spin_lock(&dev->adev.slock);
594 595
	switch (cmd) {
	case SNDRV_PCM_TRIGGER_START:
596
		atomic_set(&dev->stream_started, 1);
597 598
		break;
	case SNDRV_PCM_TRIGGER_STOP:
599
		atomic_set(&dev->stream_started, 0);
600
		break;
601 602
	default:
		retval = -EINVAL;
603
		break;
604
	}
605
	spin_unlock(&dev->adev.slock);
606 607 608

	schedule_work(&dev->wq_trigger);

609
	return retval;
610 611 612
}

static snd_pcm_uframes_t snd_cx231xx_capture_pointer(struct snd_pcm_substream
613
						     *substream)
614 615
{
	struct cx231xx *dev;
616
	unsigned long flags;
617 618 619 620
	snd_pcm_uframes_t hwptr_done;

	dev = snd_pcm_substream_chip(substream);

621
	spin_lock_irqsave(&dev->adev.slock, flags);
622
	hwptr_done = dev->adev.hwptr_done_capture;
623
	spin_unlock_irqrestore(&dev->adev.slock, flags);
624 625 626 627 628 629 630 631 632 633 634 635 636

	return hwptr_done;
}

static struct page *snd_pcm_get_vmalloc_page(struct snd_pcm_substream *subs,
					     unsigned long offset)
{
	void *pageptr = subs->runtime->dma_area + offset;

	return vmalloc_to_page(pageptr);
}

static struct snd_pcm_ops snd_cx231xx_pcm_capture = {
637 638 639
	.open = snd_cx231xx_capture_open,
	.close = snd_cx231xx_pcm_close,
	.ioctl = snd_pcm_lib_ioctl,
640
	.hw_params = snd_cx231xx_hw_capture_params,
641 642 643 644 645
	.hw_free = snd_cx231xx_hw_capture_free,
	.prepare = snd_cx231xx_prepare,
	.trigger = snd_cx231xx_capture_trigger,
	.pointer = snd_cx231xx_capture_pointer,
	.page = snd_pcm_get_vmalloc_page,
646 647 648 649 650
};

static int cx231xx_audio_init(struct cx231xx *dev)
{
	struct cx231xx_audio *adev = &dev->adev;
651 652 653 654 655 656
	struct snd_pcm *pcm;
	struct snd_card *card;
	static int devnr;
	int err;
	struct usb_interface *uif;
	int i, isoc_pipe = 0;
657 658 659 660 661 662 663 664

	if (dev->has_alsa_audio != 1) {
		/* This device does not support the extension (in this case
		   the device is expecting the snd-usb-audio module or
		   doesn't have analog audio support at all) */
		return 0;
	}

665
	pr_info("cx231xx-audio.c: probing for cx231xx "
666
		     "non standard usbaudio\n");
667

668 669
	err = snd_card_new(&dev->udev->dev, index[devnr], "Cx231xx Audio",
			   THIS_MODULE, 0, &card);
670 671
	if (err < 0)
		return err;
672 673 674 675 676 677 678 679

	spin_lock_init(&adev->slock);
	err = snd_pcm_new(card, "Cx231xx Audio", 0, 0, 1, &pcm);
	if (err < 0) {
		snd_card_free(card);
		return err;
	}

680 681
	snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE,
			&snd_cx231xx_pcm_capture);
682 683 684
	pcm->info_flags = 0;
	pcm->private_data = dev;
	strcpy(pcm->name, "Conexant cx231xx Capture");
685
	strcpy(card->driver, "Cx231xx-Audio");
686 687 688
	strcpy(card->shortname, "Cx231xx Audio");
	strcpy(card->longname, "Conexant cx231xx Audio");

689 690
	INIT_WORK(&dev->wq_trigger, audio_trigger);

691 692 693 694 695 696 697 698
	err = snd_card_register(card);
	if (err < 0) {
		snd_card_free(card);
		return err;
	}
	adev->sndcard = card;
	adev->udev = dev->udev;

699 700 701 702 703
	/* compute alternate max packet sizes for Audio */
	uif =
	    dev->udev->actconfig->interface[dev->current_pcb_config.
					    hs_config_info[0].interface_info.
					    audio_index + 1];
704

705
	adev->end_point_addr =
706 707
	    uif->altsetting[0].endpoint[isoc_pipe].desc.
			bEndpointAddress;
708

709
	adev->num_alt = uif->num_altsetting;
710
	pr_info("EndPoint Addr 0x%x, Alternate settings: %i\n",
711 712
		     adev->end_point_addr, adev->num_alt);
	adev->alt_max_pkt_size = kmalloc(32 * adev->num_alt, GFP_KERNEL);
713

714
	if (adev->alt_max_pkt_size == NULL) {
715
		pr_err("out of memory!\n");
716 717
		return -ENOMEM;
	}
718

719 720 721 722 723 724
	for (i = 0; i < adev->num_alt; i++) {
		u16 tmp =
		    le16_to_cpu(uif->altsetting[i].endpoint[isoc_pipe].desc.
				wMaxPacketSize);
		adev->alt_max_pkt_size[i] =
		    (tmp & 0x07ff) * (((tmp & 0x1800) >> 11) + 1);
725
		pr_info("Alternate setting %i, max size= %i\n", i,
726 727
			     adev->alt_max_pkt_size[i]);
	}
728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745

	return 0;
}

static int cx231xx_audio_fini(struct cx231xx *dev)
{
	if (dev == NULL)
		return 0;

	if (dev->has_alsa_audio != 1) {
		/* This device does not support the extension (in this case
		   the device is expecting the snd-usb-audio module or
		   doesn't have analog audio support at all) */
		return 0;
	}

	if (dev->adev.sndcard) {
		snd_card_free(dev->adev.sndcard);
746
		kfree(dev->adev.alt_max_pkt_size);
747 748 749 750 751 752 753
		dev->adev.sndcard = NULL;
	}

	return 0;
}

static struct cx231xx_ops audio_ops = {
754
	.id = CX231XX_AUDIO,
755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775
	.name = "Cx231xx Audio Extension",
	.init = cx231xx_audio_init,
	.fini = cx231xx_audio_fini,
};

static int __init cx231xx_alsa_register(void)
{
	return cx231xx_register_extension(&audio_ops);
}

static void __exit cx231xx_alsa_unregister(void)
{
	cx231xx_unregister_extension(&audio_ops);
}

MODULE_LICENSE("GPL");
MODULE_AUTHOR("Srinivasa Deevi <srinivasa.deevi@conexant.com>");
MODULE_DESCRIPTION("Cx231xx Audio driver");

module_init(cx231xx_alsa_register);
module_exit(cx231xx_alsa_unregister);