在Hisi3531环境中为wm8978芯片添加音量调节功能及测试

前言

  • Step1. 修改.ko驱动代码
  • Step2. 修改中间层 sample_common的代码 *
  • Step3. 修改应用程序sample_audio 的代码 *
  • 其他

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

你可能感兴趣的:(Linux,嵌入式,linux)