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

📄 azt3328.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
	r->reg = val & 0xff;	r->lchan_shift = (val >> 8) & 0x0f;	r->rchan_shift = (val >> 12) & 0x0f;	r->mask = (val >> 16) & 0xff;	r->invert = (val >> 24) & 1;	r->stereo = (val >> 25) & 1;	r->enum_c = (val >> 26) & 0x0f;}/* * mixer switches/volumes */#define AZF3328_MIXER_SWITCH(xname, reg, shift, invert) \{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \  .info = snd_azf3328_info_mixer, \  .get = snd_azf3328_get_mixer, .put = snd_azf3328_put_mixer, \  .private_value = COMPOSE_MIXER_REG(reg, shift, 0, 0x1, invert, 0, 0), \}#define AZF3328_MIXER_VOL_STEREO(xname, reg, mask, invert) \{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \  .info = snd_azf3328_info_mixer, \  .get = snd_azf3328_get_mixer, .put = snd_azf3328_put_mixer, \  .private_value = COMPOSE_MIXER_REG(reg, 8, 0, mask, invert, 1, 0), \}#define AZF3328_MIXER_VOL_MONO(xname, reg, mask, is_right_chan) \{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \  .info = snd_azf3328_info_mixer, \  .get = snd_azf3328_get_mixer, .put = snd_azf3328_put_mixer, \  .private_value = COMPOSE_MIXER_REG(reg, is_right_chan ? 0 : 8, 0, mask, 1, 0, 0), \}#define AZF3328_MIXER_VOL_SPECIAL(xname, reg, mask, shift, invert) \{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \  .info = snd_azf3328_info_mixer, \  .get = snd_azf3328_get_mixer, .put = snd_azf3328_put_mixer, \  .private_value = COMPOSE_MIXER_REG(reg, shift, 0, mask, invert, 0, 0), \}#define AZF3328_MIXER_ENUM(xname, reg, enum_c, shift) \{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \  .info = snd_azf3328_info_mixer_enum, \  .get = snd_azf3328_get_mixer_enum, .put = snd_azf3328_put_mixer_enum, \  .private_value = COMPOSE_MIXER_REG(reg, shift, 0, 0, 0, 0, enum_c), \}static intsnd_azf3328_info_mixer(struct snd_kcontrol *kcontrol,		       struct snd_ctl_elem_info *uinfo){	struct azf3328_mixer_reg reg;	snd_azf3328_dbgcallenter();	snd_azf3328_mixer_reg_decode(&reg, kcontrol->private_value);	uinfo->type = reg.mask == 1 ?		SNDRV_CTL_ELEM_TYPE_BOOLEAN : SNDRV_CTL_ELEM_TYPE_INTEGER;	uinfo->count = reg.stereo + 1;	uinfo->value.integer.min = 0;	uinfo->value.integer.max = reg.mask;	snd_azf3328_dbgcallleave();	return 0;}static intsnd_azf3328_get_mixer(struct snd_kcontrol *kcontrol,		      struct snd_ctl_elem_value *ucontrol){	struct snd_azf3328 *chip = snd_kcontrol_chip(kcontrol);	struct azf3328_mixer_reg reg;	unsigned int oreg, val;	snd_azf3328_dbgcallenter();	snd_azf3328_mixer_reg_decode(&reg, kcontrol->private_value);	oreg = snd_azf3328_mixer_inw(chip, reg.reg);	val = (oreg >> reg.lchan_shift) & reg.mask;	if (reg.invert)		val = reg.mask - val;	ucontrol->value.integer.value[0] = val;	if (reg.stereo) {		val = (oreg >> reg.rchan_shift) & reg.mask;		if (reg.invert)			val = reg.mask - val;		ucontrol->value.integer.value[1] = val;	}	snd_azf3328_dbgmixer("get: %02x is %04x -> vol %02lx|%02lx "			     "(shift %02d|%02d, mask %02x, inv. %d, stereo %d)\n",		reg.reg, oreg,		ucontrol->value.integer.value[0], ucontrol->value.integer.value[1],		reg.lchan_shift, reg.rchan_shift, reg.mask, reg.invert, reg.stereo);	snd_azf3328_dbgcallleave();	return 0;}static intsnd_azf3328_put_mixer(struct snd_kcontrol *kcontrol,		      struct snd_ctl_elem_value *ucontrol){	struct snd_azf3328 *chip = snd_kcontrol_chip(kcontrol);	struct azf3328_mixer_reg reg;	unsigned int oreg, nreg, val;	snd_azf3328_dbgcallenter();	snd_azf3328_mixer_reg_decode(&reg, kcontrol->private_value);	oreg = snd_azf3328_mixer_inw(chip, reg.reg);	val = ucontrol->value.integer.value[0] & reg.mask;	if (reg.invert)		val = reg.mask - val;	nreg = oreg & ~(reg.mask << reg.lchan_shift);	nreg |= (val << reg.lchan_shift);	if (reg.stereo) {		val = ucontrol->value.integer.value[1] & reg.mask;		if (reg.invert)			val = reg.mask - val;		nreg &= ~(reg.mask << reg.rchan_shift);		nreg |= (val << reg.rchan_shift);	}	if (reg.mask >= 0x07) /* it's a volume control, so better take care */		snd_azf3328_mixer_write_volume_gradually(			chip, reg.reg, nreg >> 8, nreg & 0xff,			/* just set both channels, doesn't matter */			SET_CHAN_LEFT|SET_CHAN_RIGHT,			0);	else        	snd_azf3328_mixer_outw(chip, reg.reg, nreg);	snd_azf3328_dbgmixer("put: %02x to %02lx|%02lx, "			     "oreg %04x; shift %02d|%02d -> nreg %04x; after: %04x\n",		reg.reg, ucontrol->value.integer.value[0], ucontrol->value.integer.value[1],		oreg, reg.lchan_shift, reg.rchan_shift,		nreg, snd_azf3328_mixer_inw(chip, reg.reg));	snd_azf3328_dbgcallleave();	return (nreg != oreg);}static intsnd_azf3328_info_mixer_enum(struct snd_kcontrol *kcontrol,			    struct snd_ctl_elem_info *uinfo){	static const char * const texts1[] = {		"Mic1", "Mic2"	};	static const char * const texts2[] = {		"Mix", "Mic"	};	static const char * const texts3[] = {                "Mic", "CD", "Video", "Aux",		"Line", "Mix", "Mix Mono", "Phone"        };	static const char * const texts4[] = {		"pre 3D", "post 3D"        };	struct azf3328_mixer_reg reg;	snd_azf3328_mixer_reg_decode(&reg, kcontrol->private_value);        uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;        uinfo->count = (reg.reg == IDX_MIXER_REC_SELECT) ? 2 : 1;        uinfo->value.enumerated.items = reg.enum_c;        if (uinfo->value.enumerated.item > reg.enum_c - 1U)                uinfo->value.enumerated.item = reg.enum_c - 1U;	if (reg.reg == IDX_MIXER_ADVCTL2) {		switch(reg.lchan_shift) {		case 8: /* modem out sel */			strcpy(uinfo->value.enumerated.name, texts1[uinfo->value.enumerated.item]);			break;		case 9: /* mono sel source */			strcpy(uinfo->value.enumerated.name, texts2[uinfo->value.enumerated.item]);			break;		case 15: /* PCM Out Path */			strcpy(uinfo->value.enumerated.name, texts4[uinfo->value.enumerated.item]);			break;		}	} else        	strcpy(uinfo->value.enumerated.name, texts3[uinfo->value.enumerated.item]);        return 0;}static intsnd_azf3328_get_mixer_enum(struct snd_kcontrol *kcontrol,			   struct snd_ctl_elem_value *ucontrol){        struct snd_azf3328 *chip = snd_kcontrol_chip(kcontrol);	struct azf3328_mixer_reg reg;        unsigned short val;        	snd_azf3328_mixer_reg_decode(&reg, kcontrol->private_value);	val = snd_azf3328_mixer_inw(chip, reg.reg);	if (reg.reg == IDX_MIXER_REC_SELECT) {        	ucontrol->value.enumerated.item[0] = (val >> 8) & (reg.enum_c - 1);        	ucontrol->value.enumerated.item[1] = (val >> 0) & (reg.enum_c - 1);	} else        	ucontrol->value.enumerated.item[0] = (val >> reg.lchan_shift) & (reg.enum_c - 1);	snd_azf3328_dbgmixer("get_enum: %02x is %04x -> %d|%d (shift %02d, enum_c %d)\n",		reg.reg, val, ucontrol->value.enumerated.item[0], ucontrol->value.enumerated.item[1],		reg.lchan_shift, reg.enum_c);        return 0;}static intsnd_azf3328_put_mixer_enum(struct snd_kcontrol *kcontrol,			   struct snd_ctl_elem_value *ucontrol){        struct snd_azf3328 *chip = snd_kcontrol_chip(kcontrol);	struct azf3328_mixer_reg reg;	unsigned int oreg, nreg, val;        	snd_azf3328_mixer_reg_decode(&reg, kcontrol->private_value);	oreg = snd_azf3328_mixer_inw(chip, reg.reg);	val = oreg;	if (reg.reg == IDX_MIXER_REC_SELECT) {        	if (ucontrol->value.enumerated.item[0] > reg.enum_c - 1U ||            	ucontrol->value.enumerated.item[1] > reg.enum_c - 1U)                	return -EINVAL;        	val = (ucontrol->value.enumerated.item[0] << 8) |        	      (ucontrol->value.enumerated.item[1] << 0);	} else {        	if (ucontrol->value.enumerated.item[0] > reg.enum_c - 1U)                	return -EINVAL;		val &= ~((reg.enum_c - 1) << reg.lchan_shift);        	val |= (ucontrol->value.enumerated.item[0] << reg.lchan_shift);	}	snd_azf3328_mixer_outw(chip, reg.reg, val);	nreg = val;	snd_azf3328_dbgmixer("put_enum: %02x to %04x, oreg %04x\n", reg.reg, val, oreg);	return (nreg != oreg);}static struct snd_kcontrol_new snd_azf3328_mixer_controls[] __devinitdata = {	AZF3328_MIXER_SWITCH("Master Playback Switch", IDX_MIXER_PLAY_MASTER, 15, 1),	AZF3328_MIXER_VOL_STEREO("Master Playback Volume", IDX_MIXER_PLAY_MASTER, 0x1f, 1),	AZF3328_MIXER_SWITCH("Wave Playback Switch", IDX_MIXER_WAVEOUT, 15, 1),	AZF3328_MIXER_VOL_STEREO("Wave Playback Volume", IDX_MIXER_WAVEOUT, 0x1f, 1),	AZF3328_MIXER_SWITCH("Wave 3D Bypass Playback Switch", IDX_MIXER_ADVCTL2, 7, 1),	AZF3328_MIXER_SWITCH("FM Playback Switch", IDX_MIXER_FMSYNTH, 15, 1),	AZF3328_MIXER_VOL_STEREO("FM Playback Volume", IDX_MIXER_FMSYNTH, 0x1f, 1),	AZF3328_MIXER_SWITCH("CD Playback Switch", IDX_MIXER_CDAUDIO, 15, 1),	AZF3328_MIXER_VOL_STEREO("CD Playback Volume", IDX_MIXER_CDAUDIO, 0x1f, 1),	AZF3328_MIXER_SWITCH("Capture Switch", IDX_MIXER_REC_VOLUME, 15, 1),	AZF3328_MIXER_VOL_STEREO("Capture Volume", IDX_MIXER_REC_VOLUME, 0x0f, 0),	AZF3328_MIXER_ENUM("Capture Source", IDX_MIXER_REC_SELECT, 8, 0),	AZF3328_MIXER_SWITCH("Mic Playback Switch", IDX_MIXER_MIC, 15, 1),	AZF3328_MIXER_VOL_MONO("Mic Playback Volume", IDX_MIXER_MIC, 0x1f, 1),	AZF3328_MIXER_SWITCH("Mic Boost (+20dB)", IDX_MIXER_MIC, 6, 0),	AZF3328_MIXER_SWITCH("Line Playback Switch", IDX_MIXER_LINEIN, 15, 1),	AZF3328_MIXER_VOL_STEREO("Line Playback Volume", IDX_MIXER_LINEIN, 0x1f, 1),	AZF3328_MIXER_SWITCH("PC Speaker Playback Switch", IDX_MIXER_PCBEEP, 15, 1),	AZF3328_MIXER_VOL_SPECIAL("PC Speaker Playback Volume", IDX_MIXER_PCBEEP, 0x0f, 1, 1),	AZF3328_MIXER_SWITCH("Video Playback Switch", IDX_MIXER_VIDEO, 15, 1),	AZF3328_MIXER_VOL_STEREO("Video Playback Volume", IDX_MIXER_VIDEO, 0x1f, 1),	AZF3328_MIXER_SWITCH("Aux Playback Switch", IDX_MIXER_AUX, 15, 1),	AZF3328_MIXER_VOL_STEREO("Aux Playback Volume", IDX_MIXER_AUX, 0x1f, 1),	AZF3328_MIXER_SWITCH("Modem Playback Switch", IDX_MIXER_MODEMOUT, 15, 1),	AZF3328_MIXER_VOL_MONO("Modem Playback Volume", IDX_MIXER_MODEMOUT, 0x1f, 1),	AZF3328_MIXER_SWITCH("Modem Capture Switch", IDX_MIXER_MODEMIN, 15, 1),	AZF3328_MIXER_VOL_MONO("Modem Capture Volume", IDX_MIXER_MODEMIN, 0x1f, 1),	AZF3328_MIXER_ENUM("Mic Select", IDX_MIXER_ADVCTL2, 2, 8),	AZF3328_MIXER_ENUM("Mono Output Select", IDX_MIXER_ADVCTL2, 2, 9),	AZF3328_MIXER_ENUM("PCM Output Route", IDX_MIXER_ADVCTL2, 2, 15), /* PCM Out Path, place in front since it controls *both* 3D and Bass/Treble! */	AZF3328_MIXER_VOL_SPECIAL("Tone Control - Treble", IDX_MIXER_BASSTREBLE, 0x07, 1, 0),	AZF3328_MIXER_VOL_SPECIAL("Tone Control - Bass", IDX_MIXER_BASSTREBLE, 0x07, 9, 0),	AZF3328_MIXER_SWITCH("3D Control - Switch", IDX_MIXER_ADVCTL2, 13, 0),	AZF3328_MIXER_VOL_SPECIAL("3D Control - Width", IDX_MIXER_ADVCTL1, 0x07, 1, 0), /* "3D Width" */	AZF3328_MIXER_VOL_SPECIAL("3D Control - Depth", IDX_MIXER_ADVCTL1, 0x03, 8, 0), /* "Hifi 3D" */#if MIXER_TESTING	AZF3328_MIXER_SWITCH("0", IDX_MIXER_ADVCTL2, 0, 0),	AZF3328_MIXER_SWITCH("1", IDX_MIXER_ADVCTL2, 1, 0),	AZF3328_MIXER_SWITCH("2", IDX_MIXER_ADVCTL2, 2, 0),	AZF3328_MIXER_SWITCH("3", IDX_MIXER_ADVCTL2, 3, 0),	AZF3328_MIXER_SWITCH("4", IDX_MIXER_ADVCTL2, 4, 0),	AZF3328_MIXER_SWITCH("5", IDX_MIXER_ADVCTL2, 5, 0),	AZF3328_MIXER_SWITCH("6", IDX_MIXER_ADVCTL2, 6, 0),	AZF3328_MIXER_SWITCH("7", IDX_MIXER_ADVCTL2, 7, 0),	AZF3328_MIXER_SWITCH("8", IDX_MIXER_ADVCTL2, 8, 0),	AZF3328_MIXER_SWITCH("9", IDX_MIXER_ADVCTL2, 9, 0),	AZF3328_MIXER_SWITCH("10", IDX_MIXER_ADVCTL2, 10, 0),	AZF3328_MIXER_SWITCH("11", IDX_MIXER_ADVCTL2, 11, 0),	AZF3328_MIXER_SWITCH("12", IDX_MIXER_ADVCTL2, 12, 0),	AZF3328_MIXER_SWITCH("13", IDX_MIXER_ADVCTL2, 13, 0),	AZF3328_MIXER_SWITCH("14", IDX_MIXER_ADVCTL2, 14, 0),	AZF3328_MIXER_SWITCH("15", IDX_MIXER_ADVCTL2, 15, 0),#endif};static u16 __devinitdata snd_azf3328_init_values[][2] = {        { IDX_MIXER_PLAY_MASTER,	MIXER_MUTE_MASK|0x1f1f },        { IDX_MIXER_MODEMOUT,		MIXER_MUTE_MASK|0x1f1f },	{ IDX_MIXER_BASSTREBLE,		0x0000 },	{ IDX_MIXER_PCBEEP,		MIXER_MUTE_MASK|0x1f1f },	{ IDX_MIXER_MODEMIN,		MIXER_MUTE_MASK|0x1f1f },	{ IDX_MIXER_MIC,		MIXER_MUTE_MASK|0x001f },	{ IDX_MIXER_LINEIN,		MIXER_MUTE_MASK|0x1f1f },	{ IDX_MIXER_CDAUDIO,		MIXER_MUTE_MASK|0x1f1f },	{ IDX_MIXER_VIDEO,		MIXER_MUTE_MASK|0x1f1f },	{ IDX_MIXER_AUX,		MIXER_MUTE_MASK|0x1f1f },        { IDX_MIXER_WAVEOUT,		MIXER_MUTE_MASK|0x1f1f },        { IDX_MIXER_FMSYNTH,		MIXER_MUTE_MASK|0x1f1f },        { IDX_MIXER_REC_VOLUME,		MIXER_MUTE_MASK|0x0707 },};static int __devinitsnd_azf3328_mixer_new(struct snd_azf3328 *chip){	struct snd_card *card;	const struct snd_kcontrol_new *sw;	unsigned int idx;	int err;	snd_azf3328_dbgcallenter();	snd_assert(chip != NULL && chip->card != NULL, return -EINVAL);	card = chip->card;	/* mixer reset */	snd_azf3328_mixer_outw(chip, IDX_MIXER_RESET, 0x0000);	/* mute and zero volume channels */	for (idx = 0; idx < ARRAY_SIZE(snd_azf3328_init_values); idx++) {		snd_azf3328_mixer_outw(chip,			snd_azf3328_init_values[idx][0],			snd_azf3328_init_values[idx][1]);	}		/* add mixer controls */	sw = snd_azf3328_mixer_controls;	for (idx = 0; idx < ARRAY_SIZE(snd_azf3328_mixer_controls); idx++, sw++) {		if ((err = snd_ctl_add(chip->card, snd_ctl_new1(sw, chip))) < 0)			return err;	}	snd_component_add(card, "AZF3328 mixer");	strcpy(card->mixername, "AZF3328 mixer");	snd_azf3328_dbgcallleave();	return 0;}static intsnd_azf3328_hw_params(struct snd_pcm_substream *substream,				 struct snd_pcm_hw_params *hw_params){	int res;	snd_azf3328_dbgcallenter();	res = snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params));	snd_azf3328_dbgcallleave();	return res;}static intsnd_azf3328_hw_free(struct snd_pcm_substream *substream){	snd_azf3328_dbgcallenter();	snd_pcm_lib_free_pages(substream);	snd_azf3328_dbgcallleave();	return 0;}static voidsnd_azf3328_setfmt(struct snd_azf3328 *chip,			       unsigned int reg,			       unsigned int bitrate,			       unsigned int format_width,			       unsigned int channels){	u16 val = 0xff00;	unsigned long flags;	snd_azf3328_dbgcallenter();	switch (bitrate) {	case  4000: val |= SOUNDFORMAT_FREQ_SUSPECTED_4000; break;	case  4800: val |= SOUNDFORMAT_FREQ_SUSPECTED_4800; break;	case  5512: val |= SOUNDFORMAT_FREQ_5510; break; /* the AZF3328 names it "5510" for some strange reason */	case  6620: val |= SOUNDFORMAT_FREQ_6620; break;	case  8000: val |= SOUNDFORMAT_FREQ_8000; break;	case  9600: val |= SOUNDFORMAT_FREQ_9600; break;	case 11025: val |= SOUNDFORMAT_FREQ_11025; break;	case 13240: val |= SOUNDFORMAT_FREQ_SUSPECTED_13240; break;	case 16000: val |= SOUNDFORMAT_FREQ_16000; break;	case 22050: val |= SOUNDFORMAT_FREQ_22050; break;	case 32000: val |= SOUNDFORMAT_FREQ_32000; break;	case 44100: val |= SOUNDFORMAT_FREQ_44100; break;	case 48000: val |= SOUNDFORMAT_FREQ_48000; break;	case 66200: val |= SOUNDFORMAT_FREQ_SUSPECTED_66200; break;	default:		snd_printk(KERN_WARNING "unknown bitrate %d, assuming 44.1kHz!\n", bitrate);		val |= SOUNDFORMAT_FREQ_44100;		break;	}	/* val = 0xff07; 3m27.993s (65301Hz; -> 64000Hz???) hmm, 66120, 65967, 66123 */	/* val = 0xff09; 17m15.098s (13123,478Hz; -> 12000Hz???) hmm, 13237.2Hz? */	/* val = 0xff0a; 47m30.599s (4764,891Hz; -> 4800Hz???) yup, 4803Hz */	/* val = 0xff0c; 57m0.510s (4010,263Hz; -> 4000Hz???) yup, 4003Hz */	/* val = 0xff05; 5m11.556s (... -> 44100Hz) */	/* val = 0xff03; 10m21.529s (21872,463Hz; -> 22050Hz???) */	/* val = 0xff0f; 20m41.883s (10937,993Hz; -> 11025Hz???) */

⌨️ 快捷键说明

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