vi s3c-wm8976.c
在s3c2410-uda1341.c修改驱动,修改硬件部分的控制接口,I2S部分通用不用修改。
1、增加写寄存器操作函数wm8976_write_reg
static void wm8976_write_reg(unsigned char reg, unsigned int data)
{
int i;
unsigned long flags;
unsigned short val = (reg << 9) | (data & 0x1ff);
s3c2410_gpio_setpin(S3C2410_GPB2,1);
s3c2410_gpio_setpin(S3C2410_GPB3,1);
s3c2410_gpio_setpin(S3C2410_GPB4,1);
local_irq_save(flags);
for (i = 0; i < 16; i++){
if (val & (1<<15))
{
s3c2410_gpio_setpin(S3C2410_GPB4,0);
s3c2410_gpio_setpin(S3C2410_GPB3,1);
udelay(1);
s3c2410_gpio_setpin(S3C2410_GPB4,1);
}
else
{
s3c2410_gpio_setpin(S3C2410_GPB4,0);
s3c2410_gpio_setpin(S3C2410_GPB3,0);
udelay(1);
s3c2410_gpio_setpin(S3C2410_GPB4,1);
}
val = val << 1;
}
s3c2410_gpio_setpin(S3C2410_GPB2,0);
udelay(1);
s3c2410_gpio_setpin(S3C2410_GPB2,1);
s3c2410_gpio_setpin(S3C2410_GPB3,1);
s3c2410_gpio_setpin(S3C2410_GPB4,1);
local_irq_restore(flags);
}
2、修改控制器初始化函数init_wm8976
static void init_wm8976(void)
{
uda1341_volume = 57;
uda1341_boost = 0;
wm8976_write_reg(0, 0);
wm8976_write_reg(0x3, 0x6f);
wm8976_write_reg(0x1, 0x1f);
wm8976_write_reg(0x2, 0x185);
wm8976_write_reg(0x6, 0x0);
wm8976_write_reg(0x4, 0x10);
wm8976_write_reg(0x2B,0x10);
wm8976_write_reg(0x9, 0x50);
wm8976_write_reg(0xD, 0x21);
wm8976_write_reg(0x7, 0x01);
}
3、修改音量uda1341_volume相关设置smdk2410_mixer_ioctl
static int smdk2410_mixer_ioctl(struct inode *inode, struct file *file,
unsigned int cmd, unsigned long arg)
{
int ret;
long val = 0;
switch (cmd) {
case SOUND_MIXER_INFO:
{
mixer_info info;
strncpy(info.id, "UDA1341", sizeof(info.id));
strncpy(info.name,"Philips UDA1341", sizeof(info.name));
info.modify_counter = audio_mix_modcnt;
return copy_to_user((void *)arg, &info, sizeof(info));
}
case SOUND_OLD_MIXER_INFO:
{
_old_mixer_info info;
strncpy(info.id, "UDA1341", sizeof(info.id));
strncpy(info.name,"Philips UDA1341", sizeof(info.name));
return copy_to_user((void *)arg, &info, sizeof(info));
}
case SOUND_MIXER_READ_STEREODEVS:
return put_user(0, (long *) arg);
case SOUND_MIXER_READ_CAPS:
val = SOUND_CAP_EXCL_INPUT;
return put_user(val, (long *) arg);
case SOUND_MIXER_WRITE_VOLUME:
ret = get_user(val, (long *) arg);
if (ret)
return ret;
uda1341_volume = (((val & 0xff) + 1) * 63) / 100;
wm8976_write_reg(52, (1<<8)|uda1341_volume);
wm8976_write_reg(53, (1<<8)|uda1341_volume);
//uda1341_l3_address(UDA1341_REG_DATA0);
//uda1341_l3_data(uda1341_volume);
break;
case SOUND_MIXER_READ_VOLUME:
val = (uda1341_volume * 100) / 63;
return put_user(val, (long *) arg);
case SOUND_MIXER_READ_IGAIN:
val = ((31- mixer_igain) * 100) / 31;
return put_user(val, (int *) arg);
case SOUND_MIXER_WRITE_IGAIN:
ret = get_user(val, (int *) arg);
if (ret)
return ret;
mixer_igain = 31 - (val * 31 / 100);
/* use mixer gain channel 1*/
//uda1341_l3_address(UDA1341_REG_DATA0);
//uda1341_l3_data(EXTADDR(EXT0));
//uda1341_l3_data(EXTDATA(EXT0_CH1_GAIN(mixer_igain)));
break;
default:
DPRINTK("mixer ioctl %u unknown\n", cmd);
return -ENOSYS;
}
audio_mix_modcnt++;
return 0;
}
测试驱动:确认内核已经配置了I2S驱动,同时将s3c-wm8976.c编译到uImage里。
# ls -l /dev/dsp /dev/mixer
crw-rw---- 1 0 0 14, 3 May 31 17:45 /dev/dsp
crw-rw---- 1 0 0 14, 0 May 31 17:45 /dev/mixer
# cat Alarm01.wav > /dev/dsp
s3c2410-uda1341-superlp: audio_set_dsp_speed:44100 prescaler:66
# cat Alarm01.wav > /dev/dsp
s3c2410-uda1341-superlp: audio_set_dsp_speed:44100 prescaler:66
# cat /dev/dsp > good.bin
s3c2410-uda1341-superlp: audio_set_dsp_speed:44100 prescaler:66
# ls
Alarm01.wav good.bin
# cat good.bin > /dev/dsp
s3c2410-uda1341-superlp: audio_set_dsp_speed:44100 prescaler:66