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