cregit-Linux how code gets into the kernel

Release 4.11 sound/pci/ctxfi/ctpcm.c

Directory: sound/pci/ctxfi
/**
 * Copyright (C) 2008, Creative Technology Ltd. All Rights Reserved.
 *
 * This source file is released under GPL v2 license (no other versions).
 * See the COPYING file included in the main directory of this source
 * distribution for the license terms and conditions.
 *
 * @File        ctpcm.c
 *
 * @Brief
 * This file contains the definition of the pcm device functions.
 *
 * @Author      Liu Chun
 * @Date        Apr 2 2008
 *
 */

#include "ctpcm.h"
#include "cttimer.h"
#include <linux/slab.h>
#include <sound/pcm.h>

/* Hardware descriptions for playback */

static struct snd_pcm_hardware ct_pcm_playback_hw = {
	.info			= (SNDRV_PCM_INFO_MMAP |
				   SNDRV_PCM_INFO_INTERLEAVED |
				   SNDRV_PCM_INFO_BLOCK_TRANSFER |
				   SNDRV_PCM_INFO_MMAP_VALID |
				   SNDRV_PCM_INFO_PAUSE),
	.formats		= (SNDRV_PCM_FMTBIT_U8 |
				   SNDRV_PCM_FMTBIT_S16_LE |
				   SNDRV_PCM_FMTBIT_S24_3LE |
				   SNDRV_PCM_FMTBIT_S32_LE |
				   SNDRV_PCM_FMTBIT_FLOAT_LE),
	.rates			= (SNDRV_PCM_RATE_CONTINUOUS |
				   SNDRV_PCM_RATE_8000_192000),
	.rate_min		= 8000,
	.rate_max		= 192000,
	.channels_min		= 1,
	.channels_max		= 2,
	.buffer_bytes_max	= (128*1024),
	.period_bytes_min	= (64),
	.period_bytes_max	= (128*1024),
	.periods_min		= 2,
	.periods_max		= 1024,
	.fifo_size		= 0,
};


static struct snd_pcm_hardware ct_spdif_passthru_playback_hw = {
	.info			= (SNDRV_PCM_INFO_MMAP |
				   SNDRV_PCM_INFO_INTERLEAVED |
				   SNDRV_PCM_INFO_BLOCK_TRANSFER |
				   SNDRV_PCM_INFO_MMAP_VALID |
				   SNDRV_PCM_INFO_PAUSE),
	.formats		= SNDRV_PCM_FMTBIT_S16_LE,
	.rates			= (SNDRV_PCM_RATE_48000 |
				   SNDRV_PCM_RATE_44100 |
				   SNDRV_PCM_RATE_32000),
	.rate_min		= 32000,
	.rate_max		= 48000,
	.channels_min		= 2,
	.channels_max		= 2,
	.buffer_bytes_max	= (128*1024),
	.period_bytes_min	= (64),
	.period_bytes_max	= (128*1024),
	.periods_min		= 2,
	.periods_max		= 1024,
	.fifo_size		= 0,
};

/* Hardware descriptions for capture */

static struct snd_pcm_hardware ct_pcm_capture_hw = {
	.info			= (SNDRV_PCM_INFO_MMAP |
				   SNDRV_PCM_INFO_INTERLEAVED |
				   SNDRV_PCM_INFO_BLOCK_TRANSFER |
				   SNDRV_PCM_INFO_PAUSE |
				   SNDRV_PCM_INFO_MMAP_VALID),
	.formats		= (SNDRV_PCM_FMTBIT_U8 |
				   SNDRV_PCM_FMTBIT_S16_LE |
				   SNDRV_PCM_FMTBIT_S24_3LE |
				   SNDRV_PCM_FMTBIT_S32_LE |
				   SNDRV_PCM_FMTBIT_FLOAT_LE),
	.rates			= (SNDRV_PCM_RATE_CONTINUOUS |
				   SNDRV_PCM_RATE_8000_96000),
	.rate_min		= 8000,
	.rate_max		= 96000,
	.channels_min		= 1,
	.channels_max		= 2,
	.buffer_bytes_max	= (128*1024),
	.period_bytes_min	= (384),
	.period_bytes_max	= (64*1024),
	.periods_min		= 2,
	.periods_max		= 1024,
	.fifo_size		= 0,
};


static void ct_atc_pcm_interrupt(struct ct_atc_pcm *atc_pcm) { struct ct_atc_pcm *apcm = atc_pcm; if (!apcm->substream) return; snd_pcm_period_elapsed(apcm->substream); }

Contributors

