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 const 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 const 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 const 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                goto free_pcm;
 145
 146        err = snd_pcm_hw_constraint_minmax(runtime,
 147                                           SNDRV_PCM_HW_PARAM_BUFFER_BYTES,
 148                                           1024, UINT_MAX);
 149        if (err < 0)
 150                goto free_pcm;
 151
 152        apcm->timer = ct_timer_instance_new(atc->timer, apcm);
 153        if (!apcm->timer) {
 154                err = -ENOMEM;
 155                goto free_pcm;
 156        }
 157        runtime->private_data = apcm;
 158        runtime->private_free = ct_atc_pcm_free_substream;
 159
 160        return 0;
 161
 162free_pcm:
 163        kfree(apcm);
 164        return err;
 165}
 166
 167static int ct_pcm_playback_close(struct snd_pcm_substream *substream)
 168{
 169        struct ct_atc *atc = snd_pcm_substream_chip(substream);
 170
 171        /* TODO: Notify mixer inactive. */
 172        if (IEC958 == substream->pcm->device)
 173                atc->spdif_out_passthru(atc, 0);
 174
 175        /* The ct_atc_pcm object will be freed by runtime->private_free */
 176
 177        return 0;
 178}
 179
 180static int ct_pcm_hw_params(struct snd_pcm_substream *substream,
 181                                     struct snd_pcm_hw_params *hw_params)
 182{
 183        struct ct_atc *atc = snd_pcm_substream_chip(substream);
 184        struct ct_atc_pcm *apcm = substream->runtime->private_data;
 185        int err;
 186
 187        err = snd_pcm_lib_malloc_pages(substream,
 188                                        params_buffer_bytes(hw_params));
 189        if (err < 0)
 190                return err;
 191        /* clear previous resources */
 192        atc->pcm_release_resources(atc, apcm);
 193        return err;
 194}
 195
 196static int ct_pcm_hw_free(struct snd_pcm_substream *substream)
 197{
 198        struct ct_atc *atc = snd_pcm_substream_chip(substream);
 199        struct ct_atc_pcm *apcm = substream->runtime->private_data;
 200
 201        /* clear previous resources */
 202        atc->pcm_release_resources(atc, apcm);
 203        /* Free snd-allocated pages */
 204        return snd_pcm_lib_free_pages(substream);
 205}
 206
 207
 208static int ct_pcm_playback_prepare(struct snd_pcm_substream *substream)
 209{
 210        int err;
 211        struct ct_atc *atc = snd_pcm_substream_chip(substream);
 212        struct snd_pcm_runtime *runtime = substream->runtime;
 213        struct ct_atc_pcm *apcm = runtime->private_data;
 214
 215        if (IEC958 == substream->pcm->device)
 216                err = atc->spdif_passthru_playback_prepare(atc, apcm);
 217        else
 218                err = atc->pcm_playback_prepare(atc, apcm);
 219
 220        if (err < 0) {
 221                dev_err(atc->card->dev,
 222                        "Preparing pcm playback failed!!!\n");
 223                return err;
 224        }
 225
 226        return 0;
 227}
 228
 229static int
 230ct_pcm_playback_trigger(struct snd_pcm_substream *substream, int cmd)
 231{
 232        struct ct_atc *atc = snd_pcm_substream_chip(substream);
 233        struct snd_pcm_runtime *runtime = substream->runtime;
 234        struct ct_atc_pcm *apcm = runtime->private_data;
 235
 236        switch (cmd) {
 237        case SNDRV_PCM_TRIGGER_START:
 238        case SNDRV_PCM_TRIGGER_RESUME:
 239        case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
 240                atc->pcm_playback_start(atc, apcm);
 241                break;
 242        case SNDRV_PCM_TRIGGER_STOP:
 243        case SNDRV_PCM_TRIGGER_SUSPEND:
 244        case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
 245                atc->pcm_playback_stop(atc, apcm);
 246                break;
 247        default:
 248                break;
 249        }
 250
 251        return 0;
 252}
 253
 254static snd_pcm_uframes_t
 255ct_pcm_playback_pointer(struct snd_pcm_substream *substream)
 256{
 257        unsigned long position;
 258        struct ct_atc *atc = snd_pcm_substream_chip(substream);
 259        struct snd_pcm_runtime *runtime = substream->runtime;
 260        struct ct_atc_pcm *apcm = runtime->private_data;
 261
 262        /* Read out playback position */
 263        position = atc->pcm_playback_position(atc, apcm);
 264        position = bytes_to_frames(runtime, position);
 265        if (position >= runtime->buffer_size)
 266                position = 0;
 267        return position;
 268}
 269
 270/* pcm capture operations */
 271static int ct_pcm_capture_open(struct snd_pcm_substream *substream)
 272{
 273        struct ct_atc *atc = snd_pcm_substream_chip(substream);
 274        struct snd_pcm_runtime *runtime = substream->runtime;
 275        struct ct_atc_pcm *apcm;
 276        int err;
 277
 278        apcm = kzalloc(sizeof(*apcm), GFP_KERNEL);
 279        if (!apcm)
 280                return -ENOMEM;
 281
 282        apcm->started = 0;
 283        apcm->substream = substream;
 284        apcm->interrupt = ct_atc_pcm_interrupt;
 285        runtime->hw = ct_pcm_capture_hw;
 286        runtime->hw.rate_max = atc->rsr * atc->msr;
 287
 288        err = snd_pcm_hw_constraint_integer(runtime,
 289                                            SNDRV_PCM_HW_PARAM_PERIODS);
 290        if (err < 0)
 291                goto free_pcm;
 292
 293        err = snd_pcm_hw_constraint_minmax(runtime,
 294                                           SNDRV_PCM_HW_PARAM_BUFFER_BYTES,
 295                                           1024, UINT_MAX);
 296        if (err < 0)
 297                goto free_pcm;
 298
 299        apcm->timer = ct_timer_instance_new(atc->timer, apcm);
 300        if (!apcm->timer) {
 301                err = -ENOMEM;
 302                goto free_pcm;
 303        }
 304        runtime->private_data = apcm;
 305        runtime->private_free = ct_atc_pcm_free_substream;
 306
 307        return 0;
 308
 309free_pcm:
 310        kfree(apcm);
 311        return err;
 312}
 313
 314static int ct_pcm_capture_close(struct snd_pcm_substream *substream)
 315{
 316        /* The ct_atc_pcm object will be freed by runtime->private_free */
 317        /* TODO: Notify mixer inactive. */
 318        return 0;
 319}
 320
 321static int ct_pcm_capture_prepare(struct snd_pcm_substream *substream)
 322{
 323        int err;
 324        struct ct_atc *atc = snd_pcm_substream_chip(substream);
 325        struct snd_pcm_runtime *runtime = substream->runtime;
 326        struct ct_atc_pcm *apcm = runtime->private_data;
 327
 328        err = atc->pcm_capture_prepare(atc, apcm);
 329        if (err < 0) {
 330                dev_err(atc->card->dev,
 331                        "Preparing pcm capture failed!!!\n");
 332                return err;
 333        }
 334
 335        return 0;
 336}
 337
 338static int
 339ct_pcm_capture_trigger(struct snd_pcm_substream *substream, int cmd)
 340{
 341        struct ct_atc *atc = snd_pcm_substream_chip(substream);
 342        struct snd_pcm_runtime *runtime = substream->runtime;
 343        struct ct_atc_pcm *apcm = runtime->private_data;
 344
 345        switch (cmd) {
 346        case SNDRV_PCM_TRIGGER_START:
 347                atc->pcm_capture_start(atc, apcm);
 348                break;
 349        case SNDRV_PCM_TRIGGER_STOP:
 350                atc->pcm_capture_stop(atc, apcm);
 351                break;
 352        default:
 353                atc->pcm_capture_stop(atc, apcm);
 354                break;
 355        }
 356
 357        return 0;
 358}
 359
 360static snd_pcm_uframes_t
 361ct_pcm_capture_pointer(struct snd_pcm_substream *substream)
 362{
 363        unsigned long position;
 364        struct ct_atc *atc = snd_pcm_substream_chip(substream);
 365        struct snd_pcm_runtime *runtime = substream->runtime;
 366        struct ct_atc_pcm *apcm = runtime->private_data;
 367
 368        /* Read out playback position */
 369        position = atc->pcm_capture_position(atc, apcm);
 370        position = bytes_to_frames(runtime, position);
 371        if (position >= runtime->buffer_size)
 372                position = 0;
 373        return position;
 374}
 375
 376/* PCM operators for playback */
 377static const struct snd_pcm_ops ct_pcm_playback_ops = {
 378        .open           = ct_pcm_playback_open,
 379        .close          = ct_pcm_playback_close,
 380        .ioctl          = snd_pcm_lib_ioctl,
 381        .hw_params      = ct_pcm_hw_params,
 382        .hw_free        = ct_pcm_hw_free,
 383        .prepare        = ct_pcm_playback_prepare,
 384        .trigger        = ct_pcm_playback_trigger,
 385        .pointer        = ct_pcm_playback_pointer,
 386        .page           = snd_pcm_sgbuf_ops_page,
 387};
 388
 389/* PCM operators for capture */
 390static const struct snd_pcm_ops ct_pcm_capture_ops = {
 391        .open           = ct_pcm_capture_open,
 392        .close          = ct_pcm_capture_close,
 393        .ioctl          = snd_pcm_lib_ioctl,
 394        .hw_params      = ct_pcm_hw_params,
 395        .hw_free        = ct_pcm_hw_free,
 396        .prepare        = ct_pcm_capture_prepare,
 397        .trigger        = ct_pcm_capture_trigger,
 398        .pointer        = ct_pcm_capture_pointer,
 399        .page           = snd_pcm_sgbuf_ops_page,
 400};
 401
 402static const struct snd_pcm_chmap_elem surround_map[] = {
 403        { .channels = 1,
 404          .map = { SNDRV_CHMAP_MONO } },
 405        { .channels = 2,
 406          .map = { SNDRV_CHMAP_RL, SNDRV_CHMAP_RR } },
 407        { }
 408};
 409
 410static const struct snd_pcm_chmap_elem clfe_map[] = {
 411        { .channels = 1,
 412          .map = { SNDRV_CHMAP_MONO } },
 413        { .channels = 2,
 414          .map = { SNDRV_CHMAP_FC, SNDRV_CHMAP_LFE } },
 415        { }
 416};
 417
 418static const struct snd_pcm_chmap_elem side_map[] = {
 419        { .channels = 1,
 420          .map = { SNDRV_CHMAP_MONO } },
 421        { .channels = 2,
 422          .map = { SNDRV_CHMAP_SL, SNDRV_CHMAP_SR } },
 423        { }
 424};
 425
 426/* Create ALSA pcm device */
 427int ct_alsa_pcm_create(struct ct_atc *atc,
 428                       enum CTALSADEVS device,
 429                       const char *device_name)
 430{
 431        struct snd_pcm *pcm;
 432        const struct snd_pcm_chmap_elem *map;
 433        int chs;
 434        int err;
 435        int playback_count, capture_count;
 436
 437        playback_count = (IEC958 == device) ? 1 : 256;
 438        capture_count = (FRONT == device) ? 1 : 0;
 439        err = snd_pcm_new(atc->card, "ctxfi", device,
 440                          playback_count, capture_count, &pcm);
 441        if (err < 0) {
 442                dev_err(atc->card->dev, "snd_pcm_new failed!! Err=%d\n",
 443                        err);
 444                return err;
 445        }
 446
 447        pcm->private_data = atc;
 448        pcm->info_flags = 0;
 449        pcm->dev_subclass = SNDRV_PCM_SUBCLASS_GENERIC_MIX;
 450        strlcpy(pcm->name, device_name, sizeof(pcm->name));
 451
 452        snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &ct_pcm_playback_ops);
 453
 454        if (FRONT == device)
 455                snd_pcm_set_ops(pcm,
 456                                SNDRV_PCM_STREAM_CAPTURE, &ct_pcm_capture_ops);
 457
 458        snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV_SG,
 459                        snd_dma_pci_data(atc->pci), 128*1024, 128*1024);
 460
 461        chs = 2;
 462        switch (device) {
 463        case FRONT:
 464                chs = 8;
 465                map = snd_pcm_std_chmaps;
 466                break;
 467        case SURROUND:
 468                map = surround_map;
 469                break;
 470        case CLFE:
 471                map = clfe_map;
 472                break;
 473        case SIDE:
 474                map = side_map;
 475                break;
 476        default:
 477                map = snd_pcm_std_chmaps;
 478                break;
 479        }
 480        err = snd_pcm_add_chmap_ctls(pcm, SNDRV_PCM_STREAM_PLAYBACK, map, chs,
 481                                     0, NULL);
 482        if (err < 0)
 483                return err;
 484
 485#ifdef CONFIG_PM_SLEEP
 486        atc->pcms[device] = pcm;
 487#endif
 488
 489        return 0;
 490}
 491