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

📄 delta.c

📁 鼎力推荐!本程序是基于嵌入式LUNUX系统开发的源程序代码
💻 C
📖 第 1 页 / 共 2 页
字号:
/* *   ALSA driver for ICEnsemble ICE1712 (Envy24) * *   Lowlevel functions for M-Audio Delta 1010, 44, 66, Dio2496, Audiophile *                          Digigram VX442 * *	Copyright (c) 2000 Jaroslav Kysela <perex@suse.cz> * *   This program is free software; you can redistribute it and/or modify *   it under the terms of the GNU General Public License as published by *   the Free Software Foundation; either version 2 of the License, or *   (at your option) any later version. * *   This program is distributed in the hope that it will be useful, *   but WITHOUT ANY WARRANTY; without even the implied warranty of *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the *   GNU General Public License for more details. * *   You should have received a copy of the GNU General Public License *   along with this program; if not, write to the Free Software *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA * */      #include <sound/driver.h>#include <asm/io.h>#include <linux/delay.h>#include <linux/interrupt.h>#include <linux/init.h>#include <linux/slab.h>#include <sound/core.h>#include <sound/cs8427.h>#include <sound/asoundef.h>#include "ice1712.h"#include "delta.h"#define SND_CS8403#include <sound/cs8403.h>/* * CS8427 via SPI mode (for Audiophile), emulated I2C *//* send 8 bits */static void ap_cs8427_write_byte(ice1712_t *ice, unsigned char data, unsigned char tmp){	int idx;	for (idx = 7; idx >= 0; idx--) {		tmp &= ~(ICE1712_DELTA_AP_DOUT|ICE1712_DELTA_AP_CCLK);		if (data & (1 << idx))			tmp |= ICE1712_DELTA_AP_DOUT;		snd_ice1712_write(ice, ICE1712_IREG_GPIO_DATA, tmp);		udelay(5);		tmp |= ICE1712_DELTA_AP_CCLK;		snd_ice1712_write(ice, ICE1712_IREG_GPIO_DATA, tmp);		udelay(5);	}}/* read 8 bits */static unsigned char ap_cs8427_read_byte(ice1712_t *ice, unsigned char tmp){	unsigned char data = 0;	int idx;		for (idx = 7; idx >= 0; idx--) {		tmp &= ~ICE1712_DELTA_AP_CCLK;		snd_ice1712_write(ice, ICE1712_IREG_GPIO_DATA, tmp);		udelay(5);		if (snd_ice1712_read(ice, ICE1712_IREG_GPIO_DATA) & ICE1712_DELTA_AP_DIN)			data |= 1 << idx;		tmp |= ICE1712_DELTA_AP_CCLK;		snd_ice1712_write(ice, ICE1712_IREG_GPIO_DATA, tmp);		udelay(5);	}	return data;}/* assert chip select */static unsigned char ap_cs8427_codec_select(ice1712_t *ice){	unsigned char tmp;	tmp = snd_ice1712_read(ice, ICE1712_IREG_GPIO_DATA);	switch (ice->eeprom.subvendor) {	case ICE1712_SUBDEVICE_DELTA1010LT:		tmp &= ~ICE1712_DELTA_1010LT_CS;		tmp |= ICE1712_DELTA_1010LT_CCLK | ICE1712_DELTA_1010LT_CS_CS8427;		break;	case ICE1712_SUBDEVICE_AUDIOPHILE:	case ICE1712_SUBDEVICE_DELTA410:		tmp |= ICE1712_DELTA_AP_CCLK | ICE1712_DELTA_AP_CS_CODEC;		tmp &= ~ICE1712_DELTA_AP_CS_DIGITAL;		break;	case ICE1712_SUBDEVICE_VX442:		tmp |= ICE1712_VX442_CCLK | ICE1712_VX442_CODEC_CHIP_A | ICE1712_VX442_CODEC_CHIP_B;		tmp &= ~ICE1712_VX442_CS_DIGITAL;		break;	}	snd_ice1712_write(ice, ICE1712_IREG_GPIO_DATA, tmp);	udelay(5);	return tmp;}/* deassert chip select */static void ap_cs8427_codec_deassert(ice1712_t *ice, unsigned char tmp){	switch (ice->eeprom.subvendor) {	case ICE1712_SUBDEVICE_DELTA1010LT:		tmp &= ~ICE1712_DELTA_1010LT_CS;		tmp |= ICE1712_DELTA_1010LT_CS_NONE;		break;	case ICE1712_SUBDEVICE_AUDIOPHILE:	case ICE1712_SUBDEVICE_DELTA410:		tmp |= ICE1712_DELTA_AP_CS_DIGITAL;		break;	case ICE1712_SUBDEVICE_VX442:		tmp |= ICE1712_VX442_CS_DIGITAL;		break;	}	snd_ice1712_write(ice, ICE1712_IREG_GPIO_DATA, tmp);}/* sequential write */static int ap_cs8427_sendbytes(snd_i2c_device_t *device, unsigned char *bytes, int count){	ice1712_t *ice = device->bus->private_data;	int res = count;	unsigned char tmp;	down(&ice->gpio_mutex);	tmp = ap_cs8427_codec_select(ice);	ap_cs8427_write_byte(ice, (device->addr << 1) | 0, tmp); /* address + write mode */	while (count-- > 0)		ap_cs8427_write_byte(ice, *bytes++, tmp);	ap_cs8427_codec_deassert(ice, tmp);	up(&ice->gpio_mutex);	return res;}/* sequential read */static int ap_cs8427_readbytes(snd_i2c_device_t *device, unsigned char *bytes, int count){	ice1712_t *ice = device->bus->private_data;	int res = count;	unsigned char tmp;		down(&ice->gpio_mutex);	tmp = ap_cs8427_codec_select(ice);	ap_cs8427_write_byte(ice, (device->addr << 1) | 1, tmp); /* address + read mode */	while (count-- > 0)		*bytes++ = ap_cs8427_read_byte(ice, tmp);	ap_cs8427_codec_deassert(ice, tmp);	up(&ice->gpio_mutex);	return res;}static int ap_cs8427_probeaddr(snd_i2c_bus_t *bus, unsigned short addr){	if (addr == 0x10)		return 1;	return -ENOENT;}static snd_i2c_ops_t ap_cs8427_i2c_ops = {	.sendbytes = ap_cs8427_sendbytes,	.readbytes = ap_cs8427_readbytes,	.probeaddr = ap_cs8427_probeaddr,};/* */static void snd_ice1712_delta_cs8403_spdif_write(ice1712_t *ice, unsigned char bits){	unsigned char tmp, mask1, mask2;	int idx;	/* send byte to transmitter */	mask1 = ICE1712_DELTA_SPDIF_OUT_STAT_CLOCK;	mask2 = ICE1712_DELTA_SPDIF_OUT_STAT_DATA;	down(&ice->gpio_mutex);	tmp = snd_ice1712_read(ice, ICE1712_IREG_GPIO_DATA);	for (idx = 7; idx >= 0; idx--) {		tmp &= ~(mask1 | mask2);		if (bits & (1 << idx))			tmp |= mask2;		snd_ice1712_write(ice, ICE1712_IREG_GPIO_DATA, tmp);		udelay(100);		tmp |= mask1;		snd_ice1712_write(ice, ICE1712_IREG_GPIO_DATA, tmp);		udelay(100);	}	tmp &= ~mask1;	snd_ice1712_write(ice, ICE1712_IREG_GPIO_DATA, tmp);	up(&ice->gpio_mutex);}static void delta_spdif_default_get(ice1712_t *ice, snd_ctl_elem_value_t * ucontrol){	snd_cs8403_decode_spdif_bits(&ucontrol->value.iec958, ice->spdif.cs8403_bits);}static int delta_spdif_default_put(ice1712_t *ice, snd_ctl_elem_value_t * ucontrol){	unsigned int val;	int change;	val = snd_cs8403_encode_spdif_bits(&ucontrol->value.iec958);	spin_lock_irq(&ice->reg_lock);	change = ice->spdif.cs8403_bits != val;	ice->spdif.cs8403_bits = val;	if (change && ice->playback_pro_substream == NULL) {		spin_unlock_irq(&ice->reg_lock);		snd_ice1712_delta_cs8403_spdif_write(ice, val);	} else {		spin_unlock_irq(&ice->reg_lock);	}	return change;}static void delta_spdif_stream_get(ice1712_t *ice, snd_ctl_elem_value_t * ucontrol){	snd_cs8403_decode_spdif_bits(&ucontrol->value.iec958, ice->spdif.cs8403_stream_bits);}static int delta_spdif_stream_put(ice1712_t *ice, snd_ctl_elem_value_t * ucontrol){	unsigned int val;	int change;	val = snd_cs8403_encode_spdif_bits(&ucontrol->value.iec958);	spin_lock_irq(&ice->reg_lock);	change = ice->spdif.cs8403_stream_bits != val;	ice->spdif.cs8403_stream_bits = val;	if (change && ice->playback_pro_substream != NULL) {		spin_unlock_irq(&ice->reg_lock);		snd_ice1712_delta_cs8403_spdif_write(ice, val);	} else {		spin_unlock_irq(&ice->reg_lock);	}	return change;}/* * AK4524 on Delta 44 and 66 to choose the chip mask */static void delta_ak4524_lock(akm4xxx_t *ak, int chip){        struct snd_ak4xxx_private *priv = (void *)ak->private_value[0];        ice1712_t *ice = ak->private_data[0];	snd_ice1712_save_gpio_status(ice);	priv->cs_mask =	priv->cs_addr = chip == 0 ? ICE1712_DELTA_CODEC_CHIP_A :				    ICE1712_DELTA_CODEC_CHIP_B;}/* * AK4524 on Delta1010LT to choose the chip address */static void delta1010lt_ak4524_lock(akm4xxx_t *ak, int chip){        struct snd_ak4xxx_private *priv = (void *)ak->private_value[0];        ice1712_t *ice = ak->private_data[0];	snd_ice1712_save_gpio_status(ice);	priv->cs_mask = ICE1712_DELTA_1010LT_CS;	priv->cs_addr = chip << 4;}/* * AK4528 on VX442 to choose the chip mask */static void vx442_ak4524_lock(akm4xxx_t *ak, int chip){        struct snd_ak4xxx_private *priv = (void *)ak->private_value[0];        ice1712_t *ice = ak->private_data[0];	snd_ice1712_save_gpio_status(ice);	priv->cs_mask =	priv->cs_addr = chip == 0 ? ICE1712_VX442_CODEC_CHIP_A :				    ICE1712_VX442_CODEC_CHIP_B;}/* * change the DFS bit according rate for Delta1010 */static void delta_1010_set_rate_val(ice1712_t *ice, unsigned int rate){	unsigned char tmp, tmp2;	if (rate == 0)	/* no hint - S/PDIF input is master, simply return */		return;	down(&ice->gpio_mutex);	tmp = snd_ice1712_read(ice, ICE1712_IREG_GPIO_DATA);	tmp2 = tmp & ~ICE1712_DELTA_DFS;	if (rate > 48000)		tmp2 |= ICE1712_DELTA_DFS;	if (tmp != tmp2)		snd_ice1712_write(ice, ICE1712_IREG_GPIO_DATA, tmp2);	up(&ice->gpio_mutex);}/* * change the rate of AK4524 on Delta 44/66, AP, 1010LT */static void delta_ak4524_set_rate_val(akm4xxx_t *ak, unsigned int rate){	unsigned char tmp, tmp2;	ice1712_t *ice = ak->private_data[0];	if (rate == 0)	/* no hint - S/PDIF input is master, simply return */		return;	/* check before reset ak4524 to avoid unnecessary clicks */	down(&ice->gpio_mutex);	tmp = snd_ice1712_read(ice, ICE1712_IREG_GPIO_DATA);	up(&ice->gpio_mutex);	tmp2 = tmp & ~ICE1712_DELTA_DFS; 	if (rate > 48000)		tmp2 |= ICE1712_DELTA_DFS;	if (tmp == tmp2)		return;	/* do it again */	snd_akm4xxx_reset(ak, 1);	down(&ice->gpio_mutex);	tmp = snd_ice1712_read(ice, ICE1712_IREG_GPIO_DATA) & ~ICE1712_DELTA_DFS;	if (rate > 48000)		tmp |= ICE1712_DELTA_DFS;	snd_ice1712_write(ice, ICE1712_IREG_GPIO_DATA, tmp);	up(&ice->gpio_mutex);	snd_akm4xxx_reset(ak, 0);}/* * change the rate of AK4524 on VX442 */static void vx442_ak4524_set_rate_val(akm4xxx_t *ak, unsigned int rate){	unsigned char val;	val = (rate > 48000) ? 0x65 : 0x60;	if (snd_akm4xxx_get(ak, 0, 0x02) != val ||	    snd_akm4xxx_get(ak, 1, 0x02) != val) {		snd_akm4xxx_reset(ak, 1);		snd_akm4xxx_write(ak, 0, 0x02, val);		snd_akm4xxx_write(ak, 1, 0x02, val);		snd_akm4xxx_reset(ak, 0);	}}/* * SPDIF ops for Delta 1010, Dio, 66 *//* open callback */static void delta_open_spdif(ice1712_t *ice, snd_pcm_substream_t * substream){	ice->spdif.cs8403_stream_bits = ice->spdif.cs8403_bits;}/* set up */static void delta_setup_spdif(ice1712_t *ice, int rate){	unsigned long flags;	unsigned int tmp;	int change;	spin_lock_irqsave(&ice->reg_lock, flags);	tmp = ice->spdif.cs8403_stream_bits;	if (tmp & 0x01)		/* consumer */		tmp &= (tmp & 0x01) ? ~0x06 : ~0x18;	switch (rate) {	case 32000: tmp |= (tmp & 0x01) ? 0x04 : 0x00; break;	case 44100: tmp |= (tmp & 0x01) ? 0x00 : 0x10; break;	case 48000: tmp |= (tmp & 0x01) ? 0x02 : 0x08; break;	default: tmp |= (tmp & 0x01) ? 0x00 : 0x18; break;	}	change = ice->spdif.cs8403_stream_bits != tmp;

⌨️ 快捷键说明

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