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