前言
目前一直在使用海思的hi3531dv100芯片,声卡已经调过tlv320aic3254和tlv320aix3101
官方SDK中 mpp/extdrv中提供了一个文件夹tlv320aic31,但是部分设置并不是很完美,因此根据自己硬件的不同,做了部分调整
下载连接
https://download.csdn.net/download/whitefish520/13010312
硬件连接
左边是I2S和I2C
右边是输入和输出
声卡驱动
#include <linux/kernel.h>
#include <linux/version.h>
#include <linux/module.h>
#include <linux/types.h>
#include <linux/errno.h>
#include <linux/fcntl.h>
#include <linux/mm.h>
#include <linux/proc_fs.h>
#include <linux/fs.h>
#include <linux/slab.h>
#include <linux/init.h>
#include <asm/uaccess.h>
#include <asm/io.h>
#ifndef CONFIG_HISI_SNAPSHOT_BOOT
#include <linux/miscdevice.h>
#endif
#include <linux/delay.h>
#include <linux/proc_fs.h>
#include <linux/poll.h>
#include <asm/bitops.h>
#include <asm/uaccess.h>
#include <asm/irq.h>
#include <linux/moduleparam.h>
#include <linux/ioport.h>
#include <linux/interrupt.h>
#include <linux/reboot.h>
#include <linux/notifier.h>
#include <linux/i2c.h>
#include <linux/i2c-dev.h>
#include "tlv320aic31.h"
#include "tlv320aic31_def.h"
#ifdef CONFIG_HISI_SNAPSHOT_BOOT
#include "himedia.h"
#endif
#define CHIP_NUM 1
#define DEV_NAME "tlv320aic31"
#define DEBUG_LEVEL 1
#define DPRINTK(level,fmt,args...) do{ if(level < DEBUG_LEVEL)\
printk(KERN_INFO "%s [%s ,%d]: " fmt "\n",DEV_NAME,__FUNCTION__,__LINE__,##args);\
}while(0)
unsigned int IIC_device_addr
[CHIP_NUM
] = {0x30};
static struct i2c_board_info hi_info
=
{
I2C_BOARD_INFO("tlv320aic31", 0x30),
};
static struct i2c_client
* tlv_client
;
static unsigned int open_cnt
= 0;
static int chip_count
= 1;
#ifdef CONFIG_HISI_SNAPSHOT_BOOT
static struct himedia_device s_stTlv320aic31Device
;
#endif
static int tlv320aic31_device_init(unsigned int num
);
int tlv320aic31_write(unsigned char chip_addr
, unsigned char reg_addr
, unsigned char value
)
{
int ret
;
unsigned char buf
[2];
struct i2c_client
* client
= tlv_client
;
buf
[0] = reg_addr
;
buf
[1] = value
;
ret
= i2c_master_send(client
, buf
, 2);
return ret
;
}
int tlv320aic31_read(unsigned char chip_addr
, unsigned char reg_addr
)
{
int ret_data
= 0xFF;
int ret
;
struct i2c_client
* client
= tlv_client
;
unsigned char buf
[2];
buf
[0] = reg_addr
;
ret
= i2c_master_recv(client
, buf
, 1);
if (ret
>= 0)
{
ret_data
= buf
[0];
}
return ret_data
;
}
void tlv320aic31_reg_dump(unsigned int reg_num
)
{
unsigned int i
= 0;
for (i
= 0; i
< reg_num
; i
++)
{
printk("reg%03d = 0x%02x | ", i
, tlv320aic31_read(IIC_device_addr
[0], i
));
if ((i
+ 1) % 8 == 0)
{
printk("\n");
}
}
printk("\n");
}
void soft_reset(unsigned int chip_num
)
{
tlv320aic31_write(IIC_device_addr
[chip_num
], 1,0x80);
msleep(10);
tlv320aic31_write(IIC_device_addr
[chip_num
], 2, 0x00);
tlv320aic31_write(IIC_device_addr
[chip_num
], 3, 0x81);
tlv320aic31_write(IIC_device_addr
[chip_num
], 4, 0x20);
tlv320aic31_write(IIC_device_addr
[chip_num
], 5, 0x00);
tlv320aic31_write(IIC_device_addr
[chip_num
], 6, 0x00);
tlv320aic31_write(IIC_device_addr
[chip_num
], 7, 0x0a);
tlv320aic31_write(IIC_device_addr
[chip_num
], 8, 0x00);
tlv320aic31_write(IIC_device_addr
[chip_num
], 9, 0x00);
tlv320aic31_write(IIC_device_addr
[chip_num
], 10, 0x00);
tlv320aic31_write(IIC_device_addr
[chip_num
], 12, 0x50);
tlv320aic31_write(IIC_device_addr
[chip_num
], 14, 0x00);
tlv320aic31_write(IIC_device_addr
[chip_num
], 15, 0x00);
tlv320aic31_write(IIC_device_addr
[chip_num
], 16, 0x00);
tlv320aic31_write(IIC_device_addr
[chip_num
], 17, 0x0f);
tlv320aic31_write(IIC_device_addr
[chip_num
], 18, 0xf0);
tlv320aic31_write(IIC_device_addr
[chip_num
], 19, 0x04);
tlv320aic31_write(IIC_device_addr
[chip_num
], 21, 0x78);
tlv320aic31_write(IIC_device_addr
[chip_num
], 22, 0x04);
tlv320aic31_write(IIC_device_addr
[chip_num
], 24, 0x78);
tlv320aic31_write(IIC_device_addr
[chip_num
], 37, 0xe0);
tlv320aic31_write(IIC_device_addr
[chip_num
], 38, 0x10);
tlv320aic31_write(IIC_device_addr
[chip_num
], 41, 0x00);
tlv320aic31_write(IIC_device_addr
[chip_num
], 46, 0x00);
tlv320aic31_write(IIC_device_addr
[chip_num
], 47, 0x80);
tlv320aic31_write(IIC_device_addr
[chip_num
], 49, 0x00);
tlv320aic31_write(IIC_device_addr
[chip_num
], 50, 0x00);
tlv320aic31_write(IIC_device_addr
[chip_num
], 51, 0x0f);
tlv320aic31_write(IIC_device_addr
[chip_num
], 53, 0x00);
tlv320aic31_write(IIC_device_addr
[chip_num
], 54, 0x80);
tlv320aic31_write(IIC_device_addr
[chip_num
], 56, 0x00);
tlv320aic31_write(IIC_device_addr
[chip_num
], 57, 0x00);
tlv320aic31_write(IIC_device_addr
[chip_num
], 58, 0x0f);
tlv320aic31_write(IIC_device_addr
[chip_num
], 60, 0x00);
tlv320aic31_write(IIC_device_addr
[chip_num
], 61, 0x80);
tlv320aic31_write(IIC_device_addr
[chip_num
], 63, 0x00);
tlv320aic31_write(IIC_device_addr
[chip_num
], 64, 0x00);
tlv320aic31_write(IIC_device_addr
[chip_num
], 65, 0x0f);
tlv320aic31_write(IIC_device_addr
[chip_num
], 67, 0x00);
tlv320aic31_write(IIC_device_addr
[chip_num
], 68, 0x80);
tlv320aic31_write(IIC_device_addr
[chip_num
], 70, 0x00);
tlv320aic31_write(IIC_device_addr
[chip_num
], 71, 0x00);
tlv320aic31_write(IIC_device_addr
[chip_num
], 72, 0x0f);
tlv320aic31_write(IIC_device_addr
[chip_num
], 43, 0x00);
tlv320aic31_write(IIC_device_addr
[chip_num
], 44, 0x00);
}
static int tlv320aic31_open(struct inode
* inode
, struct file
* file
)
{
if (0 == open_cnt
++)
{
return 0;
}
return -1 ;
}
static int tlv320aic31_close(struct inode
* inode
, struct file
* file
)
{
open_cnt
--;
return 0;
}
static long tlv320aic31_ioctl(struct file
* file
, unsigned int cmd
, unsigned long arg
)
{
unsigned int __user
* argp
= (unsigned int __user
*)arg
;
unsigned int chip_num
;
Audio_Ctrl temp
;
Audio_Ctrl
* audio_ctrl
;
Codec_Datapath_Setup_Ctrl codec_datapath_setup_ctrl
;
DAC_OUTPUT_SWIT_CTRL dac_output_swit_ctrl
;
DAC_POWER_CTRL dac_power_ctrl
;
In1_Adc_Ctrl in1_adc_ctrl
;
In2_Adc_Ctrl_Sample in2_adc_ctrl_sample
;
Adc_Pga_Dac_Gain_Ctrl adc_pga_dac_gain_ctrl
;
Line_Hpcom_Out_Ctrl line_hpcom_out_ctrl
;
Serial_Int_Ctrl serial_int_ctrl
;
Serial_Data_Offset_Ctrl serial_data_offset_ctrl
;
Ctrl_Mode ctrl_mode
;
if (argp
!= NULL)
{
if (copy_from_user(&temp
, argp
, sizeof(Audio_Ctrl
)))
{
return -EFAULT
;
}
}
audio_ctrl
= (Audio_Ctrl
*)(&temp
);
chip_num
= audio_ctrl
->chip_num
;
switch (cmd
)
{
case IN2LR_2_LEFT_ADC_CTRL
:
in2_adc_ctrl_sample
.b8
= tlv320aic31_read(IIC_device_addr
[chip_num
], 17);
in2_adc_ctrl_sample
.bit
.in2l_adc_input_level_sample
= audio_ctrl
->input_level
;
tlv320aic31_write(IIC_device_addr
[chip_num
], 17, in2_adc_ctrl_sample
.b8
);
break;
case IN2LR_2_RIGTH_ADC_CTRL
:
in2_adc_ctrl_sample
.b8
= tlv320aic31_read(IIC_device_addr
[chip_num
], 18);
in2_adc_ctrl_sample
.bit
.in2r_adc_input_level_sample
= audio_ctrl
->input_level
;
tlv320aic31_write(IIC_device_addr
[chip_num
], 18, in2_adc_ctrl_sample
.b8
);
break;
case IN1L_2_LEFT_ADC_CTRL
:
in1_adc_ctrl
.b8
= tlv320aic31_read(IIC_device_addr
[chip_num
], 19);
in1_adc_ctrl
.bit
.in1_adc_input_level
= audio_ctrl
->input_level
;
in1_adc_ctrl
.bit
.adc_ch_power_ctrl
= audio_ctrl
->if_powerup
;
tlv320aic31_write(IIC_device_addr
[chip_num
], 19, in1_adc_ctrl
.b8
);
break;
case IN1R_2_RIGHT_ADC_CTRL
:
in1_adc_ctrl
.b8
= tlv320aic31_read(IIC_device_addr
[chip_num
], 22);
in1_adc_ctrl
.bit
.in1_adc_input_level
= audio_ctrl
->input_level
;
in1_adc_ctrl
.bit
.adc_ch_power_ctrl
= audio_ctrl
->if_powerup
;
tlv320aic31_write(IIC_device_addr
[chip_num
], 22, in1_adc_ctrl
.b8
);
break;
case PGAL_2_HPLOUT_VOL_CTRL
:
adc_pga_dac_gain_ctrl
.b8
= tlv320aic31_read(IIC_device_addr
[chip_num
], 46);
adc_pga_dac_gain_ctrl
.bit
.if_mute_route
= 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
], 46, adc_pga_dac_gain_ctrl
.b8
);
break;
case DACL1_2_HPLOUT_VOL_CTRL
:
adc_pga_dac_gain_ctrl
.b8
= tlv320aic31_read(IIC_device_addr
[chip_num
], 47);
adc_pga_dac_gain_ctrl
.bit
.if_mute_route
= 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
], 47, adc_pga_dac_gain_ctrl
.b8
);
break;
case HPLOUT_OUTPUT_LEVEL_CTRL
:
line_hpcom_out_ctrl
.b8
= tlv320aic31_read(IIC_device_addr
[chip_num
], 51);
line_hpcom_out_ctrl
.bit
.if_mute
= audio_ctrl
->if_mute_route
;
line_hpcom_out_ctrl
.bit
.output_level
= audio_ctrl
->input_level
;
line_hpcom_out_ctrl
.bit
.power_status
= audio_ctrl
->if_powerup
;
tlv320aic31_write(IIC_device_addr
[chip_num
], 51, line_hpcom_out_ctrl
.b8
);
break;
case PGAL_2_HPLCOM_VOL_CTRL
:
adc_pga_dac_gain_ctrl
.b8
= tlv320aic31_read(IIC_device_addr
[chip_num
], 53);
adc_pga_dac_gain_ctrl
.bit
.if_mute_route
= 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
], 53, adc_pga_dac_gain_ctrl
.b8
);
break;
case DACL1_2_HPLCOM_VOL_CTRL
:
adc_pga_dac_gain_ctrl
.b8
= tlv320aic31_read(IIC_device_addr
[chip_num
], 54);
adc_pga_dac_gain_ctrl
.bit
.if_mute_route
= 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
], 54, adc_pga_dac_gain_ctrl
.b8
);
break;
case HPLCOM_OUTPUT_LEVEL_CTRL
:
line_hpcom_out_ctrl
.b8
= tlv320aic31_read(IIC_device_addr
[chip_num
], 58);
line_hpcom_out_ctrl
.bit
.if_mute
= audio_ctrl
->if_mute_route
;
line_hpcom_out_ctrl
.bit
.output_level
= audio_ctrl
->input_level
;
tlv320aic31_write(IIC_device_addr
[chip_num
], 58, line_hpcom_out_ctrl
.b8
);
break;
case PGAR_2_HPROUT_VOL_CTRL
:
adc_pga_dac_gain_ctrl
.b8
= tlv320aic31_read(IIC_device_addr
[chip_num
], 63);
adc_pga_dac_gain_ctrl
.bit
.if_mute_route
= 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
], 63, adc_pga_dac_gain_ctrl
.b8
);
break;
case DACR1_2_HPROUT_VOL_CTRL
:
adc_pga_dac_gain_ctrl
.b8
= tlv320aic31_read(IIC_device_addr
[chip_num
], 64);
adc_pga_dac_gain_ctrl
.bit
.if_mute_route
= 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
], 64, adc_pga_dac_gain_ctrl
.b8
);
break;
case HPROUT_OUTPUT_LEVEL_CTRL
:
line_hpcom_out_ctrl
.b8
= tlv320aic31_read(IIC_device_addr
[chip_num
], 65);
line_hpcom_out_ctrl
.bit
.if_mute
= audio_ctrl
->if_mute_route
;
line_hpcom_out_ctrl
.bit
.output_level
= audio_ctrl
->input_level
;
line_hpcom_out_ctrl
.bit
.power_status
= audio_ctrl
->if_powerup
;
tlv320aic31_write(IIC_device_addr
[chip_num
], 65, line_hpcom_out_ctrl
.b8
);
break;
case PGAR_2_HPRCOM_VOL_CTRL
:
adc_pga_dac_gain_ctrl
.b8
= tlv320aic31_read(IIC_device_addr
[chip_num
], 70);
adc_pga_dac_gain_ctrl
.bit
.if_mute_route
= 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
], 70, adc_pga_dac_gain_ctrl
.b8
);
break;
case DACR1_2_HPRCOM_VOL_CTRL
:
adc_pga_dac_gain_ctrl
.b8
= tlv320aic31_read(IIC_device_addr
[chip_num
], 71);
adc_pga_dac_gain_ctrl
.bit
.if_mute_route
= 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
], 71, adc_pga_dac_gain_ctrl
.b8
);
break;
case HPRCOM_OUTPUT_LEVEL_CTRL
:
line_hpcom_out_ctrl
.b8
= tlv320aic31_read(IIC_device_addr
[chip_num
], 72);
line_hpcom_out_ctrl
.bit
.if_mute
= audio_ctrl
->if_mute_route
;
line_hpcom_out_ctrl
.bit
.output_level
= audio_ctrl
->input_level
;
tlv320aic31_write(IIC_device_addr
[chip_num
], 72, line_hpcom_out_ctrl
.b8
);
break;
case PGAL_2_LEFT_LOP_VOL_CTRL
:
adc_pga_dac_gain_ctrl
.b8
= tlv320aic31_read(IIC_device_addr
[chip_num
], 81);
adc_pga_dac_gain_ctrl
.bit
.if_mute_route
= 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
], 81, adc_pga_dac_gain_ctrl
.b8
);
break;
case DACL1_2_LEFT_LOP_VOL_CTRL
:
adc_pga_dac_gain_ctrl
.b8
= tlv320aic31_read(IIC_device_addr
[chip_num
], 82);
adc_pga_dac_gain_ctrl
.bit
.if_mute_route
= 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
], 82, adc_pga_dac_gain_ctrl
.b8
);
break;
case LEFT_LOP_OUTPUT_LEVEL_CTRL
:
line_hpcom_out_ctrl
.b8
= tlv320aic31_read(IIC_device_addr
[chip_num
], 86);
line_hpcom_out_ctrl
.bit
.if_mute
= audio_ctrl
->if_mute_route
;
line_hpcom_out_ctrl
.bit
.output_level
= audio_ctrl
->input_level
;
line_hpcom_out_ctrl
.bit
.power_status
= audio_ctrl
->if_powerup
;
tlv320aic31_write(IIC_device_addr
[chip_num
], 86, line_hpcom_out_ctrl
.b8
);
break;
case PGAR_2_RIGHT_LOP_VOL_CTRL
:
adc_pga_dac_gain_ctrl
.b8
= tlv320aic31_read(IIC_device_addr
[chip_num
], 91);
adc_pga_dac_gain_ctrl
.bit
.if_mute_route
= 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
], 91, adc_pga_dac_gain_ctrl
.b8
);
break;
case DACR1_2_RIGHT_LOP_VOL_CTRL
:
adc_pga_dac_gain_ctrl
.b8
= tlv320aic31_read(IIC_device_addr
[chip_num
], 92);
adc_pga_dac_gain_ctrl
.bit
.if_mute_route
= 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
], 92, adc_pga_dac_gain_ctrl
.b8
);
break;
case RIGHT_LOP_OUTPUT_LEVEL_CTRL
:
line_hpcom_out_ctrl
.b8
= tlv320aic31_read(IIC_device_addr
[chip_num
], 93);
line_hpcom_out_ctrl
.bit
.if_mute
= audio_ctrl
->if_mute_route
;
line_hpcom_out_ctrl
.bit
.output_level
= audio_ctrl
->input_level
;
line_hpcom_out_ctrl
.bit
.power_status
= audio_ctrl
->if_powerup
;
tlv320aic31_write(IIC_device_addr
[chip_num
], 93, line_hpcom_out_ctrl
.b8
);
break;
case DACL1_2_HPROUT_VOL_CTRL
:
adc_pga_dac_gain_ctrl
.b8
= tlv320aic31_read(IIC_device_addr
[chip_num
], 61);
adc_pga_dac_gain_ctrl
.bit
.if_mute_route
= 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
], 61, adc_pga_dac_gain_ctrl
.b8
);
break;
case DACL1_2_HPRCOM_VOL_CTRL
:
adc_pga_dac_gain_ctrl
.b8
= tlv320aic31_read(IIC_device_addr
[chip_num
], 68);
adc_pga_dac_gain_ctrl
.bit
.if_mute_route
= 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
], 68, adc_pga_dac_gain_ctrl
.b8
);
break;
case SET_ADC_SAMPLE
:
in2_adc_ctrl_sample
.b8
= tlv320aic31_read(IIC_device_addr
[chip_num
], 2);
in2_adc_ctrl_sample
.bit
.in2l_adc_input_level_sample
= audio_ctrl
->sample
;
tlv320aic31_write(IIC_device_addr
[chip_num
], 2, in2_adc_ctrl_sample
.b8
);
break;
case SET_DAC_SAMPLE
:
in2_adc_ctrl_sample
.b8
= tlv320aic31_read(IIC_device_addr
[chip_num
], 2);
in2_adc_ctrl_sample
.bit
.in2r_adc_input_level_sample
= audio_ctrl
->sample
;
tlv320aic31_write(IIC_device_addr
[chip_num
], 2, in2_adc_ctrl_sample
.b8
);
break;
case SET_DATA_LENGTH
:
serial_int_ctrl
.b8
= tlv320aic31_read(IIC_device_addr
[chip_num
], 9);;
serial_int_ctrl
.bit
.data_length
= audio_ctrl
->data_length
;
break;
case SET_TRANSFER_MODE
:
serial_int_ctrl
.b8
= tlv320aic31_read(IIC_device_addr
[chip_num
], 9);
serial_int_ctrl
.bit
.transfer_mode
= audio_ctrl
->trans_mode
;
tlv320aic31_write(IIC_device_addr
[chip_num
], 9, serial_int_ctrl
.b8
);
break;
case SET_CTRL_MODE
:
ctrl_mode
.b8
= tlv320aic31_read(IIC_device_addr
[chip_num
], 8);
ctrl_mode
.bit
.bit_clock_dic_ctrl
= audio_ctrl
->ctrl_mode
;
ctrl_mode
.bit
.work_clock_dic_ctrl
= audio_ctrl
->ctrl_mode
;
ctrl_mode
.bit
.bit_work_dri_ctrl
= audio_ctrl
->ctrl_mode
;
tlv320aic31_write(IIC_device_addr
[chip_num
], 8, ctrl_mode
.b8
);
#if 0
if (1 == audio_ctrl
->ctrl_mode
|| (AC31_SET_48K_SAMPLERATE
!= audio_ctrl
->sample
&& AC31_SET_44_1K_SAMPLERATE
!= audio_ctrl
->sample
))
{
if ((1 == audio_ctrl
->if_44100hz_series
))
{
tlv320aic31_write(IIC_device_addr
[chip_num
], 3, 0x81);
tlv320aic31_write(IIC_device_addr
[chip_num
], 4, 0x1c);
tlv320aic31_write(IIC_device_addr
[chip_num
], 5, 0x36);
tlv320aic31_write(IIC_device_addr
[chip_num
], 6, 0xb0);
codec_datapath_setup_ctrl
.b8
= tlv320aic31_read(IIC_device_addr
[chip_num
], 7);
codec_datapath_setup_ctrl
.b8
|= 0x80;
tlv320aic31_write(IIC_device_addr
[chip_num
], 7, codec_datapath_setup_ctrl
.b8
);
tlv320aic31_write(IIC_device_addr
[chip_num
], 11, 0x1);
tlv320aic31_write(IIC_device_addr
[chip_num
], 101, 0x0);
tlv320aic31_write(IIC_device_addr
[chip_num
], 102, 0xc2);
}
else
{
tlv320aic31_write(IIC_device_addr
[chip_num
], 3, 0x81);
tlv320aic31_write(IIC_device_addr
[chip_num
], 4, 0x20);
tlv320aic31_write(IIC_device_addr
[chip_num
], 5, 0x0);
tlv320aic31_write(IIC_device_addr
[chip_num
], 6, 0x0);
codec_datapath_setup_ctrl
.b8
= tlv320aic31_read(IIC_device_addr
[chip_num
], 7);
codec_datapath_setup_ctrl
.b8
&= 0x7f;
tlv320aic31_write(IIC_device_addr
[chip_num
], 7, codec_datapath_setup_ctrl
.b8
);
tlv320aic31_write(IIC_device_addr
[chip_num
], 11, 0x1);
tlv320aic31_write(IIC_device_addr
[chip_num
], 101, 0x0);
tlv320aic31_write(IIC_device_addr
[chip_num
], 102, 0xc2);
}
}
else
{
tlv320aic31_write(IIC_device_addr
[chip_num
], 102, 0x22);
codec_datapath_setup_ctrl
.b8
= tlv320aic31_read(IIC_device_addr
[chip_num
], 7);
if ((1 == audio_ctrl
->if_44100hz_series
))
{
codec_datapath_setup_ctrl
.b8
|= 0x80;
}
else
{
codec_datapath_setup_ctrl
.b8
&= 0x7f;
}
tlv320aic31_write(IIC_device_addr
[chip_num
], 7, codec_datapath_setup_ctrl
.b8
);
tlv320aic31_write(IIC_device_addr
[chip_num
], 3, 0x81);
tlv320aic31_write(IIC_device_addr
[chip_num
], 4, 32 << 2);
tlv320aic31_write(IIC_device_addr
[chip_num
], 5, 0x0);
tlv320aic31_write(IIC_device_addr
[chip_num
], 6, 0x0);
tlv320aic31_write(IIC_device_addr
[chip_num
], 101, 0x0);
tlv320aic31_write(IIC_device_addr
[chip_num
], 11, 0x2);
}
#else
switch (audio_ctrl
->sampleRate
)
{
case 8000:
case 16000:
case 32000:
{
tlv320aic31_write(IIC_device_addr
[chip_num
], 3, 0x81);
tlv320aic31_write(IIC_device_addr
[chip_num
], 4, 0x30);
tlv320aic31_write(IIC_device_addr
[chip_num
], 5, 0x0);
tlv320aic31_write(IIC_device_addr
[chip_num
], 6, 0x0);
codec_datapath_setup_ctrl
.b8
= tlv320aic31_read(IIC_device_addr
[chip_num
], 7);
codec_datapath_setup_ctrl
.b8
&= 0x7f;
tlv320aic31_write(IIC_device_addr
[chip_num
], 7, codec_datapath_setup_ctrl
.b8
);
tlv320aic31_write(IIC_device_addr
[chip_num
], 11, 0x1);
tlv320aic31_write(IIC_device_addr
[chip_num
], 101, 0x0);
tlv320aic31_write(IIC_device_addr
[chip_num
], 102, 0xc2);
}
break;
case 12000:
case 24000:
case 48000:
{
tlv320aic31_write(IIC_device_addr
[chip_num
], 3, 0x81);
tlv320aic31_write(IIC_device_addr
[chip_num
], 4, 0x20);
tlv320aic31_write(IIC_device_addr
[chip_num
], 5, 0x0);
tlv320aic31_write(IIC_device_addr
[chip_num
], 6, 0x0);
codec_datapath_setup_ctrl
.b8
= tlv320aic31_read(IIC_device_addr
[chip_num
], 7);
codec_datapath_setup_ctrl
.b8
&= 0x7f;
tlv320aic31_write(IIC_device_addr
[chip_num
], 7, codec_datapath_setup_ctrl
.b8
);
tlv320aic31_write(IIC_device_addr
[chip_num
], 11, 0x1);
tlv320aic31_write(IIC_device_addr
[chip_num
], 101, 0x0);
tlv320aic31_write(IIC_device_addr
[chip_num
], 102, 0xc2);
}
break;
case 11025:
case 22050:
case 44100:
{
tlv320aic31_write(IIC_device_addr
[chip_num
], 3, 0x81);
tlv320aic31_write(IIC_device_addr
[chip_num
], 4, 0x20);
tlv320aic31_write(IIC_device_addr
[chip_num
], 5, 0x00);
tlv320aic31_write(IIC_device_addr
[chip_num
], 6, 0x00);
codec_datapath_setup_ctrl
.b8
= tlv320aic31_read(IIC_device_addr
[chip_num
], 7);
codec_datapath_setup_ctrl
.b8
|= 0x80;
tlv320aic31_write(IIC_device_addr
[chip_num
], 7, codec_datapath_setup_ctrl
.b8
);
tlv320aic31_write(IIC_device_addr
[chip_num
], 11, 0x1);
tlv320aic31_write(IIC_device_addr
[chip_num
], 101, 0x0);
tlv320aic31_write(IIC_device_addr
[chip_num
], 102, 0xc2);
}
break;
default:
printk("aic31 unsupport sampleRate %d\n", audio_ctrl
->sampleRate
);
return -1;
}
#endif
break;
case LEFT_DAC_VOL_CTRL
:
adc_pga_dac_gain_ctrl
.b8
= tlv320aic31_read(IIC_device_addr
[chip_num
], 43);
adc_pga_dac_gain_ctrl
.bit
.if_mute_route
= 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
], 43, adc_pga_dac_gain_ctrl
.b8
);
break;
case RIGHT_DAC_VOL_CTRL
:
adc_pga_dac_gain_ctrl
.b8
= tlv320aic31_read(IIC_device_addr
[chip_num
], 44);
adc_pga_dac_gain_ctrl
.bit
.if_mute_route
= 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
], 44, adc_pga_dac_gain_ctrl
.b8
);
break;
case LEFT_DAC_POWER_SETUP
:
codec_datapath_setup_ctrl
.b8
= tlv320aic31_read(IIC_device_addr
[chip_num
], 7);
codec_datapath_setup_ctrl
.bit
.left_dac_datapath_ctrl
= audio_ctrl
->if_powerup
;
tlv320aic31_write(IIC_device_addr
[chip_num
], 7, codec_datapath_setup_ctrl
.b8
);
dac_power_ctrl
.b8
= tlv320aic31_read(IIC_device_addr
[chip_num
], 37);
dac_power_ctrl
.bit
.left_dac_power_ctrl
= audio_ctrl
->if_powerup
;
tlv320aic31_write(IIC_device_addr
[chip_num
], 37, dac_power_ctrl
.b8
);
break;
case RIGHT_DAC_POWER_SETUP
:
codec_datapath_setup_ctrl
.b8
= tlv320aic31_read(IIC_device_addr
[chip_num
], 7);
codec_datapath_setup_ctrl
.bit
.right_dac_datapath_ctrl
= audio_ctrl
->if_powerup
;
tlv320aic31_write(IIC_device_addr
[chip_num
], 7, codec_datapath_setup_ctrl
.b8
);
dac_power_ctrl
.b8
= tlv320aic31_read(IIC_device_addr
[chip_num
], 37);
dac_power_ctrl
.bit
.right_dac_power_ctrl
= audio_ctrl
->if_powerup
;
tlv320aic31_write(IIC_device_addr
[chip_num
], 37, dac_power_ctrl
.b8
);
break;
case DAC_OUT_SWITCH_CTRL
:
dac_output_swit_ctrl
.b8
= tlv320aic31_read(IIC_device_addr
[chip_num
], 41);
dac_output_swit_ctrl
.bit
.left_dac_swi_ctrl
= audio_ctrl
->dac_path
;
dac_output_swit_ctrl
.bit
.right_dac_swi_ctrl
= audio_ctrl
->dac_path
;
tlv320aic31_write(IIC_device_addr
[chip_num
], 41, dac_output_swit_ctrl
.b8
);
break;
case LEFT_ADC_PGA_CTRL
:
adc_pga_dac_gain_ctrl
.b8
= tlv320aic31_read(IIC_device_addr
[chip_num
], 15);
adc_pga_dac_gain_ctrl
.bit
.if_mute_route
= 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
], 15, adc_pga_dac_gain_ctrl
.b8
);
break;
case RIGHT_ADC_PGA_CTRL
:
adc_pga_dac_gain_ctrl
.b8
= tlv320aic31_read(IIC_device_addr
[chip_num
], 16);
adc_pga_dac_gain_ctrl
.bit
.if_mute_route
= 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
], 16, adc_pga_dac_gain_ctrl
.b8
);
break;
case SET_SERIAL_DATA_OFFSET
:
serial_data_offset_ctrl
.b8
= tlv320aic31_read(IIC_device_addr
[chip_num
], 10);
serial_data_offset_ctrl
.bit
.serial_data_offset
= audio_ctrl
->data_offset
;
tlv320aic31_write(IIC_device_addr
[chip_num
], 10, serial_data_offset_ctrl
.b8
);
break;
case SOFT_RESET
:
soft_reset(chip_num
);
break;
case TLV320AIC31_REG_DUMP
:
tlv320aic31_reg_dump(102);
break;
default:
break;
}
return 0;
}
#ifdef CONFIG_HISI_SNAPSHOT_BOOT
static int tlv320aic31_freeze(struct himedia_device
* pdev
)
{
printk(KERN_ALERT
"%s %d\n", __FUNCTION__
, __LINE__);
return 0;
}
static int tlv320aic31_restore(struct himedia_device
* pdev
)
{
int i
;
for (i
= 0; i
< chip_count
; i
++)
{
if (tlv320aic31_device_init(i
) < 0)
{
printk(KERN_ALERT
"%s %d, tlv320aic31 device init fail!\n", __FUNCTION__
, __LINE__);
return -1;
}
}
printk(KERN_ALERT
"%s %d\n", __FUNCTION__
, __LINE__);
return 0;
}
#endif
static struct file_operations tlv320aic31_fops
=
{
.owner
= THIS_MODULE
,
.unlocked_ioctl
= tlv320aic31_ioctl
,
.open
= tlv320aic31_open
,
.release
= tlv320aic31_close
};
#ifdef CONFIG_HISI_SNAPSHOT_BOOT
struct himedia_ops stTlv320aic31DrvOps
=
{
.pm_freeze
= tlv320aic31_freeze
,
.pm_restore
= tlv320aic31_restore
};
#else
static struct miscdevice tlv320aic31_dev
=
{
MISC_DYNAMIC_MINOR
,
DEV_NAME
,
&tlv320aic31_fops
,
};
#endif
static int set_chip_count(const char* val
, const struct kernel_param
* kp
)
{
int ret
;
int chip_count
;
ret
= kstrtoint(val
, 10, &chip_count
);
if (ret
< 0)
{
return -EINVAL
;
}
if (chip_count
< 0 || chip_count
> CHIP_NUM
)
{
printk("chip_count%d err. \n", chip_count
);
return -EINVAL
;
}
return 0;
}
static struct kernel_param_ops alv320_para_ops
=
{
.set
= set_chip_count
,
};
#if 0
module_param(chip_count
, int, 0);
#else
module_param_cb(chip_count
, &alv320_para_ops
, &chip_count
, 0644);
#endif
MODULE_PARM_DESC(chip_count
, "the num we device uses the tlv320aic31,default 1");
static int tlv320aic31_reboot(struct notifier_block
* self
, unsigned long data
, void* pdata
)
{
unsigned int i
;
for (i
= 0; i
< chip_count
; i
++)
{
tlv320aic31_write(IIC_device_addr
[i
], 51, 0x04);
tlv320aic31_write(IIC_device_addr
[i
], 65, 0x04);
}
printk("Func:%s, line:%d######\n", __FUNCTION__
, __LINE__);
return 0;
}
static struct notifier_block tlv320aic31_reboot_notifier
=
{
.notifier_call
= tlv320aic31_reboot
,
};
static int tlv320aic31_device_init(unsigned int num
)
{
unsigned char temp
= 0;
temp
= tlv320aic31_read(IIC_device_addr
[num
], 0x2);
tlv320aic31_write(IIC_device_addr
[0], 0x2, 0xaa);
if ( tlv320aic31_read(IIC_device_addr
[num
], 0x2) != 0xaa)
{
DPRINTK(0, "init aic31(%d) error", num
);
return -1;
}
tlv320aic31_write(IIC_device_addr
[num
], 0x2, temp
);
soft_reset(num
);
register_reboot_notifier(&tlv320aic31_reboot_notifier
);
return 0;
}
static int tlv320aic31_device_exit(unsigned int num
)
{
tlv320aic31_write(IIC_device_addr
[num
], 51, 0x04);
tlv320aic31_write(IIC_device_addr
[num
], 65, 0x04);
return 0;
}
static int i2c_client_init(void)
{
struct i2c_adapter
* i2c_adap
;
i2c_adap
= i2c_get_adapter(0);
if (NULL == i2c_adap
)
{
printk("find i2c adapter fail. \n");
return -1;
}
tlv_client
= i2c_new_device(i2c_adap
, &hi_info
);
i2c_put_adapter(i2c_adap
);
return 0;
}
static void i2c_client_exit(void)
{
i2c_unregister_device(tlv_client
);
}
static int __init
tlv320aic31_init(void)
{
unsigned int i
, ret
;
#ifdef CONFIG_HISI_SNAPSHOT_BOOT
snprintf(s_stTlv320aic31Device
.devfs_name
, sizeof(s_stTlv320aic31Device
.devfs_name
), DEV_NAME
);
s_stTlv320aic31Device
.minor
= HIMEDIA_DYNAMIC_MINOR
;
s_stTlv320aic31Device
.fops
= &tlv320aic31_fops
;
s_stTlv320aic31Device
.drvops
= &stTlv320aic31DrvOps
;
s_stTlv320aic31Device
.owner
= THIS_MODULE
;
ret
= himedia_register(&s_stTlv320aic31Device
);
if (ret
)
{
DPRINTK(0, "could not register tlv320aic31 device");
return -1;
}
#else
ret
= misc_register(&tlv320aic31_dev
);
if (ret
)
{
DPRINTK(0, "could not register tlv320aic31 device");
return -1;
}
#endif
i2c_client_init();
for (i
= 0; i
< chip_count
; i
++)
{
if (tlv320aic31_device_init(i
) < 0)
{
goto init_fail
;
}
}
DPRINTK(1, "tlv320aic31 driver init successful!");
printk("load tlv320aic31.ko ok!\n");
return ret
;
init_fail
:
#ifdef CONFIG_HISI_SNAPSHOT_BOOT
himedia_unregister(&s_stTlv320aic31Device
);
#else
misc_deregister(&tlv320aic31_dev
);
#endif
DPRINTK(0, "tlv320aic31 device init fail,deregister it!");
return -1;
}
static void __exit
tlv320aic31_exit(void)
{
unsigned int i
;
for (i
= 0; i
< chip_count
; i
++)
{
tlv320aic31_device_exit(i
);
}
unregister_reboot_notifier(&tlv320aic31_reboot_notifier
);
#ifdef CONFIG_HISI_SNAPSHOT_BOOT
himedia_unregister(&s_stTlv320aic31Device
);
#else
misc_deregister(&tlv320aic31_dev
);
#endif
i2c_client_exit();
DPRINTK(1, "deregister tlv320aic31");
printk("rmmod tlv320aic31.ko ok!\n");
}
module_init(tlv320aic31_init
);
module_exit(tlv320aic31_exit
);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Hisilicon");
sample 程序
主程序
extern SAMPLE_AI_S gs_stSampleAi
[AI_DEV_MAX_NUM
*AIO_MAX_CHN_NUM
];
extern void *SAMPLE_COMM_AUDIO_AiProc_modby_glx(void *parg
);
HI_S32
SAMPLE_AUDIO_Aip2_Aop0(HI_VOID
)
{
HI_S32 s32Ret
, i
;
HI_S32 s32AiChnCnt
;
HI_S32 s32AoChnCnt
;
AUDIO_DEV AiDev
= SAMPLE_AUDIO_TLV320_AI_DEV
;
AUDIO_DEV AoDev
= SAMPLE_AUDIO_TLV320_AO_DEV
;
AI_CHN AiChn
= 0;
AO_CHN AoChn
= 0;
AIO_ATTR_S stAioAttr
;
stAioAttr
.enSamplerate
= AUDIO_SAMPLE_RATE_48000
;
stAioAttr
.enBitwidth
= AUDIO_BIT_WIDTH_16
;
stAioAttr
.enWorkmode
= AIO_MODE_I2S_MASTER
;
stAioAttr
.enSoundmode
= AUDIO_SOUND_MODE_STEREO
;
stAioAttr
.u32EXFlag
= 1;
stAioAttr
.u32FrmNum
= 300;
stAioAttr
.u32PtNumPerFrm
= 320;
stAioAttr
.u32ChnCnt
= 2;
stAioAttr
.u32ClkChnCnt
= 2;
stAioAttr
.u32ClkSel
= 1;
s32Ret
= SAMPLE_COMM_AUDIO_CfgTlv320(&stAioAttr
);
if (HI_SUCCESS
!= s32Ret
)
{
SAMPLE_DBG(s32Ret
);
return HI_FAILURE
;
}
s32AiChnCnt
= stAioAttr
.u32ChnCnt
>> stAioAttr
.enSoundmode
;
g_u32AiCnt
= s32AiChnCnt
;
g_u32AiDev
= AiDev
;
s32Ret
= HI_MPI_AI_SetPubAttr(AiDev
, &stAioAttr
);
if (s32Ret
)
{
printf("%s: HI_MPI_AI_SetPubAttr(%d) failed with %#x\n", __FUNCTION__
, AiDev
, s32Ret
);
return s32Ret
;
}
s32Ret
= HI_MPI_AI_Enable(AiDev
);
if (s32Ret
)
{
printf("%s: HI_MPI_AI_Enable(%d) failed with %#x\n", __FUNCTION__
, AiDev
, s32Ret
);
return s32Ret
;
}
for (i
= 0; i
< s32AiChnCnt
; i
++)
{
s32Ret
= HI_MPI_AI_EnableChn(AiDev
, i
);
if (s32Ret
)
{
printf("%s: HI_MPI_AI_EnableChn(%d,%d) failed with %#x\n", __FUNCTION__
, AiDev
, i
, s32Ret
);
return s32Ret
;
}
}
stAioAttr
.u32ChnCnt
= stAioAttr
.u32ChnCnt
>2 ? 2: stAioAttr
.u32ChnCnt
;
s32AoChnCnt
= stAioAttr
.u32ChnCnt
>> stAioAttr
.enSoundmode
;
g_u32AoCnt
= s32AoChnCnt
;
g_u32AoDev
= AoDev
;
s32Ret
= HI_MPI_AO_SetPubAttr(AoDev
, &stAioAttr
);
if (HI_SUCCESS
!= s32Ret
)
{
printf("%s: HI_MPI_AO_SetPubAttr(%d) failed with %#x!\n", __FUNCTION__
, \
AoDev
, s32Ret
);
return HI_FAILURE
;
}
s32Ret
= HI_MPI_AO_Enable(AoDev
);
if (HI_SUCCESS
!= s32Ret
)
{
printf("%s: HI_MPI_AO_Enable(%d) failed with %#x!\n", __FUNCTION__
, AoDev
, s32Ret
);
return HI_FAILURE
;
}
for (i
= 0; i
< s32AoChnCnt
; i
++)
{
s32Ret
= HI_MPI_AO_EnableChn(AoDev
, i
);
if (HI_SUCCESS
!= s32Ret
)
{
printf("%s: HI_MPI_AO_EnableChn(%d) failed with %#x!\n", __FUNCTION__
, i
, s32Ret
);
return HI_FAILURE
;
}
}
FILE
*pfd
[s32AoChnCnt
];
for (i
= 0; i
< s32AoChnCnt
; i
++)
{
HI_CHAR aszFileName
[128];
sprintf(aszFileName
, "audio_chn%d.%s", i
, SAMPLE_AUDIO_Pt2Str(PT_LPCM
));
pfd
[i
] = fopen(aszFileName
, "w+");
if (NULL == pfd
)
{
printf("%s: open file %s failed\n", __FUNCTION__
, aszFileName
);
return -1;
}
printf("open stream file:\"%s\" ok\n", aszFileName
);
}
for (i
=0; i
<g_u32AoCnt
; i
++)
{
AiChn
= i
;
AoChn
= i
;
SAMPLE_AI_S
*pstAi
= NULL;
pstAi
= &gs_stSampleAi
[AiDev
*AIO_MAX_CHN_NUM
+ AiChn
];
pstAi
->bSendAenc
= HI_FALSE
;
pstAi
->bSendAo
= HI_TRUE
;
pstAi
->bStart
= HI_TRUE
;
pstAi
->AiDev
= AiDev
;
pstAi
->AiChn
= AiChn
;
pstAi
->AoDev
= AoDev
;
pstAi
->AoChn
= AoChn
;
pstAi
->pfd
= pfd
[i
];
pthread_create(&pstAi
->stAiPid
, 0, SAMPLE_COMM_AUDIO_AiProc_modby_glx
, pstAi
);
if (s32Ret
!= HI_SUCCESS
)
{
SAMPLE_DBG(s32Ret
);
return HI_FAILURE
;
}
}
printf("\nplease press twice ENTER to exit this sample\n");
getchar();
getchar();
for (i
=0; i
<g_u32AoCnt
; i
++)
{
AiChn
= i
;
s32Ret
= SAMPLE_COMM_AUDIO_DestoryTrdAi(AiDev
, AiChn
);
if (s32Ret
!= HI_SUCCESS
)
{
SAMPLE_DBG(s32Ret
);
return HI_FAILURE
;
}
}
s32Ret
= SAMPLE_COMM_AUDIO_StopAi(AiDev
, s32AiChnCnt
, HI_FALSE
, HI_FALSE
);
if (s32Ret
!= HI_SUCCESS
)
{
SAMPLE_DBG(s32Ret
);
return HI_FAILURE
;
}
s32Ret
= SAMPLE_COMM_AUDIO_StopAo(AoDev
, s32AoChnCnt
, HI_TRUE
, HI_FALSE
);
if (s32Ret
!= HI_SUCCESS
)
{
SAMPLE_DBG(s32Ret
);
return HI_FAILURE
;
}
return HI_SUCCESS
;
}
采集播放线程
void *SAMPLE_COMM_AUDIO_AiProc_modby_glx(void *parg
)
{
HI_S32 s32Ret
;
HI_S32 AiFd
;
SAMPLE_AI_S
*pstAiCtl
= (SAMPLE_AI_S
*)parg
;
AUDIO_FRAME_S stFrame
;
fd_set read_fds
;
struct timeval TimeoutVal
;
AI_CHN_PARAM_S stAiChnPara
;
prctl(PR_SET_NAME
, "hi_SAMPLE_AiProc", 0, 0, 0);
s32Ret
= HI_MPI_AI_GetChnParam(pstAiCtl
->AiDev
, pstAiCtl
->AiChn
, &stAiChnPara
);
if (HI_SUCCESS
!= s32Ret
)
{
printf("%s: Get ai chn param failed\n", __FUNCTION__
);
return NULL;
}
stAiChnPara
.u32UsrFrmDepth
= 30;
s32Ret
= HI_MPI_AI_SetChnParam(pstAiCtl
->AiDev
, pstAiCtl
->AiChn
, &stAiChnPara
);
if (HI_SUCCESS
!= s32Ret
)
{
printf("%s: set ai chn param failed\n", __FUNCTION__
);
return NULL;
}
FD_ZERO(&read_fds
);
AiFd
= HI_MPI_AI_GetFd(pstAiCtl
->AiDev
, pstAiCtl
->AiChn
);
FD_SET(AiFd
,&read_fds
);
while (pstAiCtl
->bStart
)
{
TimeoutVal
.tv_sec
= 1;
TimeoutVal
.tv_usec
= 0;
FD_ZERO(&read_fds
);
FD_SET(AiFd
,&read_fds
);
s32Ret
= select(AiFd
+1, &read_fds
, NULL, NULL, &TimeoutVal
);
if (s32Ret
< 0)
{
break;
}
else if (0 == s32Ret
)
{
printf("%s: get ai frame select time out\n", __FUNCTION__
);
break;
}
if (FD_ISSET(AiFd
, &read_fds
))
{
s32Ret
= HI_MPI_AI_GetFrame(pstAiCtl
->AiDev
, pstAiCtl
->AiChn
, &stFrame
, NULL, HI_FALSE
);
if (HI_SUCCESS
!= s32Ret
)
{
printf("%s: HI_MPI_AI_GetFrame(%d, %d), failed with %#x!\n",\
__FUNCTION__
, pstAiCtl
->AiDev
, pstAiCtl
->AiChn
, s32Ret
);
pstAiCtl
->bStart
= HI_FALSE
;
return NULL;
}
if (HI_TRUE
== pstAiCtl
->bSendAo
)
{
s32Ret
= HI_MPI_AO_SendFrame(pstAiCtl
->AoDev
, pstAiCtl
->AoChn
, &stFrame
, 1000);
if (HI_SUCCESS
!= s32Ret
)
{
printf("%s: HI_MPI_AO_SendFrame(%d, %d), failed with %#x!\n",\
__FUNCTION__
, pstAiCtl
->AoDev
, pstAiCtl
->AoChn
, s32Ret
);
pstAiCtl
->bStart
= HI_FALSE
;
return NULL;
}
}
s32Ret
= HI_MPI_AI_ReleaseFrame(pstAiCtl
->AiDev
, pstAiCtl
->AiChn
, &stFrame
, NULL);
if (HI_SUCCESS
!= s32Ret
)
{
printf("%s: HI_MPI_AI_ReleaseFrame(%d, %d), failed with %#x!\n",\
__FUNCTION__
, pstAiCtl
->AiDev
, pstAiCtl
->AiChn
, s32Ret
);
pstAiCtl
->bStart
= HI_FALSE
;
return NULL;
}
}
}
pstAiCtl
->bStart
= HI_FALSE
;
fclose(pstAiCtl
->pfd
);
return NULL;
}
声卡配置
HI_S32
SAMPLE_Tlv320_CfgAudio(AIO_ATTR_S
*pstAioAttr
)
{
AIO_MODE_E enWorkmode
= pstAioAttr
->enWorkmode
;
AUDIO_SAMPLE_RATE_E enSample
= pstAioAttr
->enSamplerate
;
#if (defined HI_ACODEC_TYPE_TLV320AIC31)
HI_S32 s32Samplerate
;
Audio_Ctrl audio_ctrl
;
int s_fdTlv
= -1;
HI_BOOL bPCMmode
= HI_FALSE
;
HI_BOOL bMaster
= HI_FALSE
;
HI_BOOL b44100HzSeries
= HI_FALSE
;
printf("config TLV320AIC31\n");
if (AUDIO_SAMPLE_RATE_8000
== enSample
)
{
s32Samplerate
= AC31_SET_8K_SAMPLERATE
;
}
else if (AUDIO_SAMPLE_RATE_12000
== enSample
)
{
s32Samplerate
= AC31_SET_12K_SAMPLERATE
;
}
else if (AUDIO_SAMPLE_RATE_11025
== enSample
)
{
b44100HzSeries
= HI_TRUE
;
s32Samplerate
= AC31_SET_11_025K_SAMPLERATE
;
}
else if (AUDIO_SAMPLE_RATE_16000
== enSample
)
{
s32Samplerate
= AC31_SET_16K_SAMPLERATE
;
}
else if (AUDIO_SAMPLE_RATE_22050
== enSample
)
{
b44100HzSeries
= HI_TRUE
;
s32Samplerate
= AC31_SET_22_05K_SAMPLERATE
;
}
else if (AUDIO_SAMPLE_RATE_24000
== enSample
)
{
s32Samplerate
= AC31_SET_24K_SAMPLERATE
;
}
else if (AUDIO_SAMPLE_RATE_32000
== enSample
)
{
s32Samplerate
= AC31_SET_32K_SAMPLERATE
;
}
else if (AUDIO_SAMPLE_RATE_44100
== enSample
)
{
b44100HzSeries
= HI_TRUE
;
s32Samplerate
= AC31_SET_44_1K_SAMPLERATE
;
}
else if (AUDIO_SAMPLE_RATE_48000
== enSample
)
{
s32Samplerate
= AC31_SET_48K_SAMPLERATE
;
}
else
{
printf("SAMPLE_Tlv320_CfgAudio(), not support enSample:%d\n",enSample
);
return -1;
}
if(AIO_MODE_I2S_MASTER
== enWorkmode
)
{
bPCMmode
= HI_FALSE
;
bMaster
= HI_FALSE
;
}
else if(AIO_MODE_I2S_SLAVE
== enWorkmode
)
{
bPCMmode
= HI_FALSE
;
bMaster
= HI_TRUE
;
}
else if((AIO_MODE_PCM_MASTER_NSTD
== enWorkmode
)||(AIO_MODE_PCM_MASTER_STD
== enWorkmode
))
{
bPCMmode
= HI_TRUE
;
bMaster
= HI_FALSE
;
}
else if((AIO_MODE_PCM_SLAVE_NSTD
== enWorkmode
)||(AIO_MODE_PCM_SLAVE_STD
== enWorkmode
))
{
bPCMmode
= HI_TRUE
;
bMaster
= HI_TRUE
;
}
else
{
printf("SAMPLE_Tlv320_CfgAudio(), not support workmode:%d\n\n",enWorkmode
);
}
s_fdTlv
= open(TLV320_FILE
,O_RDWR
);
if (s_fdTlv
< 0)
{
printf("can't open codec device, %s\n", TLV320_FILE
);
return -1;
}
audio_ctrl
.chip_num
= 0;
if (ioctl(s_fdTlv
,SOFT_RESET
,&audio_ctrl
))
{
printf("tlv320aic31 SOFT_RESET error\n");
close(s_fdTlv
);
return -1;
}
audio_ctrl
.ctrl_mode
= bMaster
;
audio_ctrl
.sampleRate
= enSample
;
audio_ctrl
.if_44100hz_series
= b44100HzSeries
;
if (ioctl(s_fdTlv
,SET_CTRL_MODE
,&audio_ctrl
))
{
printf("tlv320aic31 SET_CTRL_MODE error\n");
close(s_fdTlv
);
return -1;
}
audio_ctrl
.trans_mode
= bPCMmode
;
if (ioctl(s_fdTlv
, SET_TRANSFER_MODE
, &audio_ctrl
))
{
printf("tlv320aic31 SET_CTRL_MODE error\n");
close(s_fdTlv
);
return -1;
}
audio_ctrl
.sample
= s32Samplerate
;
if (ioctl(s_fdTlv
, SET_DAC_SAMPLE
, &audio_ctrl
))
{
printf("tlv320aic31 SET_DAC_SAMPLE error\n");
close(s_fdTlv
);
return -1;
}
if (ioctl(s_fdTlv
, SET_ADC_SAMPLE
, &audio_ctrl
))
{
printf("tlv320aic31 SET_ADC_SAMPLE error\n");
close(s_fdTlv
);
return -1;
}
audio_ctrl
.if_powerup
= 1;
if (ioctl(s_fdTlv
, LEFT_DAC_POWER_SETUP
, &audio_ctrl
))
{
printf("tlv320aic31 LEFT_DAC_POWER_SETUP error\n");
close(s_fdTlv
);
return -1;
}
if (ioctl(s_fdTlv
, RIGHT_DAC_POWER_SETUP
, &audio_ctrl
))
{
printf("tlv320aic31 RIGHT_DAC_POWER_SETUP error\n");
close(s_fdTlv
);
return -1;
}
audio_ctrl
.if_mute_route
= 0;
audio_ctrl
.input_level
= 0;
if (ioctl(s_fdTlv
, LEFT_DAC_VOL_CTRL
, &audio_ctrl
))
{
printf("tlv320aic31 LEFT_DAC_VOL_CTRL error\n");
close(s_fdTlv
);
return -1;
}
if (ioctl(s_fdTlv
, RIGHT_DAC_VOL_CTRL
, &audio_ctrl
))
{
printf("tlv320aic31 RIGHT_DAC_VOL_CTRL error\n");
close(s_fdTlv
);
return -1;
}
audio_ctrl
.if_mute_route
= 1;
audio_ctrl
.input_level
= 9;
audio_ctrl
.if_powerup
= 1;
if (ioctl(s_fdTlv
, HPLOUT_OUTPUT_LEVEL_CTRL
, &audio_ctrl
))
{
printf("tlv320aic31 HPLOUT_OUTPUT_LEVEL_CTRL error\n");
close(s_fdTlv
);
return -1;
}
if (ioctl(s_fdTlv
, HPLCOM_OUTPUT_LEVEL_CTRL
, &audio_ctrl
))
{
printf("tlv320aic31 HPLCOM_OUTPUT_LEVEL_CTRL error\n");
close(s_fdTlv
);
return -1;
}
audio_ctrl
.if_mute_route
= 1;
audio_ctrl
.input_level
= 9;
audio_ctrl
.if_powerup
= 1;
if (ioctl(s_fdTlv
, HPROUT_OUTPUT_LEVEL_CTRL
, &audio_ctrl
))
{
printf("tlv320aic31 HPROUT_OUTPUT_LEVEL_CTRL error\n");
close(s_fdTlv
);
return -1;
}
if (ioctl(s_fdTlv
, HPRCOM_OUTPUT_LEVEL_CTRL
, &audio_ctrl
))
{
printf("tlv320aic31 HPRCOM_OUTPUT_LEVEL_CTRL error\n");
close(s_fdTlv
);
return -1;
}
close(s_fdTlv
);
printf("Set aic31 ok: bMaster = %d, enWorkmode = %d, enSamplerate = %d\n",
bMaster
, enWorkmode
, enSample
);
#elif (defined HI_ACODEC_TYPE_TLV320AIC32x4)
int s_fdTlv
= -1;
Audio_Ctrl audio_ctrl
;
printf("config TLV320AIC32x4\n");
if (AUDIO_SAMPLE_RATE_8000
== enSample
)
{
audio_ctrl
.interface
.sample_rate
= AIC32x4_SAMPLE_RATE_8K
;
}
else if (AUDIO_SAMPLE_RATE_12000
== enSample
)
{
audio_ctrl
.interface
.sample_rate
= AIC32x4_SAMPLE_RATE_12K
;
}
else if (AUDIO_SAMPLE_RATE_11025
== enSample
)
{
audio_ctrl
.interface
.sample_rate
= AIC32x4_SAMPLE_RATE_11K
;
}
else if (AUDIO_SAMPLE_RATE_16000
== enSample
)
{
audio_ctrl
.interface
.sample_rate
= AIC32x4_SAMPLE_RATE_16K
;
}
else if (AUDIO_SAMPLE_RATE_22050
== enSample
)
{
audio_ctrl
.interface
.sample_rate
= AIC32x4_SAMPLE_RATE_22K
;
}
else if (AUDIO_SAMPLE_RATE_24000
== enSample
)
{
audio_ctrl
.interface
.sample_rate
= AIC32x4_SAMPLE_RATE_24K
;
}
else if (AUDIO_SAMPLE_RATE_32000
== enSample
)
{
audio_ctrl
.interface
.sample_rate
= AIC32x4_SAMPLE_RATE_32K
;
}
else if (AUDIO_SAMPLE_RATE_44100
== enSample
)
{
audio_ctrl
.interface
.sample_rate
= AIC32x4_SAMPLE_RATE_44K
;
}
else if (AUDIO_SAMPLE_RATE_48000
== enSample
)
{
audio_ctrl
.interface
.sample_rate
= AIC32x4_SAMPLE_RATE_48K
;
}
else
{
printf("SAMPLE_Tlv320aix32x4_CfgAudio(), not support enSample:%d\n",enSample
);
return -1;
}
if(AIO_MODE_I2S_MASTER
== enWorkmode
)
{
audio_ctrl
.interface
.transfer_mode
= AIC32x4_TRANSFER_MODE_I2S
;
audio_ctrl
.interface
.master_slave_mode
= AIC32x4_SLAVE_MODE
;
}
else if(AIO_MODE_I2S_SLAVE
== enWorkmode
)
{
audio_ctrl
.interface
.transfer_mode
= AIC32x4_TRANSFER_MODE_I2S
;
audio_ctrl
.interface
.master_slave_mode
= AIC32x4_MASTER_MODE
;
}
else
{
printf("SAMPLE_Tlv320aic32x4_CfgAudio(), not support workmode:%d\n\n",enWorkmode
);
return -1;
}
s_fdTlv
= open(TLV320_FILE
,O_RDWR
);
if (s_fdTlv
< 0)
{
printf("can't open tlv320aic32x4,%s\n", TLV320_FILE
);
return -1;
}
if (ioctl(s_fdTlv
,SOFT_RESET
,&audio_ctrl
))
{
printf("[Func]:%s [Line]:%d [Info]:%s\n", __FUNCTION__
, __LINE__, "tlv320aic32x4 reset failed");
}
if (ioctl(s_fdTlv
,SAMPLE_RATE
, &audio_ctrl
))
{
printf("[Func]:%s [Line]:%d [Info]:%s\n", __FUNCTION__
, __LINE__, "tlv320aic32x4 set master/slave mode failed");
}
if (ioctl(s_fdTlv
,MASTER_SLAVE_MODE
, &audio_ctrl
))
{
printf("[Func]:%s [Line]:%d [Info]:%s\n", __FUNCTION__
, __LINE__, "tlv320aic32x4 set master/slave mode failed");
}
if (ioctl(s_fdTlv
,TRANSFER_MODE
, &audio_ctrl
))
{
printf("[Func]:%s [Line]:%d [Info]:%s\n", __FUNCTION__
, __LINE__, "tlv320aic32x4 set data transfer mode failed");
}
if(pstAioAttr
->enBitwidth
== AUDIO_BIT_WIDTH_16
)
{
audio_ctrl
.interface
.bit_width
= AIC32x4_BIT_WIDTH_16B
;
audio_ctrl
.interface
.chn_num
= pstAioAttr
->u32ChnCnt
;
if (ioctl(s_fdTlv
,BIT_WIDTH
, &audio_ctrl
))
{
printf("[Func]:%s [Line]:%d [Info]:%s\n", __FUNCTION__
, __LINE__, "tlv320aic32x4 set bitwidth failed");
}
}
else
{
printf("SAMPLE_Tlv320aic32x4_CfgAudio(), just support bitwidth 16bits\n");
return -1;
}
#endif
return 0;
}