PersonTokensPropCommitsCommitProp
Wai Yew CHAY3296.97%150.00%
Takashi Iwai13.03%150.00%
Total33100.00%2100.00%


static void ct_atc_pcm_free_substream(struct snd_pcm_runtime *runtime) { struct ct_atc_pcm *apcm = runtime->private_data; struct ct_atc *atc = snd_pcm_substream_chip(apcm->substream); atc->pcm_release_resources(atc, apcm); ct_timer_instance_free(apcm->timer); kfree(apcm); runtime->private_data = NULL; }

Contributors

PersonTokensPropCommitsCommitProp
Wai Yew CHAY5288.14%150.00%
Takashi Iwai711.86%150.00%
Total59100.00%2100.00%

/* pcm playback operations */
static int ct_pcm_playback_open(struct snd_pcm_substream *substream) { struct ct_atc *atc = snd_pcm_substream_chip(substream); struct snd_pcm_runtime *runtime = substream->runtime; struct ct_atc_pcm *apcm; int err; apcm = kzalloc(sizeof(*apcm), GFP_KERNEL); if (!apcm) return -ENOMEM; apcm->substream = substream; apcm->interrupt = ct_atc_pcm_interrupt; if (IEC958 == substream->pcm->device) { runtime->hw = ct_spdif_passthru_playback_hw; atc->spdif_out_passthru(atc, 1); } else { runtime->hw = ct_pcm_playback_hw; if (FRONT == substream->pcm->device) runtime->hw.channels_max = 8; } err = snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS); if (err < 0) { kfree(apcm); return err; } err = snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_BUFFER_BYTES, 1024, UINT_MAX); if (err < 0) { kfree(apcm); return err; } apcm->timer = ct_timer_instance_new(atc->timer, apcm); if (!apcm->timer) { kfree(apcm); return -ENOMEM; } runtime->private_data = apcm; runtime->private_free = ct_atc_pcm_free_substream; return 0; }

Contributors

PersonTokensPropCommitsCommitProp
Wai Yew CHAY18280.53%125.00%
Takashi Iwai2511.06%250.00%
Julia Lawall198.41%125.00%
Total226100.00%4100.00%


static int ct_pcm_playback_close(struct snd_pcm_substream *substream) { struct ct_atc *atc = snd_pcm_substream_chip(substream); /* TODO: Notify mixer inactive. */ if (IEC958 == substream->pcm->device) atc->spdif_out_passthru(atc, 0); /* The ct_atc_pcm object will be freed by runtime->private_free */ return 0; }

Contributors

PersonTokensPropCommitsCommitProp
Wai Yew CHAY45100.00%1100.00%
Total45100.00%1100.00%


static int ct_pcm_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *hw_params) { struct ct_atc *atc = snd_pcm_substream_chip(substream); struct ct_atc_pcm *apcm = substream->runtime->private_data; int err; err = snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params)); if (err < 0) return err; /* clear previous resources */ atc->pcm_release_resources(atc, apcm); return err; }

Contributors

PersonTokensPropCommitsCommitProp
Takashi Iwai4864.86%150.00%
Wai Yew CHAY2635.14%150.00%
Total74100.00%2100.00%


static int ct_pcm_hw_free(struct snd_pcm_substream *substream) { struct ct_atc *atc = snd_pcm_substream_chip(substream); struct ct_atc_pcm *apcm = substream->runtime->private_data; /* clear previous resources */ atc->pcm_release_resources(atc, apcm); /* Free snd-allocated pages */ return snd_pcm_lib_free_pages(substream); }

Contributors

PersonTokensPropCommitsCommitProp
Takashi Iwai3163.27%150.00%
Wai Yew CHAY1836.73%150.00%
Total49100.00%2100.00%


static int ct_pcm_playback_prepare(struct snd_pcm_substream *substream) { int err; struct ct_atc *atc = snd_pcm_substream_chip(substream); struct snd_pcm_runtime *runtime = substream->runtime; struct ct_atc_pcm *apcm = runtime->private_data; if (IEC958 == substream->pcm->device) err = atc->spdif_passthru_playback_prepare(atc, apcm); else err = atc->pcm_playback_prepare(atc, apcm); if (err < 0) { dev_err(atc->card->dev, "Preparing pcm playback failed!!!\n"); return err; } return 0; }

Contributors

PersonTokensPropCommitsCommitProp
Wai Yew CHAY9292.00%150.00%
Sudip Mukherjee88.00%150.00%
Total100100.00%2100.00%


