linux/drivers/media/usb/cx231xx/cx231xx-audio.c
<<
>>
Prefs
   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
  27static int debug;
  28module_param(debug, int, 0644);
  29MODULE_PARM_DESC(debug, "activates debug info");
  30
  31static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX;
  32
  33static 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
  57static 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
  81static 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
 173static 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
 260static 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
 321static 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
 376static 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
 398static 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
 419static 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
 465static 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
 508static 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
 532static 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
 546static 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
 556static 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
 574static 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
 602static 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
 618static 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
 626static 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
 638static 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
 730err_free_pkt_size:
 731        kfree(adev->alt_max_pkt_size);
 732err_free_card:
 733        snd_card_free(card);
 734
 735        return err;
 736}
 737
 738static 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
 759static 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
 766static int __init cx231xx_alsa_register(void)
 767{
 768        return cx231xx_register_extension(&audio_ops);
 769}
 770
 771static void __exit cx231xx_alsa_unregister(void)
 772{
 773        cx231xx_unregister_extension(&audio_ops);
 774}
 775
 776MODULE_LICENSE("GPL");
 777MODULE_AUTHOR("Srinivasa Deevi <srinivasa.deevi@conexant.com>");
 778MODULE_DESCRIPTION("Cx231xx Audio driver");
 779
 780module_init(cx231xx_alsa_register);
 781module_exit(cx231xx_alsa_unregister);
 782