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