⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 cs4281.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
static snd_pcm_uframes_t snd_cs4281_pointer(struct snd_pcm_substream *substream){	struct snd_pcm_runtime *runtime = substream->runtime;	struct cs4281_dma *dma = runtime->private_data;	struct cs4281 *chip = snd_pcm_substream_chip(substream);	// printk("DCC = 0x%x, buffer_size = 0x%x, jiffies = %li\n", snd_cs4281_peekBA0(chip, dma->regDCC), runtime->buffer_size, jiffies);	return runtime->buffer_size -	       snd_cs4281_peekBA0(chip, dma->regDCC) - 1;}static struct snd_pcm_hardware snd_cs4281_playback ={	.info =			SNDRV_PCM_INFO_MMAP |				SNDRV_PCM_INFO_INTERLEAVED |				SNDRV_PCM_INFO_MMAP_VALID |				SNDRV_PCM_INFO_PAUSE |				SNDRV_PCM_INFO_RESUME,	.formats =		SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S8 |				SNDRV_PCM_FMTBIT_U16_LE | SNDRV_PCM_FMTBIT_S16_LE |				SNDRV_PCM_FMTBIT_U16_BE | SNDRV_PCM_FMTBIT_S16_BE |				SNDRV_PCM_FMTBIT_U32_LE | SNDRV_PCM_FMTBIT_S32_LE |				SNDRV_PCM_FMTBIT_U32_BE | SNDRV_PCM_FMTBIT_S32_BE,	.rates =		SNDRV_PCM_RATE_CONTINUOUS | SNDRV_PCM_RATE_8000_48000,	.rate_min =		4000,	.rate_max =		48000,	.channels_min =		1,	.channels_max =		2,	.buffer_bytes_max =	(512*1024),	.period_bytes_min =	64,	.period_bytes_max =	(512*1024),	.periods_min =		1,	.periods_max =		2,	.fifo_size =		CS4281_FIFO_SIZE,};static struct snd_pcm_hardware snd_cs4281_capture ={	.info =			SNDRV_PCM_INFO_MMAP |				SNDRV_PCM_INFO_INTERLEAVED |				SNDRV_PCM_INFO_MMAP_VALID |				SNDRV_PCM_INFO_PAUSE |				SNDRV_PCM_INFO_RESUME,	.formats =		SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S8 |				SNDRV_PCM_FMTBIT_U16_LE | SNDRV_PCM_FMTBIT_S16_LE |				SNDRV_PCM_FMTBIT_U16_BE | SNDRV_PCM_FMTBIT_S16_BE |				SNDRV_PCM_FMTBIT_U32_LE | SNDRV_PCM_FMTBIT_S32_LE |				SNDRV_PCM_FMTBIT_U32_BE | SNDRV_PCM_FMTBIT_S32_BE,	.rates =		SNDRV_PCM_RATE_CONTINUOUS | SNDRV_PCM_RATE_8000_48000,	.rate_min =		4000,	.rate_max =		48000,	.channels_min =		1,	.channels_max =		2,	.buffer_bytes_max =	(512*1024),	.period_bytes_min =	64,	.period_bytes_max =	(512*1024),	.periods_min =		1,	.periods_max =		2,	.fifo_size =		CS4281_FIFO_SIZE,};static int snd_cs4281_playback_open(struct snd_pcm_substream *substream){	struct cs4281 *chip = snd_pcm_substream_chip(substream);	struct snd_pcm_runtime *runtime = substream->runtime;	struct cs4281_dma *dma;	dma = &chip->dma[0];	dma->substream = substream;	dma->left_slot = 0;	dma->right_slot = 1;	runtime->private_data = dma;	runtime->hw = snd_cs4281_playback;	/* should be detected from the AC'97 layer, but it seems	   that although CS4297A rev B reports 18-bit ADC resolution,	   samples are 20-bit */	snd_pcm_hw_constraint_msbits(runtime, 0, 32, 20);	return 0;}static int snd_cs4281_capture_open(struct snd_pcm_substream *substream){	struct cs4281 *chip = snd_pcm_substream_chip(substream);	struct snd_pcm_runtime *runtime = substream->runtime;	struct cs4281_dma *dma;	dma = &chip->dma[1];	dma->substream = substream;	dma->left_slot = 10;	dma->right_slot = 11;	runtime->private_data = dma;	runtime->hw = snd_cs4281_capture;	/* should be detected from the AC'97 layer, but it seems	   that although CS4297A rev B reports 18-bit ADC resolution,	   samples are 20-bit */	snd_pcm_hw_constraint_msbits(runtime, 0, 32, 20);	return 0;}static int snd_cs4281_playback_close(struct snd_pcm_substream *substream){	struct cs4281_dma *dma = substream->runtime->private_data;	dma->substream = NULL;	return 0;}static int snd_cs4281_capture_close(struct snd_pcm_substream *substream){	struct cs4281_dma *dma = substream->runtime->private_data;	dma->substream = NULL;	return 0;}static struct snd_pcm_ops snd_cs4281_playback_ops = {	.open =		snd_cs4281_playback_open,	.close =	snd_cs4281_playback_close,	.ioctl =	snd_pcm_lib_ioctl,	.hw_params =	snd_cs4281_hw_params,	.hw_free =	snd_cs4281_hw_free,	.prepare =	snd_cs4281_playback_prepare,	.trigger =	snd_cs4281_trigger,	.pointer =	snd_cs4281_pointer,};static struct snd_pcm_ops snd_cs4281_capture_ops = {	.open =		snd_cs4281_capture_open,	.close =	snd_cs4281_capture_close,	.ioctl =	snd_pcm_lib_ioctl,	.hw_params =	snd_cs4281_hw_params,	.hw_free =	snd_cs4281_hw_free,	.prepare =	snd_cs4281_capture_prepare,	.trigger =	snd_cs4281_trigger,	.pointer =	snd_cs4281_pointer,};static int __devinit snd_cs4281_pcm(struct cs4281 * chip, int device,				    struct snd_pcm ** rpcm){	struct snd_pcm *pcm;	int err;	if (rpcm)		*rpcm = NULL;	err = snd_pcm_new(chip->card, "CS4281", device, 1, 1, &pcm);	if (err < 0)		return err;	snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_cs4281_playback_ops);	snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_cs4281_capture_ops);	pcm->private_data = chip;	pcm->info_flags = 0;	strcpy(pcm->name, "CS4281");	chip->pcm = pcm;	snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV,					      snd_dma_pci_data(chip->pci), 64*1024, 512*1024);	if (rpcm)		*rpcm = pcm;	return 0;}/* *  Mixer section */#define CS_VOL_MASK	0x1fstatic int snd_cs4281_info_volume(struct snd_kcontrol *kcontrol,				  struct snd_ctl_elem_info *uinfo){	uinfo->type              = SNDRV_CTL_ELEM_TYPE_INTEGER;	uinfo->count             = 2;	uinfo->value.integer.min = 0;	uinfo->value.integer.max = CS_VOL_MASK;	return 0;} static int snd_cs4281_get_volume(struct snd_kcontrol *kcontrol,				 struct snd_ctl_elem_value *ucontrol){	struct cs4281 *chip = snd_kcontrol_chip(kcontrol);	int regL = (kcontrol->private_value >> 16) & 0xffff;	int regR = kcontrol->private_value & 0xffff;	int volL, volR;	volL = CS_VOL_MASK - (snd_cs4281_peekBA0(chip, regL) & CS_VOL_MASK);	volR = CS_VOL_MASK - (snd_cs4281_peekBA0(chip, regR) & CS_VOL_MASK);	ucontrol->value.integer.value[0] = volL;	ucontrol->value.integer.value[1] = volR;	return 0;}static int snd_cs4281_put_volume(struct snd_kcontrol *kcontrol,				 struct snd_ctl_elem_value *ucontrol){	struct cs4281 *chip = snd_kcontrol_chip(kcontrol);	int change = 0;	int regL = (kcontrol->private_value >> 16) & 0xffff;	int regR = kcontrol->private_value & 0xffff;	int volL, volR;	volL = CS_VOL_MASK - (snd_cs4281_peekBA0(chip, regL) & CS_VOL_MASK);	volR = CS_VOL_MASK - (snd_cs4281_peekBA0(chip, regR) & CS_VOL_MASK);	if (ucontrol->value.integer.value[0] != volL) {		volL = CS_VOL_MASK - (ucontrol->value.integer.value[0] & CS_VOL_MASK);		snd_cs4281_pokeBA0(chip, regL, volL);		change = 1;	}	if (ucontrol->value.integer.value[1] != volR) {		volR = CS_VOL_MASK - (ucontrol->value.integer.value[1] & CS_VOL_MASK);		snd_cs4281_pokeBA0(chip, regR, volR);		change = 1;	}	return change;}static const DECLARE_TLV_DB_SCALE(db_scale_dsp, -4650, 150, 0);static struct snd_kcontrol_new snd_cs4281_fm_vol = {	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,	.name = "Synth Playback Volume",	.info = snd_cs4281_info_volume, 	.get = snd_cs4281_get_volume,	.put = snd_cs4281_put_volume, 	.private_value = ((BA0_FMLVC << 16) | BA0_FMRVC),	.tlv = { .p = db_scale_dsp },};static struct snd_kcontrol_new snd_cs4281_pcm_vol = {	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,	.name = "PCM Stream Playback Volume",	.info = snd_cs4281_info_volume, 	.get = snd_cs4281_get_volume,	.put = snd_cs4281_put_volume, 	.private_value = ((BA0_PPLVC << 16) | BA0_PPRVC),	.tlv = { .p = db_scale_dsp },};static void snd_cs4281_mixer_free_ac97_bus(struct snd_ac97_bus *bus){	struct cs4281 *chip = bus->private_data;	chip->ac97_bus = NULL;}static void snd_cs4281_mixer_free_ac97(struct snd_ac97 *ac97){	struct cs4281 *chip = ac97->private_data;	if (ac97->num)		chip->ac97_secondary = NULL;	else		chip->ac97 = NULL;}static int __devinit snd_cs4281_mixer(struct cs4281 * chip){	struct snd_card *card = chip->card;	struct snd_ac97_template ac97;	int err;	static struct snd_ac97_bus_ops ops = {		.write = snd_cs4281_ac97_write,		.read = snd_cs4281_ac97_read,	};	if ((err = snd_ac97_bus(card, 0, &ops, chip, &chip->ac97_bus)) < 0)		return err;	chip->ac97_bus->private_free = snd_cs4281_mixer_free_ac97_bus;	memset(&ac97, 0, sizeof(ac97));	ac97.private_data = chip;	ac97.private_free = snd_cs4281_mixer_free_ac97;	if ((err = snd_ac97_mixer(chip->ac97_bus, &ac97, &chip->ac97)) < 0)		return err;	if (chip->dual_codec) {		ac97.num = 1;		if ((err = snd_ac97_mixer(chip->ac97_bus, &ac97, &chip->ac97_secondary)) < 0)			return err;	}	if ((err = snd_ctl_add(card, snd_ctl_new1(&snd_cs4281_fm_vol, chip))) < 0)		return err;	if ((err = snd_ctl_add(card, snd_ctl_new1(&snd_cs4281_pcm_vol, chip))) < 0)		return err;	return 0;}/* * proc interface */static void snd_cs4281_proc_read(struct snd_info_entry *entry, 				  struct snd_info_buffer *buffer){	struct cs4281 *chip = entry->private_data;	snd_iprintf(buffer, "Cirrus Logic CS4281\n\n");	snd_iprintf(buffer, "Spurious half IRQs   : %u\n", chip->spurious_dhtc_irq);	snd_iprintf(buffer, "Spurious end IRQs    : %u\n", chip->spurious_dtc_irq);}static long snd_cs4281_BA0_read(struct snd_info_entry *entry,				void *file_private_data,				struct file *file, char __user *buf,				unsigned long count, unsigned long pos){	long size;	struct cs4281 *chip = entry->private_data;		size = count;	if (pos + size > CS4281_BA0_SIZE)		size = (long)CS4281_BA0_SIZE - pos;	if (size > 0) {		if (copy_to_user_fromio(buf, chip->ba0 + pos, size))			return -EFAULT;	}	return size;}static long snd_cs4281_BA1_read(struct snd_info_entry *entry,				void *file_private_data,				struct file *file, char __user *buf,				unsigned long count, unsigned long pos){	long size;	struct cs4281 *chip = entry->private_data;		size = count;	if (pos + size > CS4281_BA1_SIZE)		size = (long)CS4281_BA1_SIZE - pos;	if (size > 0) {		if (copy_to_user_fromio(buf, chip->ba1 + pos, size))			return -EFAULT;	}	return size;}static struct snd_info_entry_ops snd_cs4281_proc_ops_BA0 = {	.read = snd_cs4281_BA0_read,};static struct snd_info_entry_ops snd_cs4281_proc_ops_BA1 = {	.read = snd_cs4281_BA1_read,};static void __devinit snd_cs4281_proc_init(struct cs4281 * chip){	struct snd_info_entry *entry;	if (! snd_card_proc_new(chip->card, "cs4281", &entry))		snd_info_set_text_ops(entry, chip, snd_cs4281_proc_read);	if (! snd_card_proc_new(chip->card, "cs4281_BA0", &entry)) {		entry->content = SNDRV_INFO_CONTENT_DATA;		entry->private_data = chip;		entry->c.ops = &snd_cs4281_proc_ops_BA0;		entry->size = CS4281_BA0_SIZE;	}	if (! snd_card_proc_new(chip->card, "cs4281_BA1", &entry)) {		entry->content = SNDRV_INFO_CONTENT_DATA;		entry->private_data = chip;		entry->c.ops = &snd_cs4281_proc_ops_BA1;		entry->size = CS4281_BA1_SIZE;	}}/* * joystick support */#if defined(CONFIG_GAMEPORT) || (defined(MODULE) && defined(CONFIG_GAMEPORT_MODULE))static void snd_cs4281_gameport_trigger(struct gameport *gameport){	struct cs4281 *chip = gameport_get_port_data(gameport);	snd_assert(chip, return);	snd_cs4281_pokeBA0(chip, BA0_JSPT, 0xff);}static unsigned char snd_cs4281_gameport_read(struct gameport *gameport){	struct cs4281 *chip = gameport_get_port_data(gameport);	snd_assert(chip, return 0);	return snd_cs4281_peekBA0(chip, BA0_JSPT);}#ifdef COOKED_MODEstatic int snd_cs4281_gameport_cooked_read(struct gameport *gameport,					   int *axes, int *buttons){	struct cs4281 *chip = gameport_get_port_data(gameport);	unsigned js1, js2, jst;		snd_assert(chip, return 0);	js1 = snd_cs4281_peekBA0(chip, BA0_JSC1);	js2 = snd_cs4281_peekBA0(chip, BA0_JSC2);	jst = snd_cs4281_peekBA0(chip, BA0_JSPT);		*buttons = (~jst >> 4) & 0x0F; 		axes[0] = ((js1 & JSC1_Y1V_MASK) >> JSC1_Y1V_SHIFT) & 0xFFFF;	axes[1] = ((js1 & JSC1_X1V_MASK) >> JSC1_X1V_SHIFT) & 0xFFFF;	axes[2] = ((js2 & JSC2_Y2V_MASK) >> JSC2_Y2V_SHIFT) & 0xFFFF;	axes[3] = ((js2 & JSC2_X2V_MASK) >> JSC2_X2V_SHIFT) & 0xFFFF;	for (jst = 0; jst < 4; ++jst)

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -