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

📄 bt87x.c

📁 trident tm5600的linux驱动
💻 C
📖 第 1 页 / 共 3 页
字号:
{	struct snd_bt87x *chip = dev_id;	unsigned int status, irq_status;	status = snd_bt87x_readl(chip, REG_INT_STAT);	irq_status = status & chip->interrupt_mask;	if (!irq_status)		return IRQ_NONE;	snd_bt87x_writel(chip, REG_INT_STAT, irq_status);	if (irq_status & ERROR_INTERRUPTS) {		if (irq_status & (INT_FBUS | INT_FTRGT))			snd_printk(KERN_WARNING "FIFO overrun, status %#08x\n", status);		if (irq_status & INT_OCERR)			snd_printk(KERN_ERR "internal RISC error, status %#08x\n", status);		if (irq_status & (INT_PPERR | INT_RIPERR | INT_PABORT))			snd_bt87x_pci_error(chip, irq_status);	}	if ((irq_status & INT_RISCI) && (chip->reg_control & CTL_ACAP_EN)) {		int current_block, irq_block;		/* assume that exactly one line has been recorded */		chip->current_line = (chip->current_line + 1) % chip->lines;		/* but check if some interrupts have been skipped */		current_block = chip->current_line * 16 / chip->lines;		irq_block = status >> INT_RISCS_SHIFT;		if (current_block != irq_block)			chip->current_line = (irq_block * chip->lines + 15) / 16;		snd_pcm_period_elapsed(chip->substream);	}	return IRQ_HANDLED;}static struct snd_pcm_hardware snd_bt87x_digital_hw = {	.info = SNDRV_PCM_INFO_MMAP |		SNDRV_PCM_INFO_INTERLEAVED |		SNDRV_PCM_INFO_BLOCK_TRANSFER |		SNDRV_PCM_INFO_MMAP_VALID,	.formats = SNDRV_PCM_FMTBIT_S16_LE,	.rates = 0, /* set at runtime */	.channels_min = 2,	.channels_max = 2,	.buffer_bytes_max = 255 * 4092,	.period_bytes_min = 32,	.period_bytes_max = 4092,	.periods_min = 2,	.periods_max = 255,};static struct snd_pcm_hardware snd_bt87x_analog_hw = {	.info = SNDRV_PCM_INFO_MMAP |		SNDRV_PCM_INFO_INTERLEAVED |		SNDRV_PCM_INFO_BLOCK_TRANSFER |		SNDRV_PCM_INFO_MMAP_VALID,	.formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S8,	.rates = SNDRV_PCM_RATE_KNOT,	.rate_min = ANALOG_CLOCK / CLOCK_DIV_MAX,	.rate_max = ANALOG_CLOCK / CLOCK_DIV_MIN,	.channels_min = 1,	.channels_max = 1,	.buffer_bytes_max = 255 * 4092,	.period_bytes_min = 32,	.period_bytes_max = 4092,	.periods_min = 2,	.periods_max = 255,};static int snd_bt87x_set_digital_hw(struct snd_bt87x *chip, struct snd_pcm_runtime *runtime){	chip->reg_control |= CTL_DA_IOM_DA | CTL_A_PWRDN;	runtime->hw = snd_bt87x_digital_hw;	runtime->hw.rates = snd_pcm_rate_to_rate_bit(chip->board.dig_rate);	runtime->hw.rate_min = chip->board.dig_rate;	runtime->hw.rate_max = chip->board.dig_rate;	return 0;}static int snd_bt87x_set_analog_hw(struct snd_bt87x *chip, struct snd_pcm_runtime *runtime){	static struct snd_ratnum analog_clock = {		.num = ANALOG_CLOCK,		.den_min = CLOCK_DIV_MIN,		.den_max = CLOCK_DIV_MAX,		.den_step = 1	};	static struct snd_pcm_hw_constraint_ratnums constraint_rates = {		.nrats = 1,		.rats = &analog_clock	};	chip->reg_control &= ~(CTL_DA_IOM_DA | CTL_A_PWRDN);	runtime->hw = snd_bt87x_analog_hw;	return snd_pcm_hw_constraint_ratnums(runtime, 0, SNDRV_PCM_HW_PARAM_RATE,					     &constraint_rates);}static int snd_bt87x_pcm_open(struct snd_pcm_substream *substream){	struct snd_bt87x *chip = snd_pcm_substream_chip(substream);	struct snd_pcm_runtime *runtime = substream->runtime;	int err;	if (test_and_set_bit(0, &chip->opened))		return -EBUSY;	if (substream->pcm->device == DEVICE_DIGITAL)		err = snd_bt87x_set_digital_hw(chip, runtime);	else		err = snd_bt87x_set_analog_hw(chip, runtime);	if (err < 0)		goto _error;	err = snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS);	if (err < 0)		goto _error;	chip->substream = substream;	return 0;_error:	clear_bit(0, &chip->opened);	smp_mb__after_clear_bit();	return err;}static int snd_bt87x_close(struct snd_pcm_substream *substream){	struct snd_bt87x *chip = snd_pcm_substream_chip(substream);	spin_lock_irq(&chip->reg_lock);	chip->reg_control |= CTL_A_PWRDN;	snd_bt87x_writel(chip, REG_GPIO_DMA_CTL, chip->reg_control);	spin_unlock_irq(&chip->reg_lock);	chip->substream = NULL;	clear_bit(0, &chip->opened);	smp_mb__after_clear_bit();	return 0;}static int snd_bt87x_hw_params(struct snd_pcm_substream *substream,			       struct snd_pcm_hw_params *hw_params){	struct snd_bt87x *chip = snd_pcm_substream_chip(substream);	int err;	err = snd_pcm_lib_malloc_pages(substream,				       params_buffer_bytes(hw_params));	if (err < 0)		return err;	return snd_bt87x_create_risc(chip, substream,				     params_periods(hw_params),				     params_period_bytes(hw_params));}static int snd_bt87x_hw_free(struct snd_pcm_substream *substream){	struct snd_bt87x *chip = snd_pcm_substream_chip(substream);	snd_bt87x_free_risc(chip);	snd_pcm_lib_free_pages(substream);	return 0;}static int snd_bt87x_prepare(struct snd_pcm_substream *substream){	struct snd_bt87x *chip = snd_pcm_substream_chip(substream);	struct snd_pcm_runtime *runtime = substream->runtime;	int decimation;	spin_lock_irq(&chip->reg_lock);	chip->reg_control &= ~(CTL_DA_SDR_MASK | CTL_DA_SBR);	decimation = (ANALOG_CLOCK + runtime->rate / 4) / runtime->rate;	chip->reg_control |= decimation << CTL_DA_SDR_SHIFT;	if (runtime->format == SNDRV_PCM_FORMAT_S8)		chip->reg_control |= CTL_DA_SBR;	snd_bt87x_writel(chip, REG_GPIO_DMA_CTL, chip->reg_control);	spin_unlock_irq(&chip->reg_lock);	return 0;}static int snd_bt87x_start(struct snd_bt87x *chip){	spin_lock(&chip->reg_lock);	chip->current_line = 0;	chip->reg_control |= CTL_FIFO_ENABLE | CTL_RISC_ENABLE | CTL_ACAP_EN;	snd_bt87x_writel(chip, REG_RISC_STRT_ADD, chip->dma_risc.addr);	snd_bt87x_writel(chip, REG_PACKET_LEN,			 chip->line_bytes | (chip->lines << 16));	snd_bt87x_writel(chip, REG_INT_MASK, chip->interrupt_mask);	snd_bt87x_writel(chip, REG_GPIO_DMA_CTL, chip->reg_control);	spin_unlock(&chip->reg_lock);	return 0;}static int snd_bt87x_stop(struct snd_bt87x *chip){	spin_lock(&chip->reg_lock);	chip->reg_control &= ~(CTL_FIFO_ENABLE | CTL_RISC_ENABLE | CTL_ACAP_EN);	snd_bt87x_writel(chip, REG_GPIO_DMA_CTL, chip->reg_control);	snd_bt87x_writel(chip, REG_INT_MASK, 0);	snd_bt87x_writel(chip, REG_INT_STAT, MY_INTERRUPTS);	spin_unlock(&chip->reg_lock);	return 0;}static int snd_bt87x_trigger(struct snd_pcm_substream *substream, int cmd){	struct snd_bt87x *chip = snd_pcm_substream_chip(substream);	switch (cmd) {	case SNDRV_PCM_TRIGGER_START:		return snd_bt87x_start(chip);	case SNDRV_PCM_TRIGGER_STOP:		return snd_bt87x_stop(chip);	default:		return -EINVAL;	}}static snd_pcm_uframes_t snd_bt87x_pointer(struct snd_pcm_substream *substream){	struct snd_bt87x *chip = snd_pcm_substream_chip(substream);	struct snd_pcm_runtime *runtime = substream->runtime;	return (snd_pcm_uframes_t)bytes_to_frames(runtime, chip->current_line * chip->line_bytes);}static struct snd_pcm_ops snd_bt87x_pcm_ops = {	.open = snd_bt87x_pcm_open,	.close = snd_bt87x_close,	.ioctl = snd_pcm_lib_ioctl,	.hw_params = snd_bt87x_hw_params,	.hw_free = snd_bt87x_hw_free,	.prepare = snd_bt87x_prepare,	.trigger = snd_bt87x_trigger,	.pointer = snd_bt87x_pointer,	.page = snd_pcm_sgbuf_ops_page,};static int snd_bt87x_capture_volume_info(struct snd_kcontrol *kcontrol,					 struct snd_ctl_elem_info *info){	info->type = SNDRV_CTL_ELEM_TYPE_INTEGER;	info->count = 1;	info->value.integer.min = 0;	info->value.integer.max = 15;	return 0;}static int snd_bt87x_capture_volume_get(struct snd_kcontrol *kcontrol,					struct snd_ctl_elem_value *value){	struct snd_bt87x *chip = snd_kcontrol_chip(kcontrol);	value->value.integer.value[0] = (chip->reg_control & CTL_A_GAIN_MASK) >> CTL_A_GAIN_SHIFT;	return 0;}static int snd_bt87x_capture_volume_put(struct snd_kcontrol *kcontrol,					struct snd_ctl_elem_value *value){	struct snd_bt87x *chip = snd_kcontrol_chip(kcontrol);	u32 old_control;	int changed;	spin_lock_irq(&chip->reg_lock);	old_control = chip->reg_control;	chip->reg_control = (chip->reg_control & ~CTL_A_GAIN_MASK)		| (value->value.integer.value[0] << CTL_A_GAIN_SHIFT);	snd_bt87x_writel(chip, REG_GPIO_DMA_CTL, chip->reg_control);	changed = old_control != chip->reg_control;	spin_unlock_irq(&chip->reg_lock);	return changed;}static struct snd_kcontrol_new snd_bt87x_capture_volume = {	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,	.name = "Capture Volume",	.info = snd_bt87x_capture_volume_info,	.get = snd_bt87x_capture_volume_get,	.put = snd_bt87x_capture_volume_put,};#define snd_bt87x_capture_boost_info	snd_ctl_boolean_mono_infostatic int snd_bt87x_capture_boost_get(struct snd_kcontrol *kcontrol,				       struct snd_ctl_elem_value *value){	struct snd_bt87x *chip = snd_kcontrol_chip(kcontrol);	value->value.integer.value[0] = !! (chip->reg_control & CTL_A_G2X);	return 0;}static int snd_bt87x_capture_boost_put(struct snd_kcontrol *kcontrol,				       struct snd_ctl_elem_value *value){	struct snd_bt87x *chip = snd_kcontrol_chip(kcontrol);	u32 old_control;	int changed;	spin_lock_irq(&chip->reg_lock);	old_control = chip->reg_control;	chip->reg_control = (chip->reg_control & ~CTL_A_G2X)		| (value->value.integer.value[0] ? CTL_A_G2X : 0);	snd_bt87x_writel(chip, REG_GPIO_DMA_CTL, chip->reg_control);	changed = chip->reg_control != old_control;	spin_unlock_irq(&chip->reg_lock);	return changed;}static struct snd_kcontrol_new snd_bt87x_capture_boost = {	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,	.name = "Capture Boost",	.info = snd_bt87x_capture_boost_info,	.get = snd_bt87x_capture_boost_get,	.put = snd_bt87x_capture_boost_put,};static int snd_bt87x_capture_source_info(struct snd_kcontrol *kcontrol,					 struct snd_ctl_elem_info *info){	static char *texts[3] = {"TV Tuner", "FM", "Mic/Line"};	info->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;	info->count = 1;	info->value.enumerated.items = 3;	if (info->value.enumerated.item > 2)		info->value.enumerated.item = 2;	strcpy(info->value.enumerated.name, texts[info->value.enumerated.item]);	return 0;}static int snd_bt87x_capture_source_get(struct snd_kcontrol *kcontrol,					struct snd_ctl_elem_value *value){	struct snd_bt87x *chip = snd_kcontrol_chip(kcontrol);

⌨️ 快捷键说明

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