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

📄 s3c24xx-uda1341.c

📁 扬创2440平台上的ALSA音频驱动程序( for Linux-2.6.26.5 )。驱动使用说明和ALSA Lib的编译过程都在压缩包内
💻 C
📖 第 1 页 / 共 5 页
字号:
	case CMD_RESET:
		ret = snd_uda1341_update_bits(chip, data0_2, 1, 2, 1, flush);	// MUTE
		ret = snd_uda1341_update_bits(chip, stat0, 1, 6, 1, flush);	// RESET
		ret = snd_uda1341_update_bits(chip, stat0, 1, 6, 0, flush);	// RESTORE
		uda->cfg[CMD_RESET]=0;
		break;
	case CMD_FS:
		ret = snd_uda1341_update_bits(chip, stat0, 3, 4, value, flush);
		break;
	case CMD_FORMAT:
		ret = snd_uda1341_update_bits(chip, stat0, 7, 1, value, flush);
		break;
	case CMD_OGAIN:
		ret = snd_uda1341_update_bits(chip, stat1, 1, 6, value, flush);
		break;
	case CMD_IGAIN:
		ret = snd_uda1341_update_bits(chip, stat1, 1, 5, value, flush);
		break;
	case CMD_DAC:
		ret = snd_uda1341_update_bits(chip, stat1, 1, 0, value, flush);
		break;
	case CMD_ADC:
		ret = snd_uda1341_update_bits(chip, stat1, 1, 1, value, flush);
		break;
	case CMD_VOLUME:
		ret = snd_uda1341_update_bits(chip, data0_0, 63, 0, value, flush);
		break;
	case CMD_BASS:
		ret = snd_uda1341_update_bits(chip, data0_1, 15, 2, value, flush);
		break;
	case CMD_TREBBLE:
		ret = snd_uda1341_update_bits(chip, data0_1, 3, 0, value, flush);
		break;
	case CMD_PEAK:
		ret = snd_uda1341_update_bits(chip, data0_2, 1, 5, value, flush);
		break;
	case CMD_DEEMP:
		ret = snd_uda1341_update_bits(chip, data0_2, 3, 3, value, flush);
		break;
	case CMD_MUTE:
		ret = snd_uda1341_update_bits(chip, data0_2, 1, 2, value, flush);
		break;
	case CMD_FILTER:
		ret = snd_uda1341_update_bits(chip, data0_2, 3, 0, value, flush);
		break;
	case CMD_CH1:
		ret = snd_uda1341_update_bits(chip, ext0, 31, 0, value, flush);
		break;
	case CMD_CH2:
		ret = snd_uda1341_update_bits(chip, ext1, 31, 0, value, flush);
		break;
	case CMD_MIC:
		ret = snd_uda1341_update_bits(chip, ext2, 7, 2, value, flush);
		break;
	case CMD_MIXER:
		ret = snd_uda1341_update_bits(chip, ext2, 3, 0, value, flush);
		break;
	case CMD_AGC:
		ret = snd_uda1341_update_bits(chip, ext4, 1, 4, value, flush);
		break;
	case CMD_IG:
		ret = snd_uda1341_update_bits(chip, ext4, 3, 0, value & 0x3, flush);
		ret = snd_uda1341_update_bits(chip, ext5, 31, 0, value >> 2, flush);
		break;
	case CMD_AGC_TIME:
		ret = snd_uda1341_update_bits(chip, ext6, 7, 2, value, flush);
		break;
	case CMD_AGC_LEVEL:
		ret = snd_uda1341_update_bits(chip, ext6, 3, 0, value, flush);
		break;
#ifdef CONFIG_PM		
	case CMD_SUSPEND:
		for (reg = stat0; reg < uda1341_reg_last; reg++)
			uda->suspend_regs[reg] = uda->regs[reg];
		for (reg = 0; reg < CMD_LAST; reg++)
			uda->suspend_cfg[reg] = uda->cfg[reg];
		break;
	case CMD_RESUME:
		for (reg = stat0; reg < uda1341_reg_last; reg++)
			snd_uda1341_codec_write(chip, reg, uda->suspend_regs[reg]);
		for (reg = 0; reg < CMD_LAST; reg++)
			uda->cfg[reg] = uda->suspend_cfg[reg];
		break;
