root/sound/pci/ctxfi/ctpcm.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. ct_atc_pcm_interrupt
  2. ct_atc_pcm_free_substream
  3. ct_pcm_playback_open
  4. ct_pcm_playback_close
  5. ct_pcm_hw_params
  6. ct_pcm_hw_free
  7. ct_pcm_playback_prepare
  8. ct_pcm_playback_trigger
  9. ct_pcm_playback_pointer
  10. ct_pcm_capture_open
  11. ct_pcm_capture_close
  12. ct_pcm_capture_prepare
  13. ct_pcm_capture_trigger
  14. ct_pcm_capture_pointer
  15. ct_alsa_pcm_create

   1 // SPDX-License-Identifier: GPL-2.0-only
   2 /**
   3  * Copyright (C) 2008, Creative Technology Ltd. All Rights Reserved.
   4  *
   5  * @File        ctpcm.c
   6  *
   7  * @Brief
   8  * This file contains the definition of the pcm device functions.
   9  *
  10  * @Author      Liu Chun
  11  * @Date        Apr 2 2008
  12  */
  13 
  14 #include "ctpcm.h"
  15 #include "cttimer.h"
  16 #include <linux/slab.h>
  17 #include <sound/pcm.h>
  18 
  19 /* Hardware descriptions for playback */
  20 static const struct snd_pcm_hardware ct_pcm_playback_hw = {
  21         .info                   = (SNDRV_PCM_INFO_MMAP |
  22                                    SNDRV_PCM_INFO_INTERLEAVED |
  23                                    SNDRV_PCM_INFO_BLOCK_TRANSFER |
  24                                    SNDRV_PCM_INFO_MMAP_VALID |
  25                                    SNDRV_PCM_INFO_PAUSE),
  26         .formats                = (SNDRV_PCM_FMTBIT_U8 |
  27                                    SNDRV_PCM_FMTBIT_S16_LE |
  28                                    SNDRV_PCM_FMTBIT_S24_3LE |
  29                                    SNDRV_PCM_FMTBIT_S32_LE |
  30                                    SNDRV_PCM_FMTBIT_FLOAT_LE),
  31         .rates                  = (SNDRV_PCM_RATE_CONTINUOUS |
  32                                    SNDRV_PCM_RATE_8000_192000),
  33         .rate_min               = 8000,
  34         .rate_max               = 192000,
  35         .channels_min           = 1,
  36         .channels_max           = 2,
  37         .buffer_bytes_max       = (128*1024),
  38         .period_bytes_min       = (64),
  39         .period_bytes_max       = (128*1024),
  40         .periods_min            = 2,
  41         .periods_max            = 1024,
  42         .fifo_size              = 0,
  43 };
  44 
  45 static const struct snd_pcm_hardware ct_spdif_passthru_playback_hw = {
  46         .info                   = (SNDRV_PCM_INFO_MMAP |
  47                                    SNDRV_PCM_INFO_INTERLEAVED |
  48                                    SNDRV_PCM_INFO_BLOCK_TRANSFER |
  49                                    SNDRV_PCM_INFO_MMAP_VALID |
  50                                    SNDRV_PCM_INFO_PAUSE),
  51         .formats                = SNDRV_PCM_FMTBIT_S16_LE,
  52         .rates                  = (SNDRV_PCM_RATE_48000 |
  53                                    SNDRV_PCM_RATE_44100 |
  54                                    SNDRV_PCM_RATE_32000),
  55         .rate_min               = 32000,
  56         .rate_max               = 48000,
  57         .channels_min           = 2,
  58         .channels_max           = 2,
  59         .buffer_bytes_max       = (128*1024),
  60         .period_bytes_min       = (64),
  61         .period_bytes_max       = (128*1024),
  62         .periods_min            = 2,
  63         .periods_max            = 1024,
  64         .fifo_size              = 0,
  65 };
  66 
  67 /* Hardware descriptions for capture */
  68 static const struct snd_pcm_hardware ct_pcm_capture_hw = {
  69         .info                   = (SNDRV_PCM_INFO_MMAP |
  70                                    SNDRV_PCM_INFO_INTERLEAVED |
  71                                    SNDRV_PCM_INFO_BLOCK_TRANSFER |
  72                                    SNDRV_PCM_INFO_PAUSE |
  73                                    SNDRV_PCM_INFO_MMAP_VALID),
  74         .formats                = (SNDRV_PCM_FMTBIT_U8 |
  75                                    SNDRV_PCM_FMTBIT_S16_LE |
  76                                    SNDRV_PCM_FMTBIT_S24_3LE |
  77                                    SNDRV_PCM_FMTBIT_S32_LE |
  78                                    SNDRV_PCM_FMTBIT_FLOAT_LE),
  79         .rates                  = (SNDRV_PCM_RATE_CONTINUOUS |
  80                                    SNDRV_PCM_RATE_8000_96000),
  81         .rate_min               = 8000,
  82         .rate_max               = 96000,
  83         .channels_min           = 1,
  84         .channels_max           = 2,
  85         .buffer_bytes_max       = (128*1024),
  86         .period_bytes_min       = (384),
  87         .period_bytes_max       = (64*1024),
  88         .periods_min            = 2,
  89         .periods_max            = 1024,
  90         .fifo_size              = 0,
  91 };
  92 
  93 static void ct_atc_pcm_interrupt(struct ct_atc_pcm *atc_pcm)
  94 {
  95         struct ct_atc_pcm *apcm = atc_pcm;
  96 
  97         if (!apcm->substream)
  98                 return;
  99 
 100         snd_pcm_period_elapsed(apcm->substream);
 101 }
 102 
 103 static void ct_atc_pcm_free_substream(struct snd_pcm_runtime *runtime)
 104 {
 105         struct ct_atc_pcm *apcm = runtime->private_data;
 106         struct ct_atc *atc = snd_pcm_substream_chip(apcm->substream);
 107 
 108         atc->pcm_release_resources(atc, apcm);
 109         ct_timer_instance_free(apcm->timer);
 110         kfree(apcm);
 111         runtime->private_data = NULL;
 112 }
 113 
 114 /* pcm playback operations */
 115 static int ct_pcm_playback_open(struct snd_pcm_substream *substream)
 116 {
 117         struct ct_atc *atc = snd_pcm_substream_chip(substream);
 118         struct snd_pcm_runtime *runtime = substream->runtime;
 119         struct ct_atc_pcm *apcm;
 120         int err;
 121 
 122         apcm = kzalloc(sizeof(*apcm), GFP_KERNEL);
 123         if (!apcm)
 124                 return -ENOMEM;
 125 
 126         apcm->substream = substream;
 127         apcm->interrupt = ct_atc_pcm_interrupt;
 128         if (IEC958 == substream->pcm->device) {
 129                 runtime->hw = ct_spdif_passthru_playback_hw;
 130                 atc->spdif_out_passthru(atc, 1);
 131         } else {
 132                 runtime->hw = ct_pcm_playback_hw;
 133                 if (FRONT == substream->pcm->device)
 134                         runtime->hw.channels_max = 8;
 135         }
 136 
 137         err = snd_pcm_hw_constraint_integer(runtime,
 138                                             SNDRV_PCM_HW_PARAM_PERIODS);
 139         if (err < 0)
 140                 goto free_pcm;
 141 
 142         err = snd_pcm_hw_constraint_minmax(runtime,
 143                                            SNDRV_PCM_HW_PARAM_BUFFER_BYTES,
 144                                            1024, UINT_MAX);
 145         if (err < 0)
 146                 goto free_pcm;
 147 
 148         apcm->timer = ct_timer_instance_new(atc->timer, apcm);
 149         if (!apcm->timer) {
 150                 err = -ENOMEM;
 151                 goto free_pcm;
 152         }
 153         runtime->private_data = apcm;
 154         runtime->private_free = ct_atc_pcm_free_substream;
 155 
 156         return 0;
 157 
 158 free_pcm:
 159         kfree(apcm);
 160         return err;
 161 }
 162 
 163 static int ct_pcm_playback_close(struct snd_pcm_substream *substream)
 164 {
 165         struct ct_atc *atc = snd_pcm_substream_chip(substream);
 166 
 167         /* TODO: Notify mixer inactive. */
 168         if (IEC958 == substream->pcm->device)
 169                 atc->spdif_out_passthru(atc, 0);
 170 
 171         /* The ct_atc_pcm object will be freed by runtime->private_free */
 172 
 173         return 0;
 174 }
 175 
 176 static int ct_pcm_hw_params(struct snd_pcm_substream *substream,
 177                                      struct snd_pcm_hw_params *hw_params)
 178 {
 179         struct ct_atc *atc = snd_pcm_substream_chip(substream);
 180         struct ct_atc_pcm *apcm = substream->runtime->private_data;
 181         int err;
 182 
 183         err = snd_pcm_lib_malloc_pages(substream,
 184                                         params_buffer_bytes(hw_params));
 185         if (err < 0)
 186                 return err;
 187         /* clear previous resources */
 188         atc->pcm_release_resources(atc, apcm);
 189         return err;
 190 }
 191 
 192 static int ct_pcm_hw_free(struct snd_pcm_substream *substream)
 193 {
 194         struct ct_atc *atc = snd_pcm_substream_chip(substream);
 195         struct ct_atc_pcm *apcm = substream->runtime->private_data;
 196 
 197         /* clear previous resources */
 198         atc->pcm_release_resources(atc, apcm);
 199         /* Free snd-allocated pages */
 200         return snd_pcm_lib_free_pages(substream);
 201 }
 202 
 203 
 204 static int ct_pcm_playback_prepare(struct snd_pcm_substream *substream)
 205 {
 206         int err;
 207         struct ct_atc *atc = snd_pcm_substream_chip(substream);
 208         struct snd_pcm_runtime *runtime = substream->runtime;
 209         struct ct_atc_pcm *apcm = runtime->private_data;
 210 
 211         if (IEC958 == substream->pcm->device)
 212                 err = atc->spdif_passthru_playback_prepare(atc, apcm);
 213         else
 214                 err = atc->pcm_playback_prepare(atc, apcm);
 215 
 216         if (err < 0) {
 217                 dev_err(atc->card->dev,
 218                         "Preparing pcm playback failed!!!\n");
 219                 return err;
 220         }
 221 
 222         return 0;
 223 }
 224 
 225 static int
 226 ct_pcm_playback_trigger(struct snd_pcm_substream *substream, int cmd)
 227 {
 228         struct ct_atc *atc = snd_pcm_substream_chip(substream);
 229         struct snd_pcm_runtime *runtime = substream->runtime;
 230         struct ct_atc_pcm *apcm = runtime->private_data;
 231 
 232         switch (cmd) {
 233         case SNDRV_PCM_TRIGGER_START:
 234         case SNDRV_PCM_TRIGGER_RESUME:
 235         case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
 236                 atc->pcm_playback_start(atc, apcm);
 237                 break;
 238         case SNDRV_PCM_TRIGGER_STOP:
 239         case SNDRV_PCM_TRIGGER_SUSPEND:
 240         case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
 241                 atc->pcm_playback_stop(atc, apcm);
 242                 break;
 243         default:
 244                 break;
 245         }
 246 
 247         return 0;
 248 }
 249 
 250 static snd_pcm_uframes_t
 251 ct_pcm_playback_pointer(struct snd_pcm_substream *substream)
 252 {
 253         unsigned long position;
 254         struct ct_atc *atc = snd_pcm_substream_chip(substream);
 255         struct snd_pcm_runtime *runtime = substream->runtime;
 256         struct ct_atc_pcm *apcm = runtime->private_data;
 257 
 258         /* Read out playback position */
 259         position = atc->pcm_playback_position(atc, apcm);
 260         position = bytes_to_frames(runtime, position);
 261         if (position >= runtime->buffer_size)
 262                 position = 0;
 263         return position;
 264 }
 265 
 266 /* pcm capture operations */
 267 static int ct_pcm_capture_open(struct snd_pcm_substream *substream)
 268 {
 269         struct ct_atc *atc = snd_pcm_substream_chip(substream);
 270         struct snd_pcm_runtime *runtime = substream->runtime;
 271         struct ct_atc_pcm *apcm;
 272         int err;
 273 
 274         apcm = kzalloc(sizeof(*apcm), GFP_KERNEL);
 275         if (!apcm)
 276                 return -ENOMEM;
 277 
 278         apcm->started = 0;
 279         apcm->substream = substream;
 280         apcm->interrupt = ct_atc_pcm_interrupt;
 281         runtime->hw = ct_pcm_capture_hw;
 282         runtime->hw.rate_max = atc->rsr * atc->msr;
 283 
 284         err = snd_pcm_hw_constraint_integer(runtime,
 285                                             SNDRV_PCM_HW_PARAM_PERIODS);
 286         if (err < 0)
 287                 goto free_pcm;
 288 
 289         err = snd_pcm_hw_constraint_minmax(runtime,
 290                                            SNDRV_PCM_HW_PARAM_BUFFER_BYTES,
 291                                            1024, UINT_MAX);
 292         if (err < 0)
 293                 goto free_pcm;
 294 
 295         apcm->timer = ct_timer_instance_new(atc->timer, apcm);
 296         if (!apcm->timer) {
 297                 err = -ENOMEM;
 298                 goto free_pcm;
 299         }
 300         runtime->private_data = apcm;
 301         runtime->private_free = ct_atc_pcm_free_substream;
 302 
 303         return 0;
 304 
 305 free_pcm:
 306         kfree(apcm);
 307         return err;
 308 }
 309 
 310 static int ct_pcm_capture_close(struct snd_pcm_substream *substream)
 311 {
 312         /* The ct_atc_pcm object will be freed by runtime->private_free */
 313         /* TODO: Notify mixer inactive. */
 314         return 0;
 315 }
 316 
 317 static int ct_pcm_capture_prepare(struct snd_pcm_substream *substream)
 318 {
 319         int err;
 320         struct ct_atc *atc = snd_pcm_substream_chip(substream);
 321         struct snd_pcm_runtime *runtime = substream->runtime;
 322         struct ct_atc_pcm *apcm = runtime->private_data;
 323 
 324         err = atc->pcm_capture_prepare(atc, apcm);
 325         if (err < 0) {
 326                 dev_err(atc->card->dev,
 327                         "Preparing pcm capture failed!!!\n");
 328                 return err;
 329         }
 330 
 331         return 0;
 332 }
 333 
 334 static int
 335 ct_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 
 356 static snd_pcm_uframes_t
 357 ct_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 */
 373 static const 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 */
 386 static const 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 static const struct snd_pcm_chmap_elem surround_map[] = {
 399         { .channels = 1,
 400           .map = { SNDRV_CHMAP_MONO } },
 401         { .channels = 2,
 402           .map = { SNDRV_CHMAP_RL, SNDRV_CHMAP_RR } },
 403         { }
 404 };
 405 
 406 static const struct snd_pcm_chmap_elem clfe_map[] = {
 407         { .channels = 1,
 408           .map = { SNDRV_CHMAP_MONO } },
 409         { .channels = 2,
 410           .map = { SNDRV_CHMAP_FC, SNDRV_CHMAP_LFE } },
 411         { }
 412 };
 413 
 414 static const struct snd_pcm_chmap_elem side_map[] = {
 415         { .channels = 1,
 416           .map = { SNDRV_CHMAP_MONO } },
 417         { .channels = 2,
 418           .map = { SNDRV_CHMAP_SL, SNDRV_CHMAP_SR } },
 419         { }
 420 };
 421 
 422 /* Create ALSA pcm device */
 423 int ct_alsa_pcm_create(struct ct_atc *atc,
 424                        enum CTALSADEVS device,
 425                        const char *device_name)
 426 {
 427         struct snd_pcm *pcm;
 428         const struct snd_pcm_chmap_elem *map;
 429         int chs;
 430         int err;
 431         int playback_count, capture_count;
 432 
 433         playback_count = (IEC958 == device) ? 1 : 256;
 434         capture_count = (FRONT == device) ? 1 : 0;
 435         err = snd_pcm_new(atc->card, "ctxfi", device,
 436                           playback_count, capture_count, &pcm);
 437         if (err < 0) {
 438                 dev_err(atc->card->dev, "snd_pcm_new failed!! Err=%d\n",
 439                         err);
 440                 return err;
 441         }
 442 
 443         pcm->private_data = atc;
 444         pcm->info_flags = 0;
 445         pcm->dev_subclass = SNDRV_PCM_SUBCLASS_GENERIC_MIX;
 446         strlcpy(pcm->name, device_name, sizeof(pcm->name));
 447 
 448         snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &ct_pcm_playback_ops);
 449 
 450         if (FRONT == device)
 451                 snd_pcm_set_ops(pcm,
 452                                 SNDRV_PCM_STREAM_CAPTURE, &ct_pcm_capture_ops);
 453 
 454         snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV_SG,
 455                         snd_dma_pci_data(atc->pci), 128*1024, 128*1024);
 456 
 457         chs = 2;
 458         switch (device) {
 459         case FRONT:
 460                 chs = 8;
 461                 map = snd_pcm_std_chmaps;
 462                 break;
 463         case SURROUND:
 464                 map = surround_map;
 465                 break;
 466         case CLFE:
 467                 map = clfe_map;
 468                 break;
 469         case SIDE:
 470                 map = side_map;
 471                 break;
 472         default:
 473                 map = snd_pcm_std_chmaps;
 474                 break;
 475         }
 476         err = snd_pcm_add_chmap_ctls(pcm, SNDRV_PCM_STREAM_PLAYBACK, map, chs,
 477                                      0, NULL);
 478         if (err < 0)
 479                 return err;
 480 
 481 #ifdef CONFIG_PM_SLEEP
 482         atc->pcms[device] = pcm;
 483 #endif
 484 
 485         return 0;
 486 }

/* [<][>][^][v][top][bottom][index][help] */