Hisi3531芯片公板设计,使用了tlv320aic31作为音频输出芯片。实际画板时硬件人员
使用了wm8978。
四年前,为了最快速地驱动芯片发声,对mpp\extdrv_hi3531\tlv320aic31中的
tlv_320aic31.ko
做了改造,主要是对soft_reset部分的代码进行了修改。将wm8978寄存器设置为一组固
定值。
本轮修改中,新需求要求添加播放声音时的音量调节功能。
通过检索wm8978的芯片手册,发现要设置的寄存器是:
0x0bH … bit0:7(0 == digital mute, 0xff = 0dB)
bit8(DACVU, write protect bit)
0x0cH … same as above;
为了完成这个修改,查看.ko的代码,最简便的方法是使用ioctl机制。
Step1. 修改.ko驱动代码
代码位置:mpp\extdrv_hi3531\tlv320aic31
我们修改了既有的ioctrl代码:
case LEFT_DAC_VOL_CTRL: //no break
{
adc_pga_dac_gain_ctrl.b16 = tlv320aic31_read(IIC_device_addr[chip_num], WM8978_LEFT_DAC_DIGITAL_VOLUME);
adc_pga_dac_gain_ctrl.bit.wb = audio_ctrl->if_mute_route;
adc_pga_dac_gain_ctrl.bit.input_vol_level_ctrl = audio_ctrl->input_level;
tlv320aic31_write(IIC_device_addr[chip_num],WM8978_LEFT_DAC_DIGITAL_VOLUME,adc_pga_dac_gain_ctrl.b16);
DPRINTK(0,"tlv320aic31(chip%d) left volumn:(%d - %d)", chip_num, audio_ctrl->if_mute_route, audio_ctrl->input_level);
}
break;
case RIGHT_DAC_VOL_CTRL:
{
adc_pga_dac_gain_ctrl.b16 = tlv320aic31_read(IIC_device_addr[chip_num], WM8978_RIGHT_DAC_DIGITAL_VOLUME);
adc_pga_dac_gain_ctrl.bit.wb = audio_ctrl->if_mute_route;
adc_pga_dac_gain_ctrl.bit.input_vol_level_ctrl = audio_ctrl->input_level;
tlv320aic31_write(IIC_device_addr[chip_num],WM8978_RIGHT_DAC_DIGITAL_VOLUME,adc_pga_dac_gain_ctrl.b16);
DPRINTK(0,"tlv320aic31(chip%d) right volumn:(%d - %d)", chip_num, audio_ctrl->if_mute_route, audio_ctrl->input_level);
}
break;
注意:
原有的增益控制结构
Adc_Pga_Dac_Gain_Ctrl adc_pga_dac_gain_ctrl;
是8个Bits.wm8978中使用的是9Bits结构。
为此,我修改了这个结构体的定义。这个结构体仅用于.ko工程
同样的,我也修改了ioctl中用于传递音量的结构体,将其由7Bits => 8Bits.
此时,注意,因为这个结构体会影响上位机的代码;编译时要留神,要进行全编译。
Step2. 修改中间层 sample_common的代码 *
注意,因为我们已经修改了mpp的基础芯片,
原有的代码位置:mpp\最好整体备份一下,然后创建一个同级目录。
common中有部分与驱动接触的代码要改。
我们在sample_comm_audio.c中增加了两个函数:
HI_S32 SAMPLE_Wm8978_VolumeCtrl(int volLeft, int volRight)
{
Audio_Ctrl audio_ctrl;
int s_fdTlv = -1;
s_fdTlv = open(TLV320_FILE,O_RDWR);
if (s_fdTlv < 0)
{
printf("can't open tlv320,%s\n", TLV320_FILE);
return -1;
}
audio_ctrl.chip_num = 0;
/*set volume control of left and right DAC */
audio_ctrl.if_mute_route = 1;
audio_ctrl.input_level = volLeft;
ioctl(s_fdTlv,LEFT_DAC_VOL_CTRL,&audio_ctrl);
ioctl(s_fdTlv,RIGHT_DAC_VOL_CTRL, &audio_ctrl);
close(s_fdTlv);
printf("tlv320 volumn set to ...(%d - %d)\n", volLeft, volRight);
return 0;
}
HI_S32 SAMPLE_COMM_AUDIO_VolumeCtrl(int volLeft, int volRight)
{
return SAMPLE_Wm8978_VolumeCtrl(volLeft, volRight);
}
然后将SAMPLE_COMM_AUDIO_VolumeCtrl加入头文件。sample_comm.h
硬件部分是支持左右声道分别调节的,实际输出时,我们同时设置两个输出通道。
Step3. 修改应用程序sample_audio 的代码 *
定义全局变量:giAudioVolumn来存储音量设置:
注意,WM8978的音量衰减速度很快,建议默认值设置在250(max 255);
然后修改file -> ai ->ao的那个实例,添加如下代码:
在打开音频文件前,添加音量调节。
//....
printf("volume adjust to: %d\n", giAudioVolume);
SAMPLE_COMM_AUDIO_VolumeCtrl(giAudioVolume, giAudioVolume);
pfd = SAMPLE_AUDIO_OpenAdecFile(AdChn, gs_enPayloadType);
//....
为了能够在界面中调节音量,为主菜单添加一个额外的menu item:
case '5':
{
printf("please input volume(0~255):");
scanf("%d", &giAudioVolume);
s32Ret = SAMPLE_COMM_AUDIO_VolumeCtrl(giAudioVolume, giAudioVolume);
break;
}
音量调节部分和最终的文件音频输出共享同一个音量调节变量:giAudioVolume.
至此,修改完毕。
其他
Hi3531的播放的音频文件,推荐使用.adpcm格式,这个文件可以由RAW格式的音频文件
,使用SDK中\Hi3511_VOICESDK_V1.0.0.4\HisiVoiceEngine\src中的源码生成的.exe
文件,将.RAW格式的音频文件encode得到。
音频文件 =>RAW格式的转换工具有很多,我使用的是Moo0 AudioConverter 1.32