Linux驱动. 之I2S或IIS,hisi3521移植的TLV320AIC3101 codex音频源码驱动分析(二)
·
分析hisi soc移植的音频驱动芯片,TLV320AIC3101音频驱动驱动源码。TLV320AIC3101提供了三个文件
tlv320.h
/* extdrv/peripheral/ada/tlv320.h for Linux .
#ifndef _INC_TLV320AIC31
#define _INC_TLV320AIC31
#define IN2LR_2_LEFT_ADC_CTRL 0x0
#define IN2LR_2_RIGTH_ADC_CTRL 0x1
#define IN1L_2_LEFT_ADC_CTRL 0x2
#define IN1R_2_RIGHT_ADC_CTRL 0x3
#define PGAL_2_HPLOUT_VOL_CTRL 0x4
#define PGAR_2_HPLOUT_VOL_CTRL 0x5
#define DACL1_2_HPLOUT_VOL_CTRL 0x6
#define DACR1_2_HPLOUT_VOL_CTRL 0x7
#define HPLOUT_OUTPUT_LEVEL_CTRL 0x8
#define PGAL_2_HPLCOM_VOL_CTRL 0x9
#define PGAR_2_HPLCOM_VOL_CTRL 0xa
#define DACL1_2_HPLCOM_VOL_CTRL 0xb
#define DACR1_2_HPLCOM_VOL_CTRL 0xc
#define HPLCOM_OUTPUT_LEVEL_CTRL 0xd
#define PGAR_2_HPROUT_VOL_CTRL 0xf
#define DACR1_2_HPROUT_VOL_CTRL 0x10
#define HPROUT_OUTPUT_LEVEL_CTRL 0x11
#define PGAR_2_HPRCOM_VOL_CTRL 0x12
#define DACR1_2_HPRCOM_VOL_CTRL 0X13
#define HPRCOM_OUTPUT_LEVEL_CTRL 0x14
#define PGAL_2_LEFT_LOP_VOL_CTRL 0x15
#define DACL1_2_LEFT_LOP_VOL_CTRL 0x16
#define LEFT_LOP_OUTPUT_LEVEL_CTRL 0x17
#define PGAR_2_RIGHT_LOP_VOL_CTRL 0x18
#define DACR1_2_RIGHT_LOP_VOL_CTRL 0x19
#define RIGHT_LOP_OUTPUT_LEVEL_CTRL 0x20
#define SET_ADC_SAMPLE 0x21
#define SET_DAC_SAMPLE 0x22
#define SET_DATA_LENGTH 0x23
#define SET_CTRL_MODE 0x24
#define LEFT_DAC_VOL_CTRL 0x25
#define RIGHT_DAC_VOL_CTRL 0x26
#define LEFT_DAC_POWER_SETUP 0x27
#define RIGHT_DAC_POWER_SETUP 0x28
#define DAC_OUT_SWITCH_CTRL 0x29
#define LEFT_ADC_PGA_CTRL 0x30
#define RIGHT_ADC_PGA_CTRL 0x31
#define TLV320AIC31_REG_DUMP 0x32
#define SOFT_RESET 0x33
#define SET_TRANSFER_MODE 0x34
#define SET_SERIAL_DATA_OFFSET 0X35
/*
0: ADC Fs = Fsref/1 48 44
1: ADC Fs = Fsref/1.5 32
2: ADC Fs = Fsref/2 24 22
3: ADC Fs = Fsref/2.5 20
4: ADC Fs = Fsref/3 16
5: ADC Fs = Fsref/3.5 13.7
6: ADC Fs = Fsref/4 12 11
7: ADC Fs = Fsref/4.5 10.6
8: ADC Fs = Fsref/5 9.6
9: ADC Fs = Fsref/5.5
a: ADC Fs = Fsref / 6 8
*/
#define AC31_SET_8K_SAMPLERATE 0xa
#define AC31_SET_12K_SAMPLERATE 0x6
#define AC31_SET_16K_SAMPLERATE 0x4
#define AC31_SET_24K_SAMPLERATE 0x2
#define AC31_SET_32K_SAMPLERATE 0x1
#define AC31_SET_48K_SAMPLERATE 0x0
#define AC31_SET_11_025K_SAMPLERATE 0x6
#define AC31_SET_22_05K_SAMPLERATE 0x2
#define AC31_SET_44_1K_SAMPLERATE 0x0
#define AC31_SET_SLAVE_MODE 0
#define AC31_SET_MASTER_MODE 1
#define AC31_SET_16BIT_WIDTH 0
#define AC31_SET_20BIT_WIDTH 1
#define AC31_SET_24BIT_WIDTH 2
#define AC31_SET_32BIT_WIDTH 3
typedef enum Audio_In_
{
IN1L =0,
IN1R =1,
IN2L =2,
IN2R =3,
}Audio_In;
typedef enum Audio_Out_
{
LINE_OUT_R=0,
LINE_OUT_L,
HPL,
HPR,
}Audio_Out;
typedef struct
{
unsigned int chip_num:3;
unsigned int audio_in_out:2;
unsigned int if_mute_route:1;
unsigned int if_powerup:1;
unsigned int input_level:7;
unsigned int sample:4;
unsigned int if_44100hz_series:1;
unsigned int data_length:2;
unsigned int ctrl_mode:1;
unsigned int dac_path:2;
unsigned int trans_mode:2;
unsigned int reserved :6;
unsigned int data_offset:8;
unsigned int sampleRate;
}Audio_Ctrl;
#endif
tlv320aic31_def.h
#ifndef _INC_TLV320AIC31_DEF
#define _INC_TLV320AIC31_DEF
typedef union
{
struct
{
unsigned char reserved2 : 4;
unsigned char bit_work_dri_ctrl: 1;
unsigned char reserved1: 1;
unsigned char work_clock_dic_ctrl: 1;
unsigned char bit_clock_dic_ctrl: 1;
} bit;
unsigned char b8;
} Ctrl_Mode;
typedef union
{
struct
{
unsigned char input_vol_level_ctrl: 7;
unsigned char if_mute_route: 1;
} bit;
unsigned char b8;
} Adc_Pga_Dac_Gain_Ctrl;
typedef union
{
struct
{
unsigned char in2r_adc_input_level_sample: 4;
unsigned char in2l_adc_input_level_sample: 4;
} bit;
unsigned char b8;
} In2_Adc_Ctrl_Sample;
typedef union
{
struct
{
unsigned adc_pga_step_ctrl: 2;
unsigned adc_ch_power_ctrl: 1;
unsigned char in1_adc_input_level: 4;
unsigned char mode: 1;
} bit;
unsigned char b8;
} In1_Adc_Ctrl;
typedef union
{
struct
{
unsigned char reserved: 4;
unsigned char data_length: 2;
unsigned char transfer_mode: 2;
} bit;
unsigned char b8;
} Serial_Int_Ctrl;
typedef union
{
struct
{
unsigned char power_status: 1;
unsigned char vol_ctrl_status: 1;
unsigned char power_down_ctrl: 1;
unsigned char if_mute: 1;
unsigned char output_level: 4;
} bit;
unsigned char b8;
} Line_Hpcom_Out_Ctrl;
typedef union
{
struct
{
unsigned char reserved1: 1;
unsigned char right_dac_datapath_ctrl: 2;
unsigned char left_dac_datapath_ctrl: 2;
unsigned char reserved2: 3;
} bit;
unsigned char b8;
} Codec_Datapath_Setup_Ctrl;
typedef union
{
struct
{
unsigned char reserved: 6;
unsigned char right_dac_power_ctrl: 1;
unsigned char left_dac_power_ctrl: 1;
} bit;
unsigned char b8;
} DAC_POWER_CTRL;
typedef union
{
struct
{
unsigned char reserved: 4;
unsigned char right_dac_swi_ctrl: 2;
unsigned char left_dac_swi_ctrl: 2;
} bit;
unsigned char b8;
} DAC_OUTPUT_SWIT_CTRL;
typedef union
{
struct
{
unsigned char serial_data_offset: 8;
} bit;
unsigned char b8;
} Serial_Data_Offset_Ctrl;
#endif
tlv320aic31.c
#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/smp_lock.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%d =%x,", i, tlv320aic31_read(IIC_device_addr[0], i));
if ((i + 1) % 8 == 0)
{
printk("\n");
}
}
}
void soft_reset(unsigned int chip_num)
{
/*soft reset*/
tlv320aic31_write(IIC_device_addr[chip_num], 0x1, 0x80);
msleep(10);
/*CLKDIV_IN uses MCLK*/
tlv320aic31_write(IIC_device_addr[chip_num], 102, 0x32);
#if 1
/*PLL disable and select Q value*/
tlv320aic31_write(IIC_device_addr[chip_num], 3, 0x10);
#else
/*PLL enable */
tlv320aic31_write(IIC_device_addr[chip_num], 3, 0x82);/* P=2 */
tlv320aic31_write(IIC_device_addr[chip_num], 4, 0x1c);/* J=28 */
tlv320aic31_write(IIC_device_addr[chip_num], 5, 0x2c);
tlv320aic31_write(IIC_device_addr[chip_num], 6, 0x8);/* reg 5 and 6 set D=2818*/
tlv320aic31_write(IIC_device_addr[chip_num], 11, 0x1);/* R=1 */
#endif
/*left and right DAC open*/
tlv320aic31_write(IIC_device_addr[chip_num], 7, 0xa);/* FSref = 48 kHz */
/*sample*/
tlv320aic31_write(IIC_device_addr[chip_num], 2, 0xaa);/* FS = FSref/6 */
/*ctrl mode*/
tlv320aic31_write(IIC_device_addr[chip_num], 8, 0xf0);/* master mode */
/*Audio Serial Data Interface Control*/
tlv320aic31_write(IIC_device_addr[chip_num], 9, 0x7);/* I2S mode,16bit */
/*Audio Codec Digital Filter Control Register*/
tlv320aic31_write(IIC_device_addr[chip_num], 12, 0x50);
//tlv320aic31_write(IIC_device_addr[chip_num], 25, 0x0);
tlv320aic31_write(IIC_device_addr[chip_num], 25, 0x40);
tlv320aic31_write(IIC_device_addr[chip_num], 17, 0xf);
tlv320aic31_write(IIC_device_addr[chip_num], 18, 0xf0);
tlv320aic31_write(IIC_device_addr[chip_num], 15, 0x0);
tlv320aic31_write(IIC_device_addr[chip_num], 16, 0x0);
//tlv320aic31_write(IIC_device_addr[chip_num], 19, 0x7c);
//tlv320aic31_write(IIC_device_addr[chip_num], 22, 0x7c);
tlv320aic31_write(IIC_device_addr[chip_num], 19, 0x04);
tlv320aic31_write(IIC_device_addr[chip_num], 22, 0x04);
tlv320aic31_write(IIC_device_addr[chip_num], 28, 0x0);
tlv320aic31_write(IIC_device_addr[chip_num], 31, 0x0);
/*out ac-coupled*/
tlv320aic31_write(IIC_device_addr[chip_num], 14, 0x80);
/*left and right DAC power on*/
tlv320aic31_write(IIC_device_addr[chip_num], 37, 0xc0);
/*out common-mode voltage, DTS2014123002762*/
//tlv320aic31_write(IIC_device_addr[chip_num], 40, 0x80);
/*out path select*/
tlv320aic31_write(IIC_device_addr[chip_num], 41, 0x1);
/*out path select DTS2014123002762 change delay time from 2s to 200ms*/
tlv320aic31_write(IIC_device_addr[chip_num], 42, 0x78);
/*left DAC not muted*/
tlv320aic31_write(IIC_device_addr[chip_num], 43, 0x0);
/*right DAC not muted*/
tlv320aic31_write(IIC_device_addr[chip_num], 44, 0x0);
tlv320aic31_write(IIC_device_addr[chip_num], 47, 0x80);
/*HPLOUT is not muted*/
//tlv320aic31_write(IIC_device_addr[chip_num], 51, 0x04);
tlv320aic31_write(IIC_device_addr[chip_num], 64, 0x80);
/*HPROUT is not muted*/
//tlv320aic31_write(IIC_device_addr[chip_num], 65, 0x9f);
/*out short circuit protection*/
tlv320aic31_write(IIC_device_addr[chip_num], 38, 0x3e);
}
/*
* device open. set counter
*/
static int tlv320aic31_open(struct inode* inode, struct file* file)
{
if (0 == open_cnt++)
{
return 0;
}
return -1 ;
}
/*
* Close device, Do nothing!
*/
static int tlv320aic31_close(struct inode* inode , struct file* file)
{
open_cnt--;
return 0;
}
//static int tlv320aic31_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
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 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);
//printk("set SET_DAC_SAMPLE,audio_ctrl->sample=%x\n",audio_ctrl->sample);
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;
//tlv320aic31_write(IIC_device_addr[chip_num],9,serial_int_ctrl.b8);
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:
//tlv320aic31_write(IIC_device_addr[chip_num],0x1,0x80);
//udelay(50);
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);
/* clock config */
/* aic31, aiao mclk */
switch (audio_ctrl->sampleRate)
{
case 8000:
case 16000:
case 32000:
{
/* 32K series sampling rate */
tlv320aic31_write(IIC_device_addr[chip_num], 3, 0x81); /* P=1 */
tlv320aic31_write(IIC_device_addr[chip_num], 4, 0x30); /* J=12 */
tlv320aic31_write(IIC_device_addr[chip_num], 5, 0x0); /* reg 5 and 6 set D=0000*/
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; /* FSref = 48 kHz */
tlv320aic31_write(IIC_device_addr[chip_num], 7, codec_datapath_setup_ctrl.b8);
tlv320aic31_write(IIC_device_addr[chip_num], 11, 0x1); /* R=1 */
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:
{
/* 48K series sampling rate */
tlv320aic31_write(IIC_device_addr[chip_num], 3, 0x81); /* P=1 */
tlv320aic31_write(IIC_device_addr[chip_num], 4, 0x20); /* J=8 */
tlv320aic31_write(IIC_device_addr[chip_num], 5, 0x0); /* reg 5 and 6 set D=0000*/
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; /* FSref = 48 kHz */
tlv320aic31_write(IIC_device_addr[chip_num], 7, codec_datapath_setup_ctrl.b8);
tlv320aic31_write(IIC_device_addr[chip_num], 11, 0x1); /* R=1 */
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:
{
/* 44.1K series sampling rate */
tlv320aic31_write(IIC_device_addr[chip_num], 3, 0x81); /* P=1 */
tlv320aic31_write(IIC_device_addr[chip_num], 4, 0x20); /* J=7 */
tlv320aic31_write(IIC_device_addr[chip_num], 5, 0x00); /* reg 5 and 6 set D=0000*/
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; /* FSref = 44.1 kHz */
tlv320aic31_write(IIC_device_addr[chip_num], 7, codec_datapath_setup_ctrl.b8);
tlv320aic31_write(IIC_device_addr[chip_num], 11, 0x1); /* R=1 */
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;
}
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:
//printk("[Func]:%s [Line]:%d [Info]:%s\n", __FUNCTION__, __LINE__, "invalid attribute");
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
/*
* The various file operations we support.
*/
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++)
{
/* HPLOUT is mute */
tlv320aic31_write(IIC_device_addr[i], 51, 0x04);
/* HPROUT is mute */
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)
{
/* inite codec configs.*/
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);
/* reboot_notifier */
register_reboot_notifier(&tlv320aic31_reboot_notifier);
return 0;
}
static int tlv320aic31_device_exit(unsigned int num)
{
/* HPLOUT is mute */
tlv320aic31_write(IIC_device_addr[num], 51, 0x04);
/* HPROUT is mute */
tlv320aic31_write(IIC_device_addr[num], 65, 0x04);
return 0;
}
static int i2c_client_init(void)
{
struct i2c_adapter* i2c_adap;
// tlv_aic31 use i2c0
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");
TLV320AIC3101这个芯片商写的驱动,可以看到,非常简单,就是个字符设备,一个字符设备的那一套流程,提供file_opration函数集操作接口,read,write,ioctl设置音频参数。然后套上i2c,i2c驱动的外壳。
static struct file_operations tlv320aic31_fops =
{
.owner = THIS_MODULE,
.unlocked_ioctl = tlv320aic31_ioctl,
.open = tlv320aic31_open,
.release = tlv320aic31_close
};
然后调用音频的驱动框架ALSA,注册到了hisi封装的多媒体框架,himedia_register来注册
填充drvier,如果用hisi的框架,没有就注册到了misc框架
#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
himedia_register注册到hisi的多媒体框架,如果是别家的,源码,是alsa框架接口
#ifdef CONFIG_HISI_SNAPSHOT_BOOT
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设备
static int i2c_client_init(void)
{
struct i2c_adapter* i2c_adap;
// tlv_aic31 use i2c0
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;
}
然后将这两个驱动,提交给内核,注册加载,可以看到,这是老内核提供的一种方法,没有用udev的方式,和dts。因为这个文件非常老,好像是2006年写的了。现在应该是dts,新的方法写的。
static int __init tlv320aic31_init(void)
{
himedia_register(&s_stTlv320aic31Device);
i2c_client_init();
}
module_init(tlv320aic31_init);
更多推荐



所有评论(0)