#endif
	default:
		ret = -EINVAL;
		break;
	}
                
	if (!uda->active)
		printk(KERN_ERR "UDA1341 codec not active!\n");                
	return ret;
}


/*
 * Mixer Control Settings
 */
#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(struct snd_kcontrol *kcontrol,
				   struct snd_ctl_elem_info *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(struct snd_kcontrol *kcontrol,
				  struct snd_ctl_elem_value *ucontrol)
{
	struct s3c24xx_uda1341 *chip = snd_kcontrol_chip(kcontrol);
	struct uda1341 *uda = chip -> chip_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(struct snd_kcontrol *kcontrol,
				  struct snd_ctl_elem_value *ucontrol)
{
	struct s3c24xx_uda1341 *chip = snd_kcontrol_chip( kcontrol );
	struct uda1341 *uda = chip -> chip_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(chip, 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(struct snd_kcontrol *kcontrol,
				 struct snd_ctl_elem_info *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(struct snd_kcontrol *kcontrol,
				struct snd_ctl_elem_value *ucontrol)
{
	struct s3c24xx_uda1341 *chip = snd_kcontrol_chip(kcontrol);
	struct uda1341 *uda = chip -> chip_data;
	int where = kcontrol->private_value & 31;        
        
	ucontrol->value.enumerated.item[0] = uda->cfg[where];	
	return 0;
}

static int snd_uda1341_put_enum(struct snd_kcontrol *kcontrol,
				struct snd_ctl_elem_value *ucontrol)
{
	struct s3c24xx_uda1341 *chip = snd_kcontrol_chip(kcontrol);
	struct uda1341 *uda = chip -> chip_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(chip, 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(struct snd_kcontrol *kcontrol,
				  struct snd_ctl_elem_info *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(struct snd_kcontrol *kcontrol,
				 struct snd_ctl_elem_value *ucontrol)
{
	struct s3c24xx_uda1341 *chip = snd_kcontrol_chip(kcontrol);
	struct uda1341 *uda = chip -> chip_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(struct snd_kcontrol *kcontrol,
				 struct snd_ctl_elem_value *ucontrol)
{
	struct s3c24xx_uda1341 *chip = snd_kcontrol_chip(kcontrol);
	struct uda1341 *uda = chip -> chip_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(chip, reg_1, mask_1, shift_1, val1, FLUSH);
	return snd_uda1341_update_bits(chip, reg_2, mask_2, shift_2, val2, FLUSH);
}




static struct snd_kcontrol_new 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),
};

int __devinit uda1341_chip_init( struct s3c24xx_uda1341 *chip )
{
	struct uda1341 *uda;

	uda = kzalloc( sizeof( struct uda1341 ), GFP_KERNEL );
	if ( !uda )
	{
		return -ENOMEM;
	}

	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 );

	chip -> chip_data = uda;

	uda -> active = 1;

	/*
	 * Initialize default configurations
	 */

	snd_uda1341_cfg_write(chip, CMD_RESET, 0, REGS_ONLY);
	snd_uda1341_cfg_write(chip, CMD_MUTE, OFF, REGS_ONLY);  // default value after reset
	snd_uda1341_cfg_write(chip, CMD_VOLUME, 20, FLUSH);     // default 0dB after reset
	snd_uda1341_cfg_write(chip, CMD_BASS, 0, REGS_ONLY);    // default value after reset
	snd_uda1341_cfg_write(chip, CMD_TREBBLE, 0, REGS_ONLY); // default value after reset
	snd_uda1341_cfg_write(chip, CMD_IGAIN, ON, FLUSH);      // default off after reset
	snd_uda1341_cfg_write(chip, CMD_OGAIN, ON, FLUSH);      // default off after reset
	snd_uda1341_cfg_write(chip, CMD_CH1, 31, FLUSH);        // default value after reset
	snd_uda1341_cfg_write(chip, CMD_CH2, 4, FLUSH);         // default value after reset
	snd_uda1341_cfg_write(chip, CMD_MIC, 4, FLUSH);         // default 0dB after reset
	snd_uda1341_cfg_write(chip, CMD_AGC_LEVEL, 0, FLUSH);   // default value after reset
	snd_uda1341_cfg_write(chip, CMD_AGC_TIME, 0, FLUSH);    // default value after reset
	snd_uda1341_cfg_write(chip, CMD_AGC, OFF, FLUSH);       // default value after reset
	snd_uda1341_cfg_write(chip, CMD_DAC, ON, FLUSH);	// ??? default value after reset
	snd_uda1341_cfg_write(chip, CMD_ADC, ON, FLUSH);	// ??? default value after reset
	snd_uda1341_cfg_write(chip, CMD_PEAK, AFTER, REGS_ONLY);// default value after reset
	snd_uda1341_cfg_write(chip, CMD_DEEMP, NONE, REGS_ONLY);// default value after reset
	snd_uda1341_cfg_write(chip, CMD_FILTER, MAX, FLUSH);    // defaul flat after reset
	snd_uda1341_cfg_write(chip, CMD_MIXER, MIXER, FLUSH);   // default doub.dif.mode          

	return 0;
}

int __devinit snd_chip_uda1341_mixer_new( struct snd_card *card, struct s3c24xx_uda1341 *chip )
{
	int idx, err;

	uda1341_chip_init( chip );

	for ( idx = 0; idx < ARRAY_SIZE( snd_uda1341_controls ); idx++ )
	{
		if ( ( err = snd_ctl_add( card, snd_ctl_new1( &snd_uda1341_controls[ idx ], chip ) ) ) < 0 )
		{
			s3c24xx_uda1341_free( chip );

			return err;
		}
	}

	strcpy( card -> mixername, "UDA1341TS Mixer" );

	return 0;

}

#else
static int __devinit snd_chip_uda1341_mixer_new( struct snd_card *card, 
							struct s3c24xx_uda1341 *chip)
{
	/*
	 * Anything more to do???
	 */

	strcpy( card -> mixername, "UDA1341TS Mixer" );

	return 0;
}
#endif /* MIXER_EN */

/* Proc interface */
#ifdef CONFIG_PROC_FS

static const char *format_names[] = {
	"I2S-bus",
	"LSB 16bits",
	"LSB 18bits",
	"LSB 20bits",
	"MSB",
	"in LSB 16bits/out MSB",
	"in LSB 18bits/out MSB",
	"in LSB 20bits/out MSB",        
};

static const char *fs_names[] = {
	"512*fs",
	"384*fs",
	"256*fs",
	"Unused - bad value!",
};

static const char* bass_values[][16] = {
	{"0 dB", "0 dB", "0 dB", "0 dB", "0 dB", "0 dB", "0 dB", "0 dB", "0 dB", "0 dB", "0 dB",
	 "0 dB", "0 dB", "0 dB", "0 dB", "undefined", }, //flat
	{"0 dB", "2 dB", "4 dB", "6 dB", "8 dB", "10 dB", "12 dB", "14 dB", "16 dB", "18 dB", "18 dB",
	 "18 dB", "18 dB", "18 dB", "18 dB", "undefined",}, // min
	{"0 dB", "2 dB", "4 dB", "6 dB", "8 dB", "10 dB", "12 dB", "14 dB", "16 dB", "18 dB", "18 dB",
	 "18 dB", "18 dB", "18 dB", "18 dB", "undefined",}, // min
	{"0 dB", "2 dB", "4 dB", "6 dB", "8 dB", "10 dB", "12 dB", "14 dB", "16 dB", "18 dB", "20 dB",
	 "22 dB", "24 dB", "24 dB", "24 dB", "undefined",}, // max
};

static const char *mic_sens_value[] = {
	"-3 dB", "0 dB", "3 dB", "9 dB", "15 dB", "21 dB", "27 dB", "not used",
};

static const unsigned short AGC_atime[] = {
	11, 16, 11, 16, 21, 11, 16, 21,
};

static const unsigned short AGC_dtime[] = {
	100, 100, 200, 200, 200, 400, 400, 400,
};

⌨️ 快捷键说明

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