static int ct_pcm_playback_trigger(struct snd_pcm_substream *substream, int cmd) { struct ct_atc *atc = snd_pcm_substream_chip(substream); struct snd_pcm_runtime *runtime = substream->runtime; struct ct_atc_pcm *apcm = runtime->private_data; switch (cmd) { case SNDRV_PCM_TRIGGER_START: case SNDRV_PCM_TRIGGER_RESUME: case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: atc->pcm_playback_start(atc, apcm); break; case SNDRV_PCM_TRIGGER_STOP: case SNDRV_PCM_TRIGGER_SUSPEND: case SNDRV_PCM_TRIGGER_PAUSE_PUSH: atc->pcm_playback_stop(atc, apcm); break; default: break; } return 0; }

Contributors

PersonTokensPropCommitsCommitProp
Wai Yew CHAY91100.00%1100.00%
Total91100.00%1100.00%


static snd_pcm_uframes_t ct_pcm_playback_pointer(struct snd_pcm_substream *substream) { unsigned long position; struct ct_atc *atc = snd_pcm_substream_chip(substream); struct snd_pcm_runtime *runtime = substream->runtime; struct ct_atc_pcm *apcm = runtime->private_data; /* Read out playback position */ position = atc->pcm_playback_position(atc, apcm); position = bytes_to_frames(runtime, position); if (position >= runtime->buffer_size) position = 0; return position; }

Contributors

PersonTokensPropCommitsCommitProp
Wai Yew CHAY6784.81%150.00%
Takashi Iwai1215.19%150.00%
Total79100.00%2100.00%

/* pcm capture operations */
static int ct_pcm_capture_open(struct snd_pcm_substream *substream) { struct ct_atc *atc = snd_pcm_substream_chip(substream); struct snd_pcm_runtime *runtime = substream->runtime; struct ct_atc_pcm *apcm; int err; apcm = kzalloc(sizeof(*apcm), GFP_KERNEL); if (!apcm) return -ENOMEM; apcm->started = 0; apcm->substream = substream; apcm->interrupt = ct_atc_pcm_interrupt; runtime->hw = ct_pcm_capture_hw; runtime->hw.rate_max = atc->rsr * atc->msr; err = snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS); if (err < 0) { kfree(apcm); return err; } err = snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_BUFFER_BYTES, 1024, UINT_MAX); if (err < 0) { kfree(apcm); return err; } apcm->timer = ct_timer_instance_new(atc->timer, apcm); if (!apcm->timer) { kfree(apcm); return -ENOMEM; } runtime->private_data = apcm; runtime->private_free = ct_atc_pcm_free_substream; return 0; }

Contributors

PersonTokensPropCommitsCommitProp
Wai Yew CHAY15477.78%125.00%
Takashi Iwai2512.63%250.00%
Julia Lawall199.60%125.00%
Total198100.00%4100.00%


static int ct_pcm_capture_close(struct snd_pcm_substream *substream) { /* The ct_atc_pcm object will be freed by runtime->private_free */ /* TODO: Notify mixer inactive. */ return 0; }

Contributors

PersonTokensPropCommitsCommitProp
Wai Yew CHAY16100.00%1100.00%
Total16100.00%1100.00%


static int ct_pcm_capture_prepare(struct snd_pcm_substream *substream) { int err; struct ct_atc *atc = snd_pcm_substream_chip(substream); struct snd_pcm_runtime *runtime = substream->runtime; struct ct_atc_pcm *apcm = runtime->private_data; err = atc->pcm_capture_prepare(atc, apcm); if (err < 0) { dev_err(atc->card->dev, "Preparing pcm capture failed!!!\n"); return err; } return 0; }

Contributors

PersonTokensPropCommitsCommitProp
Wai Yew CHAY7089.74%150.00%
Sudip Mukherjee810.26%150.00%
Total78100.00%2100.00%


static int ct_pcm_capture_trigger(struct snd_pcm_substream *substream, int cmd) { struct ct_atc *atc = snd_pcm_substream_chip(substream); struct snd_pcm_runtime *runtime = substream->runtime; struct ct_atc_pcm *apcm = runtime->private_data; switch (cmd) { case SNDRV_PCM_TRIGGER_START: atc->pcm_capture_start(atc, apcm); break; case SNDRV_PCM_TRIGGER_STOP: atc->pcm_capture_stop(atc, apcm); break; default: atc->pcm_capture_stop(atc, apcm); break; } return 0; }

Contributors

PersonTokensPropCommitsCommitProp
Wai Yew CHAY88100.00%1100.00%
Total88100.00%1100.00%


static snd_pcm_uframes_t ct_pcm_capture_pointer(struct snd_pcm_substream *substream) { unsigned long position; struct ct_atc *atc = snd_pcm_substream_chip(substream); struct snd_pcm_runtime *runtime = substream->runtime; struct ct_atc_pcm *apcm = runtime->private_data; /* Read out playback position */ position = atc->pcm_capture_position(atc, apcm); position = bytes_to_frames(runtime, position); if (position >= runtime->buffer_size) position = 0; return position; }

