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

📄 uda1341.c

📁 linux-2.6.15.6
💻 C
📖 第 1 页 / 共 2 页
字号:
static void __devinit snd_uda1341_proc_init(snd_card_t *card, struct l3_client *clnt){	snd_info_entry_t *entry;	if (! snd_card_proc_new(card, "uda1341", &entry))		snd_info_set_text_ops(entry, clnt, 1024, snd_uda1341_proc_read);	if (! snd_card_proc_new(card, "uda1341-regs", &entry))		snd_info_set_text_ops(entry, clnt, 1024, snd_uda1341_proc_regs_read);}/* }}} *//* {{{ Mixer controls setting *//* {{{ UDA1341 single functions */#define UDA1341_SINGLE(xname, where, reg, shift, mask, invert) \{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .info = snd_uda1341_info_single, \  .get = snd_uda1341_get_single, .put = snd_uda1341_put_single, \  .private_value = where | (reg << 5) | (shift << 9) | (mask << 12) | (invert << 18) \}static int snd_uda1341_info_single(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo){	int mask = (kcontrol->private_value >> 12) & 63;	uinfo->type = mask == 1 ? SNDRV_CTL_ELEM_TYPE_BOOLEAN : SNDRV_CTL_ELEM_TYPE_INTEGER;	uinfo->count = 1;	uinfo->value.integer.min = 0;	uinfo->value.integer.max = mask;	return 0;}static int snd_uda1341_get_single(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol){	struct l3_client *clnt = snd_kcontrol_chip(kcontrol);	uda1341_t *uda = clnt->driver_data;	int where = kcontrol->private_value & 31;        	int mask = (kcontrol->private_value >> 12) & 63;	int invert = (kcontrol->private_value >> 18) & 1;        	ucontrol->value.integer.value[0] = uda->cfg[where];	if (invert)		ucontrol->value.integer.value[0] = mask - ucontrol->value.integer.value[0];	return 0;}static int snd_uda1341_put_single(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol){	struct l3_client *clnt = snd_kcontrol_chip(kcontrol);	uda1341_t *uda = clnt->driver_data;	int where = kcontrol->private_value & 31;        	int reg = (kcontrol->private_value >> 5) & 15;	int shift = (kcontrol->private_value >> 9) & 7;	int mask = (kcontrol->private_value >> 12) & 63;	int invert = (kcontrol->private_value >> 18) & 1;	unsigned short val;	val = (ucontrol->value.integer.value[0] & mask);	if (invert)		val = mask - val;	uda->cfg[where] = val;	return snd_uda1341_update_bits(clnt, reg, mask, shift, val, FLUSH);}/* }}} *//* {{{ UDA1341 enum functions */#define UDA1341_ENUM(xname, where, reg, shift, mask, invert) \{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .info = snd_uda1341_info_enum, \  .get = snd_uda1341_get_enum, .put = snd_uda1341_put_enum, \  .private_value = where | (reg << 5) | (shift << 9) | (mask << 12) | (invert << 18) \}static int snd_uda1341_info_enum(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo){	int where = kcontrol->private_value & 31;	const char **texts;		// this register we don't handle this way	if (!uda1341_enum_items[where])		return -EINVAL;	uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;	uinfo->count = 1;	uinfo->value.enumerated.items = uda1341_enum_items[where];	if (uinfo->value.enumerated.item >= uda1341_enum_items[where])		uinfo->value.enumerated.item = uda1341_enum_items[where] - 1;	texts = uda1341_enum_names[where];	strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);	return 0;}static int snd_uda1341_get_enum(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol){	struct l3_client *clnt = snd_kcontrol_chip(kcontrol);	uda1341_t *uda = clnt->driver_data;	int where = kcontrol->private_value & 31;                	ucontrol->value.enumerated.item[0] = uda->cfg[where];		return 0;}static int snd_uda1341_put_enum(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol){	struct l3_client *clnt = snd_kcontrol_chip(kcontrol);	uda1341_t *uda = clnt->driver_data;	int where = kcontrol->private_value & 31;        	int reg = (kcontrol->private_value >> 5) & 15;	int shift = (kcontrol->private_value >> 9) & 7;	int mask = (kcontrol->private_value >> 12) & 63;	uda->cfg[where] = (ucontrol->value.enumerated.item[0] & mask);		return snd_uda1341_update_bits(clnt, reg, mask, shift, uda->cfg[where], FLUSH);}/* }}} *//* {{{ UDA1341 2regs functions */#define UDA1341_2REGS(xname, where, reg_1, reg_2, shift_1, shift_2, mask_1, mask_2, invert) \{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname), .info = snd_uda1341_info_2regs, \  .get = snd_uda1341_get_2regs, .put = snd_uda1341_put_2regs, \  .private_value = where | (reg_1 << 5) | (reg_2 << 9) | (shift_1 << 13) | (shift_2 << 16) | \                         (mask_1 << 19) | (mask_2 << 25) | (invert << 31) \}static int snd_uda1341_info_2regs(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo){	int mask_1 = (kcontrol->private_value >> 19) & 63;	int mask_2 = (kcontrol->private_value >> 25) & 63;	int mask;        	mask = (mask_2 + 1) * (mask_1 + 1) - 1;	uinfo->type = mask == 1 ? SNDRV_CTL_ELEM_TYPE_BOOLEAN : SNDRV_CTL_ELEM_TYPE_INTEGER;	uinfo->count = 1;	uinfo->value.integer.min = 0;	uinfo->value.integer.max = mask;	return 0;}static int snd_uda1341_get_2regs(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol){	struct l3_client *clnt = snd_kcontrol_chip(kcontrol);	uda1341_t *uda = clnt->driver_data;	int where = kcontrol->private_value & 31;	int mask_1 = (kcontrol->private_value >> 19) & 63;	int mask_2 = (kcontrol->private_value >> 25) & 63;        	int invert = (kcontrol->private_value >> 31) & 1;	int mask;	mask = (mask_2 + 1) * (mask_1 + 1) - 1;	ucontrol->value.integer.value[0] = uda->cfg[where];	if (invert)		ucontrol->value.integer.value[0] = mask - ucontrol->value.integer.value[0];	return 0;}static int snd_uda1341_put_2regs(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol){	struct l3_client *clnt = snd_kcontrol_chip(kcontrol);	uda1341_t *uda = clnt->driver_data;        	int where = kcontrol->private_value & 31;        	int reg_1 = (kcontrol->private_value >> 5) & 15;	int reg_2 = (kcontrol->private_value >> 9) & 15;        	int shift_1 = (kcontrol->private_value >> 13) & 7;	int shift_2 = (kcontrol->private_value >> 16) & 7;	int mask_1 = (kcontrol->private_value >> 19) & 63;	int mask_2 = (kcontrol->private_value >> 25) & 63;        	int invert = (kcontrol->private_value >> 31) & 1;	int mask;	unsigned short val1, val2, val;	val = ucontrol->value.integer.value[0];         	mask = (mask_2 + 1) * (mask_1 + 1) - 1;	val1 = val & mask_1;	val2 = (val / (mask_1 + 1)) & mask_2;        	if (invert) {		val1 = mask_1 - val1;		val2 = mask_2 - val2;	}	uda->cfg[where] = invert ? mask - val : val;        	//FIXME - return value	snd_uda1341_update_bits(clnt, reg_1, mask_1, shift_1, val1, FLUSH);	return snd_uda1341_update_bits(clnt, reg_2, mask_2, shift_2, val2, FLUSH);}/* }}} */  static snd_kcontrol_new_t snd_uda1341_controls[] = {	UDA1341_SINGLE("Master Playback Switch", CMD_MUTE, data0_2, 2, 1, 1),	UDA1341_SINGLE("Master Playback Volume", CMD_VOLUME, data0_0, 0, 63, 1),	UDA1341_SINGLE("Bass Playback Volume", CMD_BASS, data0_1, 2, 15, 0),	UDA1341_SINGLE("Treble Playback Volume", CMD_TREBBLE, data0_1, 0, 3, 0),	UDA1341_SINGLE("Input Gain Switch", CMD_IGAIN, stat1, 5, 1, 0),	UDA1341_SINGLE("Output Gain Switch", CMD_OGAIN, stat1, 6, 1, 0),	UDA1341_SINGLE("Mixer Gain Channel 1 Volume", CMD_CH1, ext0, 0, 31, 1),	UDA1341_SINGLE("Mixer Gain Channel 2 Volume", CMD_CH2, ext1, 0, 31, 1),	UDA1341_SINGLE("Mic Sensitivity Volume", CMD_MIC, ext2, 2, 7, 0),	UDA1341_SINGLE("AGC Output Level", CMD_AGC_LEVEL, ext6, 0, 3, 0),	UDA1341_SINGLE("AGC Time Constant", CMD_AGC_TIME, ext6, 2, 7, 0),	UDA1341_SINGLE("AGC Time Constant Switch", CMD_AGC, ext4, 4, 1, 0),	UDA1341_SINGLE("DAC Power", CMD_DAC, stat1, 0, 1, 0),	UDA1341_SINGLE("ADC Power", CMD_ADC, stat1, 1, 1, 0),	UDA1341_ENUM("Peak detection", CMD_PEAK, data0_2, 5, 1, 0),	UDA1341_ENUM("De-emphasis", CMD_DEEMP, data0_2, 3, 3, 0),	UDA1341_ENUM("Mixer mode", CMD_MIXER, ext2, 0, 3, 0),	UDA1341_ENUM("Filter mode", CMD_FILTER, data0_2, 0, 3, 0),	UDA1341_2REGS("Gain Input Amplifier Gain (channel 2)", CMD_IG, ext4, ext5, 0, 0, 3, 31, 0),};static void uda1341_free(struct l3_client *uda1341){	l3_detach_client(uda1341); // calls kfree for driver_data (uda1341_t)	kfree(uda1341);}static int uda1341_dev_free(snd_device_t *device){	struct l3_client *clnt = device->device_data;	uda1341_free(clnt);	return 0;}int __init snd_chip_uda1341_mixer_new(snd_card_t *card, struct l3_client **clnt){	static snd_device_ops_t ops = {		.dev_free =     uda1341_dev_free,	};	struct l3_client *uda1341;	int idx, err;	snd_assert(card != NULL, return -EINVAL);	uda1341 = kzalloc(sizeof(*uda1341), GFP_KERNEL);	if (uda1341 == NULL)		return -ENOMEM;         	if ((err = l3_attach_client(uda1341, "l3-bit-sa1100-gpio", "snd-uda1341"))) {		kfree(uda1341);		return err;	}	if ((err = snd_device_new(card, SNDRV_DEV_CODEC, uda1341, &ops)) < 0) {		l3_detach_client(uda1341);		kfree(uda1341);		return err;	}	for (idx = 0; idx < ARRAY_SIZE(snd_uda1341_controls); idx++) {		if ((err = snd_ctl_add(card, snd_ctl_new1(&snd_uda1341_controls[idx], uda1341))) < 0)			return err;	}	*clnt = uda1341;	strcpy(card->mixername, "UDA1341TS Mixer");	((uda1341_t *)uda1341->driver_data)->card = card;        	snd_uda1341_proc_init(card, uda1341);        	return 0;}/* }}} *//* {{{ L3 operations */static int uda1341_attach(struct l3_client *clnt){	struct uda1341 *uda;	uda = kzalloc(sizeof(*uda), 0, GFP_KERNEL);	if (!uda)		return -ENOMEM;	/* init fixed parts of my copy of registers */	uda->regs[stat0]   = STAT0;	uda->regs[stat1]   = STAT1;	uda->regs[data0_0] = DATA0_0;	uda->regs[data0_1] = DATA0_1;	uda->regs[data0_2] = DATA0_2;	uda->write = snd_uda1341_codec_write;	uda->read = snd_uda1341_codec_read;  	spin_lock_init(&uda->reg_lock);        	clnt->driver_data = uda;	return 0;}static void uda1341_detach(struct l3_client *clnt){	kfree(clnt->driver_data);}static intuda1341_command(struct l3_client *clnt, int cmd, void *arg){	if (cmd != CMD_READ_REG)		return snd_uda1341_cfg_write(clnt, cmd, (int) arg, FLUSH);	return snd_uda1341_codec_read(clnt, (int) arg);}static int uda1341_open(struct l3_client *clnt){	struct uda1341 *uda = clnt->driver_data;	uda->active = 1;	/* init default configuration */	snd_uda1341_cfg_write(clnt, CMD_RESET, 0, REGS_ONLY);	snd_uda1341_cfg_write(clnt, CMD_FS, F256, FLUSH);       // unknown state after reset	snd_uda1341_cfg_write(clnt, CMD_FORMAT, LSB16, FLUSH);  // unknown state after reset	snd_uda1341_cfg_write(clnt, CMD_OGAIN, ON, FLUSH);      // default off after reset	snd_uda1341_cfg_write(clnt, CMD_IGAIN, ON, FLUSH);      // default off after reset	snd_uda1341_cfg_write(clnt, CMD_DAC, ON, FLUSH);	// ??? default value after reset	snd_uda1341_cfg_write(clnt, CMD_ADC, ON, FLUSH);	// ??? default value after reset	snd_uda1341_cfg_write(clnt, CMD_VOLUME, 20, FLUSH);     // default 0dB after reset	snd_uda1341_cfg_write(clnt, CMD_BASS, 0, REGS_ONLY);    // default value after reset	snd_uda1341_cfg_write(clnt, CMD_TREBBLE, 0, REGS_ONLY); // default value after reset	snd_uda1341_cfg_write(clnt, CMD_PEAK, AFTER, REGS_ONLY);// default value after reset	snd_uda1341_cfg_write(clnt, CMD_DEEMP, NONE, REGS_ONLY);// default value after reset	//at this moment should be QMUTED by h3600_audio_init	snd_uda1341_cfg_write(clnt, CMD_MUTE, OFF, REGS_ONLY);  // default value after reset	snd_uda1341_cfg_write(clnt, CMD_FILTER, MAX, FLUSH);    // defaul flat after reset	snd_uda1341_cfg_write(clnt, CMD_CH1, 31, FLUSH);        // default value after reset	snd_uda1341_cfg_write(clnt, CMD_CH2, 4, FLUSH);         // default value after reset	snd_uda1341_cfg_write(clnt, CMD_MIC, 4, FLUSH);         // default 0dB after reset	snd_uda1341_cfg_write(clnt, CMD_MIXER, MIXER, FLUSH);   // default doub.dif.mode          	snd_uda1341_cfg_write(clnt, CMD_AGC, OFF, FLUSH);       // default value after reset	snd_uda1341_cfg_write(clnt, CMD_IG, 0, FLUSH);          // unknown state after reset	snd_uda1341_cfg_write(clnt, CMD_AGC_TIME, 0, FLUSH);    // default value after reset	snd_uda1341_cfg_write(clnt, CMD_AGC_LEVEL, 0, FLUSH);   // default value after reset	return 0;}static void uda1341_close(struct l3_client *clnt){	struct uda1341 *uda = clnt->driver_data;	uda->active = 0;}/* }}} *//* {{{ Module and L3 initialization */static struct l3_ops uda1341_ops = {	.open =		uda1341_open,	.command =	uda1341_command,	.close =	uda1341_close,};static struct l3_driver uda1341_driver = {	.name =		UDA1341_ALSA_NAME,	.attach_client = uda1341_attach,	.detach_client = uda1341_detach,	.ops =		&uda1341_ops,	.owner =	THIS_MODULE,};static int __init uda1341_init(void){	return l3_add_driver(&uda1341_driver);}static void __exit uda1341_exit(void){	l3_del_driver(&uda1341_driver);}module_init(uda1341_init);module_exit(uda1341_exit);MODULE_AUTHOR("Tomas Kasparek <tomas.kasparek@seznam.cz>");MODULE_LICENSE("GPL");MODULE_DESCRIPTION("Philips UDA1341 CODEC driver for ALSA");MODULE_SUPPORTED_DEVICE("{{UDA1341,UDA1341TS}}");EXPORT_SYMBOL(snd_chip_uda1341_mixer_new);/* }}} *//* * Local variables: * indent-tabs-mode: t * End: */

⌨️ 快捷键说明

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