linux/sound/pci/ctxfi/ctpcm.c
<<
>>
Prefs
   1/**
   2 * Copyright (C) 2008, Creative Technology Ltd. All Rights Reserved.
   3 *
   4 * This source file is released under GPL v2 license (no other versions).
   5 * See the COPYING file included in the main directory of this source
   6 * distribution for the license terms and conditions.
   7 *
   8 * @File        ctpcm.c
   9 *
  10 * @Brief
  11 * This file contains the definition of the pcm device functions.
  12 *
  13 * @Author      Liu Chun
  14 * @Date        Apr 2 2008
  15 *
  16 */
  17
  18#include "ctpcm.h"
  19#include "cttimer.h"
  20#include <linux/slab.h>
  21#include <sound/pcm.h>
  22
  23/* Hardware descriptions for playback */
  24static struct snd_pcm_hardware ct_pcm_playback_hw = {
  25        .info                   = (SNDRV_PCM_INFO_MMAP |
  26                                   SNDRV_PCM_INFO_INTERLEAVED |
  27                                   SNDRV_PCM_INFO_BLOCK_TRANSFER |
  28                                   SNDRV_PCM_INFO_MMAP_VALID |
  29                                   SNDRV_PCM_INFO_PAUSE),
  30        .formats                = (SNDRV_PCM_FMTBIT_U8 |
  31                                   SNDRV_PCM_FMTBIT_S16_LE |
  32                                   SNDRV_PCM_FMTBIT_S24_3LE |
  33                                   SNDRV_PCM_FMTBIT_S32_LE |
  34                                   SNDRV_PCM_FMTBIT_FLOAT_LE),
  35        .rates                  = (SNDRV_PCM_RATE_CONTINUOUS |
  36                                   SNDRV_PCM_RATE_8000_192000),
  37        .rate_min               = 8000,
  38        .rate_max               = 192000,
  39        .channels_min           = 1,
  40        .channels_max           = 2,
  41        .buffer_bytes_max       = (128*1024),
  42        .period_bytes_min       = (64),
  43        .period_bytes_max       = (128*1024),
  44        .periods_min            = 2,
  45        .periods_max            = 1024,
  46        .fifo_size              = 0,
  47};
  48
  49static struct snd_pcm_hardware ct_spdif_passthru_playback_hw = {
  50        .info                   = (SNDRV_PCM_INFO_MMAP |
  51                                   SNDRV_PCM_INFO_INTERLEAVED |
  52                                   SNDRV_PCM_INFO_BLOCK_TRANSFER |
  53                                   SNDRV_PCM_INFO_MMAP_VALID |
  54                                   SNDRV_PCM_INFO_PAUSE),
  55        .formats                = SNDRV_PCM_FMTBIT_S16_LE,
  56        .rates                  = (SNDRV_PCM_RATE_48000 |
  57                                   SNDRV_PCM_RATE_44100 |
  58                                   SNDRV_PCM_RATE_32000),
  59        .rate_min               = 32000,
  60        .rate_max               = 48000,
  61        .channels_min           = 2,
  62        .channels_max           = 2,
  63        .buffer_bytes_max       = (128*1024),
  64        .period_bytes_min       = (64),
  65        .period_bytes_max       = (128*1024),
  66        .periods_min            = 2,
  67        .periods_max            = 1024,
  68        .fifo_size              = 0,
  69};
  70
  71/* Hardware descriptions for capture */
  72static struct snd_pcm_hardware ct_pcm_capture_hw = {
  73        .info                   = (SNDRV_PCM_INFO_MMAP |
  74                                   SNDRV_PCM_INFO_INTERLEAVED |
  75                                   SNDRV_PCM_INFO_BLOCK_TRANSFER |
  76                                   SNDRV_PCM_INFO_PAUSE |
  77                                   SNDRV_PCM_INFO_MMAP_VALID),
  78        .formats                = (SNDRV_PCM_FMTBIT_U8 |
  79                                   SNDRV_PCM_FMTBIT_S16_LE |
  80                                   SNDRV_PCM_FMTBIT_S24_3LE |
  81                                   SNDRV_PCM_FMTBIT_S32_LE |
  82                                   SNDRV_PCM_FMTBIT_FLOAT_LE),
  83        .rates                  = (SNDRV_PCM_RATE_CONTINUOUS |
  84                                   SNDRV_PCM_RATE_8000_96000),
  85        .rate_min               = 8000,
  86        .rate_max               = 96000,
  87        .channels_min           = 1,
  88        .channels_max           = 2,
  89        .buffer_bytes_max       = (128*1024),
  90        .period_bytes_min       = (384),
  91        .period_bytes_max       = (64*1024),
  92        .periods_min            = 2,
  93        .periods_max            = 1024,
  94        .fifo_size              = 0,
  95};
  96
  97static void ct_atc_pcm_interrupt(struct ct_atc_pcm *atc_pcm)
  98{
  99        struct ct_atc_pcm *apcm = atc_pcm;
 100
 101        if (!apcm->substream)
 102                return;
 103
 104        snd_pcm_period_elapsed(apcm->substream);
 105}
 106
 107static void ct_atc_pcm_free_substream(struct snd_pcm_runtime *runtime)
 108{
 109        struct ct_atc_pcm *apcm = runtime->private_data;
 110        struct ct_atc *atc = snd_pcm_substream_chip(apcm->substream);
 111
 112        atc->pcm_release_resources(atc, apcm);
 113        ct_timer_instance_free(apcm->timer);
 114        kfree(apcm);
 115        runtime->private_data = NULL;
 116}
 117
 118/* pcm playback operations */
 119static int ct_pcm_playback_open(struct snd_pcm_substream *substream)
 120{
 121        struct ct_atc *atc = snd_pcm_substream_chip(substream);
 122        struct snd_pcm_runtime *runtime = substream->runtime;
 123        struct ct_atc_pcm *apcm;
 124        int err;
 125
 126        apcm = kzalloc(sizeof(*apcm), GFP_KERNEL);
 127        if (!apcm)
 128                return -ENOMEM;
 129
 130        apcm->substream = substream;
 131        apcm->interrupt = ct_atc_pcm_interrupt;
 132        if (IEC958 == substream->pcm->device) {
 133                runtime->hw = ct_spdif_passthru_playback_hw;
 134                atc->spdif_out_passthru(atc, 1);
 135        } else {
 136                runtime->hw = ct_pcm_playback_hw;
 137                if (FRONT == substream->pcm->device)
 138                        runtime->hw.channels_max = 8;
 139        }
 140
 141        err = snd_pcm_hw_constraint_integer(runtime,
 142                                            SNDRV_PCM_HW_PARAM_PERIODS);
 143        if (err < 0) {
 144                kfree(apcm);
 145                return err;
 146        }
 147        err = snd_pcm_hw_constraint_minmax(runtime,
 148                                           SNDRV_PCM_HW_PARAM_BUFFER_BYTES,
 149                                           1024, UINT_MAX);
 150        if (err < 0) {
 151                kfree(apcm);
 152                return err;
 153        }
 154
 155        apcm->timer = ct_timer_instance_new(atc->timer, apcm);
 156        if (!apcm->timer) {
 157                kfree(apcm);
 158                return -ENOMEM;
 159        }
 160        runtime->private_data = apcm;
 161        runtime->private_free = ct_atc_pcm_free_substream;
 162
 163        return 0;
 164}
 165
 166static int ct_pcm_playback_close(struct snd_pcm_substream *substream)
 167{
 168        struct ct_atc *atc = snd_pcm_substream_chip(substream);
 169
 170        /* TODO: Notify mixer inactive. */
 171        if (IEC958 == substream->pcm->device)
 172                atc->spdif_out_passthru(atc, 0);
 173
 174        /* The ct_atc_pcm object will be freed by runtime->private_free */
 175
 176        return 0;
 177}
 178
 179static int ct_pcm_hw_params(struct snd_pcm_substream *substream,
 180                                     struct snd_pcm_hw_params *hw_params)
 181{
 182        struct ct_atc *atc = snd_pcm_substream_chip(substream);
 183        struct ct_atc_pcm *apcm = substream->runtime->private_data;
 184        int err;
 185
 186        err = snd_pcm_lib_malloc_pages(substream,
 187                                        params_buffer_bytes(hw_params));
 188        if (err < 0)
 189                return err;
 190        /* clear previous resources */
 191        atc->pcm_release_resources(atc, apcm);
 192        return err;
 193}
 194
 195static int ct_pcm_hw_free(struct snd_pcm_substream *substream)
 196{
 197        struct ct_atc *atc = snd_pcm_substream_chip(substream);
 198        struct ct_atc_pcm *apcm = substream->runtime->private_data;
 199
 200        /* clear previous resources */
 201        atc->pcm_release_resources(atc, apcm);
 202        /* Free snd-allocated pages */
 203        return snd_pcm_lib_free_pages(substream);
 204}
 205
 206
 207static int ct_pcm_playback_prepare(struct snd_pcm_substream *substream)
 208{
 209        int err;
 210        struct ct_atc *atc = snd_pcm_substream_chip(substream);
 211        struct snd_pcm_runtime *runtime = substream->runtime;
 212        struct ct_atc_pcm *apcm = runtime->private_data;
 213
 214        if (IEC958 == substream->pcm->device)
 215                err = atc->spdif_passthru_playback_prepare(atc, apcm);
 216        else
 217                err = atc->pcm_playback_prepare(atc, apcm);
 218
 219        if (err < 0) {
 220                printk(KERN_ERR "ctxfi: Preparing pcm playback failed!!!\n");
 221                return err;
 222        }
 223
 224        return 0;
 225}
 226
 227static int
 228ct_pcm_playback_trigger(struct snd_pcm_substream *substream, int cmd)
 229{
 230        struct ct_atc *atc = snd_pcm_substream_chip(substream);
 231        struct snd_pcm_runtime *runtime = substream->runtime;
 232        struct ct_atc_pcm *apcm = runtime->private_data;
 233
 234        switch (cmd) {
 235        case SNDRV_PCM_TRIGGER_START:
 236        case SNDRV_PCM_TRIGGER_RESUME:
 237        case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
 238                atc->pcm_playback_start(atc, apcm);
 239                break;
 240        case SNDRV_PCM_TRIGGER_STOP:
 241        case SNDRV_PCM_TRIGGER_SUSPEND:
 242        case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
 243                atc->pcm_playback_stop(atc, apcm);
 244                break;
 245        default:
 246                break;
 247        }
 248
 249        return 0;
 250}
 251
 252static snd_pcm_uframes_t
 253ct_pcm_playback_pointer(struct snd_pcm_substream *substream)
 254{
 255        unsigned long position;
 256        struct ct_atc *atc = snd_pcm_substream_chip(substream);
 257        struct snd_pcm_runtime *runtime = substream->runtime;
 258        struct ct_atc_pcm *apcm = runtime->private_data;
 259
 260        /* Read out playback position */
 261        position = atc->pcm_playback_position(atc, apcm);
 262        position = bytes_to_frames(runtime, position);
 263        if (position >= runtime->buffer_size)
 264                position = 0;
 265        return position;
 266}
 267
 268/* pcm capture operations */
 269static int ct_pcm_capture_open(struct snd_pcm_substream *substream)
 270{
 271        struct ct_atc *atc = snd_pcm_substream_chip(substream);
 272        struct snd_pcm_runtime *runtime = substream->runtime;
 273        struct ct_atc_pcm *apcm;
 274        int err;
 275
 276        apcm = kzalloc(sizeof(*apcm), GFP_KERNEL);
 277        if (!apcm)
 278                return -ENOMEM;
 279
 280        apcm->started = 0;
 281        apcm->substream = substream;
 282        apcm->interrupt = ct_atc_pcm_interrupt;
 283        runtime->hw = ct_pcm_capture_hw;
 284        runtime->hw.rate_max = atc->rsr * atc->msr;
 285
 286        err = snd_pcm_hw_constraint_integer(runtime,
 287                                            SNDRV_PCM_HW_PARAM_PERIODS);
 288        if (err < 0) {
 289                kfree(apcm);
 290                return err;
 291        }
 292        err = snd_pcm_hw_constraint_minmax(runtime,
 293                                           SNDRV_PCM_HW_PARAM_BUFFER_BYTES,
 294                                           1024, UINT_MAX);
 295        if (err < 0) {
 296                kfree(apcm);
 297                return err;
 298        }
 299
 300        apcm->timer = ct_timer_instance_new(atc->timer, apcm);
 301        if (!apcm->timer) {
 302                kfree(apcm);
 303                return -ENOMEM;
 304        }
 305        runtime->private_data = apcm;
 306        runtime->private_free = ct_atc_pcm_free_substream;
 307
 308        return 0;
 309}
 310
 311static int ct_pcm_capture_close(struct snd_pcm_substream *substream)
 312{
 313        /* The ct_atc_pcm object will be freed by runtime->private_free */
 314        /* TODO: Notify mixer inactive. */
 315        return 0;
 316}
 317
 318static int ct_pcm_capture_prepare(struct snd_pcm_substream *substream)
 319{
 320        int err;
 321        struct ct_atc *atc = snd_pcm_substream_chip(substream);
 322        struct snd_pcm_runtime *runtime = substream->runtime;
 323        struct ct_atc_pcm *apcm = runtime->private_data;
 324
 325        err = atc->pcm_capture_prepare(atc, apcm);
 326        if (err < 0) {
 327                printk(KERN_ERR "ctxfi: Preparing pcm capture failed!!!\n");
 328                return err;
 329        }
 330
 331        return 0;
 332}
 333
 334static int
 335ct_pcm_capture_trigger(struct snd_pcm_substream *substream, int cmd)
 336{
 337        struct ct_atc *atc = snd_pcm_substream_chip(substream);
 338        struct snd_pcm_runtime *runtime = substream->runtime;
 339        struct ct_atc_pcm *apcm = runtime->private_data;
 340
 341        switch (cmd) {
 342        case SNDRV_PCM_TRIGGER_START:
 343                atc->pcm_capture_start(atc, apcm);
 344                break;
 345        case SNDRV_PCM_TRIGGER_STOP:
 346                atc->pcm_capture_stop(atc, apcm);
 347                break;
 348        default:
 349                atc->pcm_capture_stop(atc, apcm);
 350                break;
 351        }
 352
 353        return 0;
 354}
 355
 356static snd_pcm_uframes_t
 357ct_pcm_capture_pointer(struct snd_pcm_substream *substream)
 358{
 359        unsigned long position;
 360        struct ct_atc *atc = snd_pcm_substream_chip(substream);
 361        struct snd_pcm_runtime *runtime = substream->runtime;
 362        struct ct_atc_pcm *apcm = runtime->private_data;
 363
 364        /* Read out playback position */
 365        position = atc->pcm_capture_position(atc, apcm);
 366        position = bytes_to_frames(runtime, position);
 367        if (position >= runtime->buffer_size)
 368                position = 0;
 369        return position;
 370}
 371
 372/* PCM operators for playback */
 373static struct snd_pcm_ops ct_pcm_playback_ops = {
 374        .open           = ct_pcm_playback_open,
 375        .close          = ct_pcm_playback_close,
 376        .ioctl          = snd_pcm_lib_ioctl,
 377        .hw_params      = ct_pcm_hw_params,
 378        .hw_free        = ct_pcm_hw_free,
 379        .prepare        = ct_pcm_playback_prepare,
 380        .trigger        = ct_pcm_playback_trigger,
 381        .pointer        = ct_pcm_playback_pointer,
 382        .page           = snd_pcm_sgbuf_ops_page,
 383};
 384
 385/* PCM operators for capture */
 386static struct snd_pcm_ops ct_pcm_capture_ops = {
 387        .open           = ct_pcm_capture_open,
 388        .close          = ct_pcm_capture_close,
 389        .ioctl          = snd_pcm_lib_ioctl,
 390        .hw_params      = ct_pcm_hw_params,
 391        .hw_free        = ct_pcm_hw_free,
 392        .prepare        = ct_pcm_capture_prepare,
 393        .trigger        = ct_pcm_capture_trigger,
 394        .pointer        = ct_pcm_capture_pointer,
 395        .page           = snd_pcm_sgbuf_ops_page,
 396};
 397
 398/* Create ALSA pcm device */
 399int ct_alsa_pcm_create(struct ct_atc *atc,
 400                       enum CTALSADEVS device,
 401                       const char *device_name)
 402{
 403        struct snd_pcm *pcm;
 404        int err;
 405        int playback_count, capture_count;
 406
 407        playback_count = (IEC958 == device) ? 1 : 8;
 408        capture_count = (FRONT == device) ? 1 : 0;
 409        err = snd_pcm_new(atc->card, "ctxfi", device,
 410                          playback_count, capture_count, &pcm);
 411        if (err < 0) {
 412                printk(KERN_ERR "ctxfi: snd_pcm_new failed!! Err=%d\n", err);
 413                return err;
 414        }
 415
 416        pcm->private_data = atc;
 417        pcm->info_flags = 0;
 418        pcm->dev_subclass = SNDRV_PCM_SUBCLASS_GENERIC_MIX;
 419        strlcpy(pcm->name, device_name, sizeof(pcm->name));
 420
 421        snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &ct_pcm_playback_ops);
 422
 423        if (FRONT == device)
 424                snd_pcm_set_ops(pcm,
 425                                SNDRV_PCM_STREAM_CAPTURE, &ct_pcm_capture_ops);
 426
 427        snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV_SG,
 428                        snd_dma_pci_data(atc->pci), 128*1024, 128*1024);
 429
 430#ifdef CONFIG_PM
 431        atc->pcms[device] = pcm;
 432#endif
 433
 434        return 0;
 435}
 436