Contributors

PersonTokensPropCommitsCommitProp
Wai Yew CHAY6784.81%150.00%
Takashi Iwai1215.19%150.00%
Total79100.00%2100.00%

/* PCM operators for playback */ static const struct snd_pcm_ops ct_pcm_playback_ops = { .open = ct_pcm_playback_open, .close = ct_pcm_playback_close, .ioctl = snd_pcm_lib_ioctl, .hw_params = ct_pcm_hw_params, .hw_free = ct_pcm_hw_free, .prepare = ct_pcm_playback_prepare, .trigger = ct_pcm_playback_trigger, .pointer = ct_pcm_playback_pointer, .page = snd_pcm_sgbuf_ops_page, }; /* PCM operators for capture */ static const struct snd_pcm_ops ct_pcm_capture_ops = { .open = ct_pcm_capture_open, .close = ct_pcm_capture_close, .ioctl = snd_pcm_lib_ioctl, .hw_params = ct_pcm_hw_params, .hw_free = ct_pcm_hw_free, .prepare = ct_pcm_capture_prepare, .trigger = ct_pcm_capture_trigger, .pointer = ct_pcm_capture_pointer, .page = snd_pcm_sgbuf_ops_page, }; static const struct snd_pcm_chmap_elem surround_map[] = { { .channels = 1, .map = { SNDRV_CHMAP_MONO } }, { .channels = 2, .map = { SNDRV_CHMAP_RL, SNDRV_CHMAP_RR } }, { } }; static const struct snd_pcm_chmap_elem clfe_map[] = { { .channels = 1, .map = { SNDRV_CHMAP_MONO } }, { .channels = 2, .map = { SNDRV_CHMAP_FC, SNDRV_CHMAP_LFE } }, { } }; static const struct snd_pcm_chmap_elem side_map[] = { { .channels = 1, .map = { SNDRV_CHMAP_MONO } }, { .channels = 2, .map = { SNDRV_CHMAP_SL, SNDRV_CHMAP_SR } }, { } }; /* Create ALSA pcm device */
int ct_alsa_pcm_create(struct ct_atc *atc, enum CTALSADEVS device, const char *device_name) { struct snd_pcm *pcm; const struct snd_pcm_chmap_elem *map; int chs; int err; int playback_count, capture_count; playback_count = (IEC958 == device) ? 1 : 256; capture_count = (FRONT == device) ? 1 : 0; err = snd_pcm_new(atc->card, "ctxfi", device, playback_count, capture_count, &pcm); if (err < 0) { dev_err(atc->card->dev, "snd_pcm_new failed!! Err=%d\n", err); return err; } pcm->private_data = atc; pcm->info_flags = 0; pcm->dev_subclass = SNDRV_PCM_SUBCLASS_GENERIC_MIX; strlcpy(pcm->name, device_name, sizeof(pcm->name)); snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &ct_pcm_playback_ops); if (FRONT == device) snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &ct_pcm_capture_ops); snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV_SG, snd_dma_pci_data(atc->pci), 128*1024, 128*1024); chs = 2; switch (device) { case FRONT: chs = 8; map = snd_pcm_std_chmaps; break; case SURROUND: map = surround_map; break; case CLFE: map = clfe_map; break; case SIDE: map = side_map; break; default: map = snd_pcm_std_chmaps; break; } err = snd_pcm_add_chmap_ctls(pcm, SNDRV_PCM_STREAM_PLAYBACK, map, chs, 0, NULL); if (err < 0) return err; #ifdef CONFIG_PM_SLEEP atc->pcms[device] = pcm; #endif return 0; }

Contributors

PersonTokensPropCommitsCommitProp
Wai Yew CHAY17962.59%225.00%
Takashi Iwai9834.27%450.00%
Sudip Mukherjee82.80%112.50%
Maarten Lankhorst10.35%112.50%
Total286100.00%8100.00%


Overall Contributors

PersonTokensPropCommitsCommitProp
Wai Yew CHAY159177.23%211.11%
Takashi Iwai40119.47%1161.11%
Julia Lawall401.94%211.11%
Sudip Mukherjee241.17%15.56%
Tejun Heo30.15%15.56%
Maarten Lankhorst10.05%15.56%
Total2060100.00%18100.00%
Directory: sound/pci/ctxfi
Information contained on this website is for historical information purposes only and does not indicate or represent copyright ownership.
Created with cregit.